JOE'S BLOG

好记性不如烂键盘

0%

分布式系统

分布式系统是由一组通过网络进行通信、为了完成共同的任务而协调工作的计算机节点组成的系统。分布式系统是一个很大的话题,这里仅仅简单介绍下基本概念。

单节点已经无法满足日益增长的计算和存储需求,所以才有了现在各式各样的分布式系统。分布式要解决的问题跟单机系统要解决的问题一样,但由于分布式系统是有多个节点组成,分布在网络的各个节点上,从而引入了单机系统不存在的问题,为了解决这些问题又会引入了各种协议、机制等等。区块链就是一个典型的分布式系统,区块链是由分布式架构与分布式存储、块链式数据结构、点对点网络、共识算法、密码学算法、博弈论、智能合约等多种信息技术共同组成的整体解决方案。

Read more »

前言

使用go时间久了,就会想搞明白go的底层是如何运行的,也就是go runtime的实现原理。本文主要描述了go的启动过程。不过会先从前置知识汇编学起,go runtime涉及了很多汇编知识,而go使用的汇编是plan9汇编,了解完汇编的大概知识再一步步的跟踪go的启动流程。

Read more »

许式伟的架构课

首先,基础架构是业务架构的一部分。不了解基础架构,你就不知道自己写的软件背后都发生了什么,你就无法掌控全局,这对你思考架构演进会有很大的局限性,因为你是 “戴着脚镣跳舞”。

其次,基础架构是最宏大的架构实践案例,需要我们好好感悟。我们不只是要知道基础架构怎么用,还应该理解它为何演变成今天这样。对于优雅的基础架构设计,我们应该要有强烈的共鸣,惊喜赞叹。如果你没有感觉,说明你对架构思维也还没有感觉,也就更不可能构建出极致的架构。

一个架构师需要掌握的三个技能:

  1. 理解代码的能力
  2. 读代码的能力
  3. 抽象系统的能力

架构思维

服务治理

  1. sre 变更是故障之源
  2. 一个完善的监控系统,并不是 “报警很多很完善” 的系统,而是 “信噪比高,有故障就报警,有报警就直指根因” 的监控系统。
  3. 监控的4个指标:延迟、流量、错误和饱和度
  4. 通过采样+汇总可以降低成本
  5. 少就是指数级的多
  6. 灰度发布,减少风险
  7. 针对长期会有风险的故障,需要进行严格的白盒代码审核和全面的覆盖率测试
  8. 日志有助于故障排查
  9. 过载后如何保护系统
  10. 过载如何监控系统,可以基于某个资源的阈值比如CPU,而不仅仅是基于QPS设定

未来服务端技术的演进会走向何方?服务治理系统的迭代,最终将让我们达到这样的状态。

  • 任何业务都可以轻松达到 7x24 小时不间断服务。高并发?高可用?高可靠?小菜一碟。做业务都足够的傻瓜化。
  • 服务端工程师?不存在的,我们要的只是 SQL 工程师。
  • 做一个新的有状态的存储中间件虽然比做业务麻烦一点,但是,一方面也没有多少新的存储中间件需要做的,另一方面做一个存储中间件有足够便捷的辅助设施,也不会比今天做一个内存中的哈希表难多少。

最终软件开发不在区分后端和前端

架构设计

架构设计的基本准则

  • KISS:简单比复杂好;
  • Modularity:着眼于模块而不是框架;
  • Testable:保证可测试性;
  • Orthogonal Decomposition:正交分解。

其中一个评论感觉也非常重要:

其实还有一种耦合度经常被人忽视,就是技术耦合度。我们相信,无论是今天多么流行的技术,未来都有失去竞争力的一天,但要开一家长达数十年甚至数百年的技术公司,不可能长期使用已经失去竞争力的技术,必然涉及到技术的多次演进。如果公司的关键性产品与某一种技术耦合度太高,则当该技术失去竞争力或彻底淘汰后,技术迁移成本过高,极易造成迁移彻底失败。所以我从不看好那种一个 Git 库里数十万甚至数百万行 xx 语言或者基于 xx 框架编写的代码,要起一个新项目还必须去引用这个库里的代码不可,这种项目不可能活很久。如果这个项目是公司的关键性产品,那么这个公司也活不了很久。

  • 比框架(架构图)更重要的是数据结构,比数据结构更重要的是接口。
  • 需求分析->概要设计->模块的详细设计
  • 任何功能都可已做正交分解
  • 核心系统一定要最小化
  • 坚持不要往核心系统增加新功能,这样业务系统就不可能有臭味

