Redis 运维实战 第02期:Redis Cluster

Redis 最为突出的特性就是:执行命令的速度非常快(原因是所有数据都存放在内存中)。但是单机 Redis 总会遇到瓶颈的,比如:并发、流量、内存等。在 Redis 3.0 之前,官方并没有提供集群方案,在访问量比较大的情况,基本使用的是 Twemproxy、Codis 等集群方案。直到 Redis 3.0,官方推出了 Redis Cluster,实现了切片集群方案。今天就来聊聊 Redis Cluster。

1 虚拟槽

Redis Cluster 采用虚拟槽分区,一个集群有 16384 个虚拟槽,这些虚拟槽类似数据分区,每个键值对都会根据它的 key,按照 CRC16 算法计算一个 16bit 的值,然后再用这个 16bit 的值对 16384 取模,通过模映射到一个虚拟槽中。

Redis Cluster 使用虚拟槽,可以解耦数据和节点之间的关系,大大简化了节点扩缩容的难度,并且重要的是扩缩容不影响数据一致性

2 集群搭建

2.1 安装 Redis

安装 6 个 Redis 实例(本节的版本为:5.0.7,6 个实例在同一台 Centos7 上部署的,端口分配是:7001 到 7006),Redis 安装可以参考官方文档(https://redis.io/download)。

2.2 修改配置文件

在 Redis 的配置文件中,加入如下参数,开启 Redis 集群功能。

cluster-enabled yes

cluster-config-file /data/redis{port}/data/nodes{port}.conf

cluster-node-timeout 5000

简单介绍上面三个参数的含义:

cluster-enabled:是否开启集群模式

cluster-config-file:集群内部配置文件

cluster-node-timeout:节点超时时间,单位毫秒

2.3 创建集群

部署 Redis Cluster 方案时,可以使用 cluster create 命令创建集群,此时,Redis 会自动把这些槽平均分布在集群实例上。

当然,如果想自定义每个实例的槽分配,也可以使用 cluster meet 命令手动建立实例间的连接,形成集群,再使用 cluster addslots 命令,指定每个实例上的哈希槽个数(比如集群中配置不统一的场景)。要注意的是,在手动分配哈希槽时,需要把 16384 个槽都分配完,否则 Redis 集群无法正常工作。

本节内容就只讲使用 cluster create 命令创建集群的过程。

首先执行集群创建命令:

redis-cli --cluster create 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 127.0.0.1:7006 --cluster-replicas 1

这里的 --cluster-replicas 1 表示每个主节点都分配一个从节点,如果为 2,则表示每个主节点分配两个从节点。

生产环境也建议至少配置一个从节点。

如图,在下方输入 yes 确认

出现如下信息,则表示集群创建完毕

查看集群状态

redis-cli --cluster check 127.0.0.1:7001

可以看到,槽位分配和主从配置已经自动完成。

3 扩缩容

3.1 扩容

继续安装两个 Redis 节点 7007 和 7008,然后按照 2.2 的方式在配置文件中加入集群相关参数。

增加节点,命令如下:

redis-cli --cluster add-node 127.0.0.1:7007 127.0.0.1:7001

127.0.0.1:7007 表示新增节点

127.0.0.1:7001 表示集群中任意节点

查看集群状态

redis-cli --cluster check 127.0.0.1:7001

发现 127.0.0.1:7007 已经加入到集群中了

再添加从节点:

redis-cli --cluster add-node 127.0.0.1:7008 127.0.0.1:7001 --cluster-slave --cluster-master-id c9d5817021fe802c094806a79c3c52a37b8b15f5

查看集群状态

redis-cli --cluster check 127.0.0.1:7001

如图,框中的就是新增加的一组主从。

然后进行槽迁移

redis-cli --cluster reshard 127.0.0.1:7001

在最后一行,显示要分配多少槽

How many slots do you want to move (from 1 to 16384)?

因为扩容后是 4 个主实例,因此这个位置输入 4096,表示每个实例分配 4096 个槽

随后会出现

其中:

What is the receiving node ID?  

这里输入新增节点 7007 的 node-id

Source node #1:

这里输入 all,表示所有节点平均分配

或者手动输入 node-id 分配,然后输入 done 结束

查看集群状态

redis-cli --cluster check 127.0.0.1:7001

发现会从每个老节点上抽取一些槽,转移到新的节点上。

3.2 缩容

如果需要进行缩容,首先要下线缩容节点的槽,执行以下命令,可以将 7007 节点上的 1364 个槽转移到 7001 节点上

redis-cli --cluster reshard --cluster-from c9d5817021fe802c094806a79c3c52a37b8b15f5 --cluster-to 99d09213eab4bd707e4923d6574182e23384b765 --cluster-slots 1364 127.0.0.1 7001

按照同样的方式,将其余的槽迁移到 7002 和 7003 两个节点。

查看集群信息,发现 7007 节点没任何槽了

然后删除节点

redis-cli --cluster del-node  127.0.0.1:7001 c9d5817021fe802c094806a79c3c52a37b8b15f5

该操作会将删除的节点服务关闭。

同样的办法,把从节点也删除

redis-cli --cluster del-node  127.0.0.1:7001 81d26724de7961a22a93cf64901a68b40c1f90cd

4 数据迁移

其实,Redis Cluster 在进行类似上面的扩缩容操作时,客户端依然可以进行数据改查,那么 Redis Cluster 是怎样实现这一动态扩缩容特性的呢?

这里就来聊聊 Redis Cluster 的迁移原理:

比如需要将 masterA 节点中编号为 1、2、3 的 slot 迁移到 masterB 节点上,在slot 迁移的中间状态,slot 1、2、3 在 masterA 节点的状态表现为 MIGRATING 状态,在 masterB 节点的状态表现为 IMPORTING。

4.1 MIGRATING 状态

如果 key 存在,则成功处理

如果 key 不存在,则返回客户端 ASK,客户端根据 ASK 首先发送 ASKING 命令到目标节点,然后发送请求的命令到目标节点。

假如 key 包含多个命令,如果都存在,则成功处理,如果都不存在,则返回客户端 ASK,如果一部分存在,则返回客户端 TRYAGAIN,通知客户端稍后重试,这样当所有的 key 都迁移完毕的时候,客户端重试请求的时候会得到 ASK,然后经过一次重定向就可以获取这一批键了。

4.2 IMPORTING 状态

正常命令会被 MOVED 重定向,如果是 ASKING 命令,则命令会被执行,从而 key 没在被迁移的节点,已经被迁移到目标节点的情况命令可以被顺利执行;如果 key 不存在,则新建;如果 key 不在该节点上,命令会被 MOVED 重定向,刷新客户端中 node 的映射关系。

5 节点通信

为什么客户端在访问任何一个实例时,都能获得其他槽的数据呢?

因为 Redis 实例会把自己的虚拟槽信息发给同集群下的其它实例,当集群创建完成后,每个实例就有所有哈希槽的映射关系了。

6 故障检测

集群中的每个节点都会定期的向集群中其他节点发送 ping 消息,以此交换各个节点状态信息。

7 集群优势

这里再总结下 Redis cluster 的一些优势

无中心架构

动态扩缩容:如本节内容,Redis 可支持动态扩缩容

高可用性:部分节点不可用时,集群仍可用

8 集群限制

Redis Cluster 与 Redis 单机版相比,存在一些限制,我们在运维或者开发过程,应该提前了解的,这里就总结几点限制:

key 批量操作支持有限。如 mset、mget,目前只支持具有相同 slot 值的 key 执行批量操作。

只支持多 key 在同一个节点上的事务操作

不能将一个大的键值对象如 hash、list 等映射到不同的节点

只支持 db 0

复制结构只支持一层

9 Redis Cluster 建议

尽量避免大 key、热 key,因为这可能导致某一个节点成为系统的短板。

不建议使用事务、避免使用阻塞操作(比如 save、flushall、keys * 等)



欢迎加入 Redis 交流社群

群内不定期邀请一些身边的 Redis 大牛

交流分享,解答工作中遇到的的问题

分享工作经验、面试技巧等!加vx:yzlkf09

也欢迎各位大牛投稿,内容可以是数据库、开发、运维、产品、运营等!

悦专栏  LIKECOLUMN 

在这里,学好编程

做更优秀的 IT人!

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

推荐阅读更多精彩内容