Redis-Cluster 关键点测试

本篇主要针对可能会出现的异常情况。

一、与集群相关操作

在运维过程中,尤其是修复故障集群中,需要熟练掌握使用。
比如以下几种情况,都需要手动在线上紧急操作,做集群恢复:
1) 扩容缩容时,发生网络分区,两个分区节点数一样,造成无法投票。
2) 迁移时,目标节点发生宕机,导致各个节点管理的键空间分布不一致。
3 )集群中大部分节点不可用。

1. Redis提供测cluster集群元操作

http://www.redis.cn/commands/cluster-setslot.html

image.png

2.redis-cli提供的集合操作

image.png

二、与集群相关的配置

1、cluster-enabled <yes/no>:
如果想在特定的Redis实例中启用Redis群集支持就设置为yes。 
否则,实例通常作为独立实例启动。

2、cluster-config-file <filename>:
这不是用户可编辑的配置文件,而是Redis群集节点每次发生更改时自动保留群集配置(基本上为状态)的文件,
以便能够在启动时重新读取它。 
文件列出了集群中各个节点的键空间分布以及集群本次和最近一次的epoch。 
update集群信息时,通常会将此文件重写并刷新到磁盘上。

3、cluster-node-timeout <milliseconds>:
Redis群集节点间超过此时间通信失败,则会将对方设置为pfail。 
这个值会影响故障切换耗时。

4、cluster-slave-validity-factor <factor>:
如果设置为0,无论主和从之间的链路保持断开连接的时间长短,从都将尝试故障切换。 
如果该值为正值,则计算最大断开时间作为节点超时值乘以此选项提供的系数,
如果该节点是从,则在主断开连接的时间超过指定的超时值时,它不会尝试启动故障切换。 
例如,如果节点超时设置为5秒,并且有效因子设置为10,
则与主设备断开连接超过50秒的从将不会尝试对其主进行故障切换。 
如果没有从服务器节点能够对其进行故障转移,
则任何非零值都可能导致Redis群集在主服务器出现故障后不可用。 
在这种情况下,只有主节点重新加入集群时,集群才会返回可用。

5、cluster-migration-barrier <count>:
主将保持连接的最小从数量。

6、cluster-require-full-coverage <yes/no>:
如果将其设置为yes,则默认情况下,任何一个slot不可用,集群停止接受写入。 
如果该选项设置为no,群集在大多数主节点可用时,仍将提供查询。

在下面的测试中,将设置cluster-require-full-coverage no、cluster-node-timeout 15000。

三、异常测试

通过命令构建集群

./redis-cli --cluster create   127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 
127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 --cluster-replicas 

构建完成后如下:集群包含3主3从


image.png

1、Redis Cluster可用性测试

1)单个slot不可用

集群仍可用。但当cluster-require-full-coverage yes,集群将不可用。

2)某个master和它的slave不可达

shutdwon 从实例7000
shutdwon 从实例7000的主实例7005
此时集群依然处于可用状态cluster_state:ok。


image.png

3)大部分节点不可用

shutdwon 主实例7000
shutdwon 主实例7000的从7004
shutdwon 主实例7001

唯一存活的主节点为7002,大约过了15~16s,实例7002发现整个集群不可用,设置自己的集群状态cluster_state:fail。
因为是大部分节点不可用,所以不会发生投票将pfail状态的节点设置为fail。7002主要是依靠ping超时(超时的节点设置为pfail),直到累积超时的节点超过(server.cluster->size / 2) + 1,则可判断整个集群不可用。
也就是说当大部分节点不可用,发现集群不可用至少为15s。

image.png

日志:


image.png

其中投票数的计算:
needed_quorum = (server.cluster->size / 2) + 1;
其中server.cluster->size 是通过cluster meet命令到集群中的主节点数之和。

假设集群为6主6从,那么needed_quorum=4。此时发生网络分区,两边集群拥有的节点数都是3个,那么就会导致集群不可用。设置为奇数,就不会出现类似的情况。所以将节点数设置为奇数比偶数,可用性更高。
同时在扩容缩容时,如果发生网络分区,是非常容易出现无法投票情况。此时就需要手动修复(整个修复方案还得仔细想想,不然很容易造成数据丢失)。

接着我们设想一下3)中的7002是由于网络分区,与集群大部分节点断连。那么也是15s之后,它才会拒绝客户端的写操作。15s内写入的数据将会全部丢失。
Redis 集群在拥有少数主节点和至少一个客户端的分区上,是容易丢失为数不少的写入操作。这其实是非常危险的,后面在主从复制切换丢失数据中,尝试提出一些方案来解决。

2、迁移过程中异常测试

1)迁移过程中,目标节点shutdown

执行:

redis-cli --cluster-from 72ef6eb3a168788dfa25033672118aafdfb27259 
--cluster-to b646070182a9ec51fb8663658e5b816ea9ae09af 
--cluster-slots 5461

将slot 0-5460从节点7005迁移到7003(7001为7003的从)。
执行 :

redis-cli -p 7003 shutdown

shutdown 主节点7003
此时迁移到slot 1084


image.png

7001提升为主,管理slot:5461-10922
各个节点标识的7005和7001键空间分布


image.png

统计一下:


image.png

由上面可以看出:
键空间分布式是很杂乱的。
由于7005是迁移的源节点,从它的键空间分布,我们可以得出。0-1083肯定是已经迁移出去,正在迁移1084的过程中被中断。
7002,7004,7005都更改了slot的分布,但是7003的从节点7001和7000,并未更新。导致集群键空间分布不一致。
此时集群虽然是可用的,但实际存在部分slot不能被访问的情况。