开闭原则

架构设计的核心工具

  • 组合,通过小业务组合大业务
  • 开闭原则

开闭原则总结

  • 模块的业务要稳定
  • 对于模块变化的部分,可以通过回调函数或者接口开发出去。复制点的可以通过插件把系统分解

单一职责原则和开闭原则的区别:

  • 单一职责:强调每个模块只负责一个业务
  • 开闭原则:强调把模块业务的变化点抽离出来,包给其他的模块

他们说谈论的其实是同一个问题的两面

接口设计准则

  • 如无必要,勿增实体
  • 对于模块的使用界面,推荐KISS原则
  • 对于模块的依赖,遵循最小依赖原则

软件工程

软件工程

  • 软件工程是快速变化的,不确定的。软件项目的管理又期望达到确定性。这就是软件工程的核心点

软件外包

  • 我们尽可能不要做太多事情。非核心竞争力相关的,能够外包的我们尽可能外包。
  • 在外包选择上,我们优先选择云服务,次选开源,最后才考虑传统的外包。

职业规划

《远见》

  • 我如何避免被机器取代?

  • 我能在哪里以什么方式找到工作?

  • 未来我将如何分配时间?

  • 我会把钱花光吗?

  • 工作如何能让我更幸福?

  • 职业生涯将近40年

  • 精通一门技能所需的时间仅1w小时

  • 40岁之后能赚到个人财富百分比85%以上

  • 社交货币200个左右

  • 职场支持者的人数3, 4个

1
2
3
4
5
6
7
8
9
10
职场燃料之可迁移技能:学术学位、专业证书,语言,优点,情商,“人才账户”。
职场燃料之有意义的经验:个人旅行,海外工作经验,企业管理、创业经验,社区、志愿者活动,做出个人贡献的项目,公开演讲、写作、表演的经验,教学、咨询、指导的经验,工作之余的热情所在……
职场燃料之持久的关系:联系人,专家团,关键同事,支持者。
职场望远镜
THE LONG VIEW
年度职业价值评估问题1:我是否正在学习和成长?
年度职业价值评估问题2:我是否正在对某些人、现在的公司,乃至整个社会拥有影响力?
年度职业价值评估问题3:我体验到乐趣了吗?
年度职业价值评估问题4:我是否得到了适当的奖励,并创造了经济价值?

  • 合理利用时间,是否合适可以使用100小时来进行测试

道德经

什么是道

  • 道的起源

    1
    2
    3
    4
    道可道,非常道;名可名,非常名。
    无名天地之始,有名万物之母。
    故常无欲以观其妙,常有欲以观其徼。
    此两者,同出而异名,同谓之玄。玄之又玄,众妙之门。
  • 物极必反,不停进取

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    原文:
    天下皆知美之为美斯恶矣,皆知善之为善斯不善矣。
    故有无相生,难易相成,长短相较(形),高下相倾,音声相贺,前后相随。
    是以圣人处无为之事,行不言之,教万物作焉而不辞。
    生而不有为而不恃,功成而弗居,夫唯弗居,是以不去。
    注释:
    1.天下皆知美之为美斯恶矣,天下所有的人都知道美好的的事物当时确实很好,但是发现到极致的时候就会出现糟糕的状态。
    2.皆知善之为善斯不善矣,天下人都知道正确好的事物当时是好的,但如果这件事物好到极点那么他就会开始衰败直到最后彻底消亡。
    3.(1)故有无相生,无和有是相伴而生的。眼前拥有的可能在将来某一天就会失去。
    (2)难易相成,难做的事和简单的事总是相辅相成的,很难的事情挺一挺突然间就会容易许多了。
    (3)长短相较,优点和缺点是相对的,反而优点会害了自己,缺点有时候也会救自己。
    (4)高下相倾,高位置的人需要底下人的支持,底下的人也需要高位置人的提拔,高和低的人应该互相团结需要互相依赖的。高的人要谦虚与关爱低的人,低的人要对高的人尊重与配合。
    (5)音声相贺,音代表动听的☞赞扬的,声代表刺耳的☞批评难听的,好听的和难听的是同时存在的
  • 不尚贤不等于忽略人才

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    原文:
    不尚贤使民不争,不贵,难得之货,使民不为盗。
    不限可欲使民心不乱。
    是以圣人之治,虚其心,实其腹,弱其志强其骨。
    常使民无知,无欲使夫,智者不敢为也。
    为无为,则无不治。
    感悟:
    1.不尚贤。尚,单独的。一个人想取得成功就不能够只依赖个别人才,需要依赖的是一个大的团队。
    2.使民不争,不要让老百姓不正当的竞争。
    3.不贵,难得之货,使民不为盗。难得之货,奢侈品。
    不贵,不要过分执迷于这些东西。
    盗,(1)偷盗(2)小人。
    4.不限可欲使民心不乱。一个领导不要把个人的喜好让下级展示,下级就会投其所好,从而使失去了做事的目标和准则。
  • 努力进取

    1
    2
    3
    4
    5
    6
    7
    8
    9
    原文:
    道冲,而用之或不盈。
    渊兮,似万物之宗。
    挫其锐,解其纷,和其光,同其尘。
    湛兮似或存。
    吾不知谁之子,象帝之先。
    感悟:
    不能太过着急追求成功, 遵循道的规律,欲速者不达
    专注做一件事
1
2
3
4
5
6
7
8
9
10
11
12
13
原文:
天地不仁,以万物为刍狗;圣人不仁,以百姓为刍狗。
天地之间,其犹橐籥乎?虚而不屈,动而愈出。
多言数穷,不如守中。
感悟:
人生没有终点,不能只

{{TOC}}

{{TOC}}

搞一件事,不能给自己设限,博学多才
多言数穷
  • 养生

    1
    2
    3
    4
    5
    6
    7
    原文:
    谷神不死,是谓玄牝。
    玄牝之门,是谓天地根。
    绵绵若存,用之不勤。
    感悟:
    不能太累,需要适当的放松,养生
    持之以恒
  • 自私

    1
    2
    3
    4
    5
    6
    7
    8
    原文:
    天长地久。
    天地所以能长且久者,
    以其不自生,故能长生。
    是以圣人后其身而身先,外其身而身存。
    非以其无私邪!故能成其私
    感悟:
    需要考虑自己的利益,需要有一点自私
  • 上善若水

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    原文:
    上善若水。水善利万物而不争,处众人之所恶,故几于道。
    居善地,心善渊,与善仁,言善信,政善治,事善能,动善时。
    夫唯不争,故无尤。
    感悟:
    上善若水,主要说明人要像水一样,水是最接近道的状态
    水最为接近于道:
    居善地(势)
    心善渊(完整深入,心思深邃)
    与善仁(给与别人有利的,关心赞美鼓励欣赏别人)
    言善信(讲话经常讲正确的别人爱听的话守信)
    正善治(正直善良,同时也要灵活解决问题,水也是不好欺负的,大多数情况是利于万物,惹急了也有力量产生海啸和洪水。)
    事善能(可大可小可方可圆,君子不器,以七十二变应变)
    动善时(时机。注意观察,逐步进行,小心投入。第二波成功率更高)
  • 中国文化的核心智慧与目标

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    原文:
    持而盈之,不如其已。
    揣而锐之,不可长保。
    金玉满堂,莫之能守。
    富贵而骄,自遗其咎。
    功遂身退,天之道也。
    感悟:
    持而盈之,不如其已。
    (自满)
    揣而锐之,不可长保。
    (极端,太急)
    金玉满堂,莫之能守。
    (不把自己财富展示给别人太多,不露富,守的财富才更长)
    富贵而骄,自遗其疚。
    (不要骄傲)
    功遂身退,天之道也。
    (功成身退)
  • 道家抱抱的智慧

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    原文:
    载营魄抱一,能无离乎?
    抟气致柔,能如婴儿乎?
    涤除玄览,能无疵乎?
    爱民治国,能无知乎?
    天门开阖,能为雌乎?
    明白四达,能无为乎?
    生之畜之。
    生而不有,为而不恃,长而不宰。
    是谓玄德。
    感悟:
    不仅要关注身体健康,更要关注心理的健康
    专注
  • 无胜过有

    1
    2
    3
    4
    5
    6
    7
    原文:
    三十辐共一毂,当其无,有车之用;
    埏埴以为器,当其无,有器之用;
    凿户牖以为室,当其无,有室之用。
    故有之以为利,无之以为用。
    感悟:
    无才有成长的空间,往更高的地方看,不断为宏伟的未来规划
    1. 老子的肚子和眼睛
      1
      2
      3
      4
      5
      原文:
      五色令人目盲,五音令人耳聋,五味令人口爽,驰骋田猎令人心发狂,
      爽,差失也,失口之用,故谓之爽。夫耳、目、口、心皆顺其性也,不以顺性命反以伤自然,故曰盲、聋、爽,狂也。
      感受:
      针对新出现的事务,不能看以前的经验。尝试新事务的时候要小心翼翼
  • 13 宠辱不经大错特错