接着我们重启节点7003,各个节点的键空间分布一致。但是此时出现4个master,所以要恢复3主3从模式,还需要做手动维护。
如果在7003发生宕机事故,则需要使用cluster setslot强制将438-1083指向7001。


image.png

2)迁移过程中,源节点shutdown

执行:

redis-cli -p 7004 --cluster reshard 127.0.0.1:7004  --cluster-from cc2559271dcb9ffcd0c5bfe655e46736d6b78271 --cluster-to 2eef2e210a7a8bec4287904ae4c570b5c25e4a1a --cluster-slots 5462

将slot 0-5460从节点7005迁移到7003。
执行 :

redis-cli -p 7005 shutdown 

关掉源节点7005。
通过cluster nodes查看键空间分布如下,键空间分布集群各个节点是一致的。


image.png

此时也需要通过setslot来修复。

我们注意到,迁移的时候,shutdown源节点与目标测试结果是不一致的。只有弄清楚这个问题,才好修复故障。
迁移一个槽的元命令见文档:https://moji.wemomo.com/doc#/detail/84254
迁移的最后一步CLUSTER SETSLOT <slot> NODE <destination-node-id>源或着目标。。
测试使用的是集成命令--cluster reshard做迁移,具体在Redis-cli.c中实现,CLUSTER SETSLOT <slot> NODE是在目标源上操作的。所以shutdown目标节点,会造成这个修改无法同步到其他节点。

image.png

迁移过程是一个挺复杂的过程。在其中发生宕机很容易造成集群部分slot不可用,出现各种情况,修复起来也不一样。
修复错误,很有可能发生丢失数据的情况。
最好还是能理解整个流程,知道如何做正确的修复。

3. 主从集群切丢失数据

在上文中的迁移和分区故障中都提及的数据丢失都是与主从有关。

1) 异步复制导致的丢失

手动故障切换(默认)是只有当从库和主库数据一致才能进行故障切换。
但自动故障中,切换的从是根据Rank选出的,是会造成数据丢失。

从节点在确认主节点failover 之后 , DELAY = 500 milliseconds + random delay between 0 and 500 milliseconds +
SLAVE_RANK * 1000 milliseconds.
才会发起选举。

固定延时500ms,是为了留出时间,使主节点下线的消息能传播到集群中其他节点,这样集群中的主节点才有可能投票。随机延时是为了避免两个从节点同时开始故障转移流程。rank表示从节点的排名,排名是指当前从节点在下线主节点的所有从节点中的排名,排名主要是根据复制数据量来定,复制数据量越多,排名越靠前,因此,具有较多复制数据量的从节点可以更早发起故障转移流程,从而更可能成为新的主节点。
在redis的配置文件中有个参数我们可以设置:
min-slaves-max-lag 10
min-slaves-max-lag默认情况下是10。
以上面配置为例,这两个参数表示salve的与master的同步复制延迟不能超过10s,一旦所有的slave复制和同步的延迟达到了10s,那么此时master就不会接受任何请求。
就可以减小min-slaves-max-lag参数的值,这样就可以避免在发生故障时大量的数据丢失,一旦发现延迟超过了该值就不会往master中写入数据。
同时对于client,可以暂时将数据写入缓存或者磁盘,等redis恢复继续往里面写入。

2) 集群分区导致的丢失

Redis 集群在拥有少数主节点和至少一个客户端的分区上,最少15s才能发现自己是不可写的,那么至少在15s的写入操作都将被丢弃。
(可以想下,这块毕竟丢失数据比较多。目前没有什么好的想法。)

4.gossip通信

1) 集群间通信流量

为了支持1000节点规模的集群,在通信上作者做了相关优化。

a)每个节点1s向一个节点发送gossip信息,这个gossip只携带至少3个至多1/10个其他节点的信息。

每个gossip信息大小为sizeof(clusterMsg)-sizeof(union clusterMsgData) = 4352 - 2096 = 2256,大概2kb。


image.png
b)向server.cluster_node_timeout/2未接受到pong的节点发送gossip信息,同样这个gossip只携带至少3个至多1/10个其他节点的信息。

每个节点信息大小104 Byte


image.png

当集群较小时,发送的a)类消息占大多数。集群较大时,发送b)类信息占大多数。
一个700节点的集群通信带宽占 107.5MBit / s,这是非常可观的开销。这也是超大规模集群面临的问题。

2)gossip机制下判断主节点时效到传播到大部分节点,到底需要花多久时间。

1)某节点发现A节点不可达,并设置为pfail状态 :至少cluster_node_timeout
2)大多数节点发现A不可达:至多需要cluster_node_timeout/2(超过这个时间,一定会发送b)类消息)
3)接受大多数节点pfail,设置改节点fail。按 a)类传播,最大需要6s。
4)将 fail 状态发送到大部分节点。按 a)类传播,大概率需要6s

所以大概估算一下:
cluster_node_timeout + cluster_node_timeout/2 + 12s 大概率可以做自动故障切换。
至少也要等待
cluster_node_timeout + DELAY 时间才会发生故障切换。
这段时间业务是无法访问的。
DELAY = 500 milliseconds + random delay between 0 and 500 milliseconds + SLAVE_RANK * 1000 milliseconds.

总结

1.如果说Redis本身就是不适合做存储的,那么Redis Cluster在这个上面更是打折扣。尤其是不适合存储一些重要数据。
2.Redis Cluster中需要手动恢复的故障较多,需要熟练掌握细节并尽量自动化。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,137评论 6 511
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,824评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,465评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,131评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,140评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,895评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,535评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,435评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,952评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,081评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,210评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,896评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,552评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,089评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,198评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,531评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,209评论 2 357