1
原文: 
    1. 民不畏死
      1
      民不畏死,奈何以死惧之?若使民常畏死,而为奇者,吾得执而杀之,孰敢?常有司杀者杀。而代司杀者杀,是代大匠斫 。夫代大匠斫者,希有不伤其手矣。
    1. 越努力事情越做不好吗
      1
      民之饥,以其上食税之多,是以饥。民之难治,以其上之有为,是以难治。民之轻死,以其上求生之厚,是以轻死。夫唯无以生为者,是贤于贵生。
    1. 柔弱有时会比强大好
      1
      2
      3
      人之生也柔弱,其死也坚强。万物草木之生也柔弱,其死也枯槁。故坚强者死之徒,柔弱者生之徒。是以兵强则灭,木强则折。强大处下,柔弱处上。
      感受:
      养生,身体是革命的本钱
    1. 为什么圣人功成而不处
1
天之道,其犹张弓乎?高者抑之,下者举之;有余者损之,不足者补之。天之道,损有余而补不足。人之道则不然,损不足以奉有余。孰能以有余奉天下?唯有道者。是以圣人,为而不恃,功成而不处,其不欲见贤耶。
    1. 能受国之垢是谓天下主
      1
      2
      3
      天下莫柔弱于水,而攻坚强者莫之能胜,其无以易[1]之。
      弱之胜强,柔之胜刚,天下莫不知,莫能行。
      是以圣人云:“能受国之垢,是谓社稷主;能受国之不祥,是谓天下王。”正言若反。

Redis核心技术与实战

Redis功能

hyperloglog

用户统计基数的数据集合类型

pfadd 增加计算
pfcount 统计数据

example:
pfadd uv user1
pfcout uv

pfmerge 合并多个值

code:

1
2
3
PFADD page1:uv user1 user2 user3

PFCOUNT page1:uv

布隆过滤器

场景:判断某个值在不在集合中,有误差,比如推荐系统,过滤用户已经看过的新闻

redis命令

添加元素
bf.add news user1

判断是否在集合中
bf.exists news users

添加多个元素
bf.madd news user1 user2 user3

判断多个元素是否在集合中
bf.mexists news user1 user2 user3

redis做消息队列

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
基于List做消息队列
LPUSH 入队,RPOP出队
BRPOP阻塞式读取,可以更省CPU开销
如果读取消息后,redis挂了,可以使用BRPOPLPUSH命名,让消费者程序从一个List中读取消息,同时Redis会把这个图消息再插入到另一个List留存,这样子,redis重启后,就可以从备份的List中读取消息并进行处理

基于Streams的消息队列解决方案
Redis5.0才有
操作命令:
XADD: 插入消息,保证有序,可以自动生成全局唯一ID
XREAD: 用于读取消息,可以按ID读取消息
XREADGROUP: 按消费组形式读取消息
XPENDING和XACK: XPENDING命令可以用来查询每个消费组内所有消费者已读取但尚未确认的消息,XACK命令用于向消息队列确认消息处理已完成

// * 号让系统自动生成id号,也可以自己指定
XADD mqstream * repo 5
"1599203861727-0"



// 从id号开始读取后续的所有数据,block类似BRPOP,阻塞读取,block后面设置的是时间,超过这个时间
// 还没有读取到,则返回空
XREAD BLOCK 100 STREAMS mqstream 1599203861727-0
1) 1) "mqstream"
2) 1) 1) "1599274912765-0"
2) 1) "repo"
2) "3"
2) 1) "1599274925823-0"
2) 1) "repo"
2) "2"
3) 1) "1599274927910-0"
2) 1) "repo"
2) "1"



// $ 表示读取最新的消息
XREAD block 10000 streams mqstream $
(nil)
(10.00s)



Streams的消费组的概念

todo: 消息队列中的消息一旦被消费组里的一个消费者读取了,就不能再被消费组内的其他消费者读取了
// 创建一个group1的消费组, 该消费组的消息队列为mqstream
XGROUP create mqstream group1 0
OK


// 让group1消费组里的消费者consumer1从mqstream中读取所有消息
// ‘>’ 表示从第一条尚未被消费的消息开始读取
127.0.0.1:6379> xreadgroup group group1 consumer1 streams mqstream >
1) 1) "mqstream"
2) 1) 1) "1630813716027-0"
2) 1) "repo"
2) "5"
2) 1) "1630813794727-0"
2) 1) "repo"
2) "2"
3) 1) "1630813797519-0"
2) 1) "repo"
2) "1"
4) 1) "1630814298480-0"
2) 1) "repo1"
2) "1"



// group2中的consumer1,2,3各自读取一条消息
XREADGROUP group group2 consumer1 count 1 streams mqstream >
1) 1) "mqstream"
2) 1) 1) "1599203861727-0"
2) 1) "repo"
2) "5"

XREADGROUP group group2 consumer2 count 1 streams mqstream >
1) 1) "mqstream"
2) 1) 1) "1599274912765-0"
2) 1) "repo"
2) "3"

XREADGROUP group group2 consumer3 count 1 streams mqstream >
1) 1) "mqstream"
2) 1) 1) "1599274925823-0"
2) 1) "repo"
2) "2"


//一旦某一条消息被处理了,消费者就可以使用xack通知Streams把这条消息删除

XACK mqstream group2 1599274912765-0
(integer) 1
XPENDING mqstream group2 - + 10 consumer2
(empty list or set)
```





### 清理内存碎片

查看内存碎片

INFO memory

Memory

used_memory:1073741736
used_memory_human:1024.00M
used_memory_rss:1997159792
used_memory_rss_human:1.86G

mem_fragmentation_ratio:1.86

1
这里有一个 mem_fragmentation_ratio 的指标,它表示的就是 Redis 当前的内存碎片率。那么,这个碎片率是怎么计算的呢?其实,就是上面的命令中的两个指标 used_memory_rss 和 used_memory 相除的结果。

mem_fragmentation_ratio = used_memory_rss/ used_memory

```

首先,Redis 需要启用自动内存碎片清理,可以把 activedefrag 配置项设置为 yes,命令如下:config set activedefrag yes

  • active-defrag-ignore-bytes 100mb:表示内存碎片的字节数达到 100MB 时,开始清理;active-defrag-threshold-lower 10:表示内存碎片空间占操作系统分配给 Redis 的总空间比例达到 10% 时,开始清理。
  • active-defrag-cycle-min 25: 表示自动清理过程所用 CPU 时间的比例不低于 25%,保证清理能正常开展;
  • active-defrag-cycle-max 75:表示自动清理过程所用 CPU 时间的比例不高于 75%,一旦超过,就停止清理,从而避免在清理时,大量的内存拷贝阻塞 Redis,导致响应延迟升高。

缓存区

输入缓冲区溢出:

原因:

  1. 写入了 bigkey,比如一下子写入了多个百万级别的集合类型数据;
  2. 服务器端处理请求的速度过慢,例如,Redis 主线程出现了间歇性阻塞,无法及时处理正常发送的请求,导致客户端发送的请求在缓冲区越积越多。
    解决办法
  3. 调整客户端缓存大小,这个一般是1GB,但是对于一般的生成环境够用了,也没有参数来调整
  4. 避免客户端写入bigkey

输出缓冲区溢出:

原因:

  1. 服务器端返回 bigkey 的大量结果;
  2. 执行了 MONITOR 命令;
  3. 缓冲区大小设置得不合理。

解决办法:

  1. 避免 bigkey 操作返回大量数据结果;
  2. 避免在线上环境中持续使用 MONITOR 命令。
  3. 使用 client-output-buffer-limit 设置合理的缓冲区大小上限,或是缓冲区连续写入时间和写入量上限。

主从复制也会导致缓存区溢出

  1. 控制主节点保存的数据量大小
  2. 设置合理的复制缓存区大小
  3. 控制从节点数量

Redis缓存

Redis用户缓存需要解决如下几个问题:

  1. Redis 缓存具体是怎么工作的?
  2. Redis 缓存如果满了,该怎么办?
  3. 为什么会有缓存一致性、缓存穿透、缓存雪崩、缓存击穿等异常,该如何应对?
  4. Redis 的内存毕竟有限,如果用快速的固态硬盘来保存数据,可以增加缓存的数据量,那么,Redis 缓存可以使用快速固态硬盘吗?

    解决缓存问题

解决缓存不一致

操作顺序 是否有并发请求 潜在问题 现象 应对方案
先删除缓存值,再更新数据库 缓存删除成功,但数据库更新失败 应用从数据库读取到旧数据 重试数据库更新
先删除缓存值,再更新数据库 缓存删除后,尚未更新数据库,有并发读请求 并发请求从数据库读到旧值,并且更新到缓存,导致后续请求都读取旧值 延迟双删除
先更新数据库,再删除缓存 数据库更新成功,但缓存删除失败 应用从缓存读到旧数据 重试缓存删除
先更新数据库,再删除缓存 数据库更新成功后,尚未删除缓存,有并发读请求 并发请求从缓存中读到旧值 等待缓存删除完成,期间会有不一致数据短暂存在

解决缓存雪崩, 缓存击穿,缓存穿透

| 问题 | 原因 | 应对方案 |
|:–|:–|:–|:–|
| 缓存雪崩 | * 大量数据同时过期
* 缓存实例宕机 | 1. 给缓存数据的过期时间加上小的随机数
2. 服务降级
3. 服务熔断
4. 请求限流
5. Redis缓存主从集群 |
|缓存击穿 | 访问非常频繁的热点数据过期 |不给热点数据设置过期时间,一直保留 |
|缓存穿透|缓存和数据库中都没有要访问的数据|1. 缓存空值或缺省值
2. 请使用布隆过滤器快速判断 3. 请求入口前端对请求合法性进行检查|

解决缓存污染问题

那什么是缓存污染呢?在一些场景下,有些数据被访问的次数非常少,甚至只会被访问一次。当这些数据服务完访问请求后,如果还继续留存在缓存中的话,就只会白白占用缓存空间。这种情况,就是缓存污染。

如何解决:
LRU 策略和 LFU 策略

大内存Redis

使用ssd解决大内存Redis问题
https://github.com/OpenAtomFoundation/pika

Redis应对并发

  1. 使用锁
  2. 使用原子操作, Lua脚本

分布式锁

为了避免 Redis 实例故障而导致的锁无法工作的问题,Redis 的开发者 Antirez 提出了分布式锁算法 Redlock。Redlock 算法的基本思路,是让客户端和多个独立的 Redis 实例依次请求加锁,如果客户端能够和半数以上的实例成功地完成加锁操作,那么我们就认为,客户端成功地获得分布式锁了,否则加锁失败。这样一来,即使有单个 Redis 实例发生故障,因为锁变量在其它实例上也有保存,所以,客户端仍然可以正常地进行锁操作,锁变量并不会丢失。

ACID

Redis通过MULTI, EXEC, DISCARD,WATCH四个命令来支持事务机制

命令 作用
MULTI 开启一个事务
EXEC 提交事务,从命令队列中取出提交的操作命令,进行实际执行
DISCARD 放弃一个事务,清空命令队列
WATCH 检测一个或多个键的值在事务执行期间是否发生变化,如果发生变化,那么当前事务放弃执行

Redis 的事务机制可以保证一致性和隔离性,但是无法保证持久性。不过,因为 Redis 本身是内存数据库,持久性并不是一个必须的属性,我们更加关注的还是原子性、一致性和隔离性这三个属性。原子性的情况比较复杂,只有当事务中使用的命令语法有误时,原子性得不到保证,在其它情况下,事务都可以原子性执行。

主从故障

  • 主从数据不一致。Redis 采用的是异步复制,所以无法实现强一致性保证(主从数据时时刻刻保持一致),数据不一致是难以避免的。我给你提供了应对方法:保证良好网络环境,以及使用程序监控从库复制进度,一旦从库复制进度超过阈值,不让客户端连接从库。
  • 对于读到过期数据,这是可以提前规避的,一个方法是,使用 Redis 3.2 及以上版本;另外,你也可以使用 EXPIREAT/PEXPIREAT 命令设置过期时间,避免从库上的数据过期时间滞后。不过,这里有个地方需要注意下,因为 EXPIREAT/PEXPIREAT 设置的是时间点,所以,主从节点上的时钟要保持一致,具体的做法是,让主从节点和相同的 NTP 服务器(时间服务器)进行时钟同步。

脑裂

所谓的脑裂,就是指在主从集群中,同时有两个主节点,它们都能接收写请求。而脑裂最直接的影响,就是客户端不知道应该往哪个主节点写入数据,结果就是不同的客户端会往不同的主节点上写入数据。而且,严重的话,脑裂会进一步导致数据丢失。

  • min-slaves-to-write:这个配置项设置了主库能进行数据同步的最少从库数量;
  • min-slaves-max-lag:这个配置项设置了主从库间进行数据复制时,从库给主库发送 ACK 消息的最大延迟(以秒为单位)。

假设我们将 min-slaves-to-write 设置为 1,把 min-slaves-max-lag 设置为 12s,把哨兵的 down-after-milliseconds 设置为 10s,主库因为某些原因卡住了 15s,导致哨兵判断主库客观下线,开始进行主从切换。同时,因为原主库卡住了 15s,没有一个从库能和原主库在 12s 内进行数据复制,原主库也无法接收客户端请求了。这样一来,主从切换完成后,也只有新主库能接收请求,不会发生脑裂,也就不会发生数据丢失的问题了。

网络整体概览

网络程序体系结构

超时

一个http的生命周期中的各个阶段的超时

http超时

简介

本文将从context->http->gin的路线全面吃透go web开发

context

要理解go web开发我认为首先离不开的就是context, 同时context也是最适合用来学习go源码的一个包

几种ctx的简介

  1. emptyCtx: 所有ctx的根,用context.TODO(), context.Background()生成
  2. valueCtx: 在ctx中存储kv数据,同一个ctx只能存储一个kv数据, 更多的kv数据构造了一个树形结构
  3. cancelCtx: 可以用来取消程序的执行树, 父级取消会依次通知下级取消所有的ctx, 也是最为核心实现最复杂的一个ctx
  4. timerCtx: 基于cancelCtx,基于支持时间的cancel

context的核心接口,有以下几个方法, 上面的几个ctx也都是围绕该接口实现和扩展的

1
2
3
4
5
6
7
8
// Context's methods may be called by multiple goroutines simultaneously.
type Context interface {
Deadline() (deadline time.Time, ok bool)
Done() <-chan struct{}
Err() error
Value(key any) any
}

Read more »