【实践】Redis 集群搭建

背景

在测试服务器(CentOS 系统)上搭建 Redis 集群,这里一步步实践并整理一些较好的步骤。

正文

简单安装请参照官方文档:Redis Quick Start

  • 前提
  • 搭建
  • 测试
  • 维护

前提

在搭建集群之前,需要明确一下情况。

  • 版本
    目前安装的是 3.2.11 版本,在有些 CentOS 上内置的就是它,所以导致目前项目都用的这个版本。

  • 安装
    默认的编译安装只需要使用 make install 命令,所以依赖的无非是 gccgcc-c++ 这两个编译工具,install 命令也仅仅是将 redis-* 系列拷贝到 /usr/local/bin 目录下。

  • 更正确的配置
    建立 /etc/redis/var/redis 目录,拷贝 redis.conf/etc/redis/6380.conf
    6380.conf 中,bind 设为 192.168.1.57port 设为 6380daemonize 设为 yespidfile 指向 /var/run/redis_6380.pidlogfile 指向 /var/log/redis_6380.logdir 指向 /var/redis/6380

搭建

有了前提条件,接下来就参考官方 Redis Cluster 文档来实践一番。

  • 配置
  • 创建

配置

集群的配置稍微比【更正确的配置】要多一些。

根据 Redis Cluster 以及 redis.conf 中的解释:

  • cluster-enable yes
    yes 表示在特定实例(以此配置文件启动的实例)中启用集群支持;no 表示作为独立实例启动。

  • cluster-config-file nodes.conf
    每个集群节点都有这个配置文件,但用户不能手动编辑内容,它是由节点自己创建和更新。每个节点需要有不同的配置文件,请确保同一个系统中的不同节点,不会覆盖这个配置文件(即:不同的实例,配置文件中的 dir 必须指向不同的目录)。

  • cluster-node-timeout 5000
    集群节点超时是节点在确认失败的状态下,持续不可访问的毫秒总时长,大多数其他内部时间限制是节点超时的倍数。

  • cluster-slave-validity-factor 0
    对于主节点来说,这个因数乘以超时值,表示主节点最终确认故障的时间范围;对于从节点来说,在因数乘以超时值的时间范围内,将不会进行故障转移(成为主节点)。如果因数设为 0,则始终在主节点不可用时进行故障切换,这也是唯一能保证最大可用性的参数。

  • cluster-migration-barrier 1
    默认是1,表示所有主节点在正常状态下,应当保持的从节点数量。比如当前主节点拥有 2 个从节点,另外有个主节点的从节点出现故障,又没有其他从节点可用,此时当前主节点下的一个从节点会自动迁移到另外的主节点下。如果当前主节点只有 1 个从节点,那么将不会进行切换。这个值可以是 0,在调试时可用,但在生产中很危险。

  • cluster-require-full-coverage yes
    yes 是默认情况,表示只要有一个散列槽未被使用(没有节点服务于它),那么集群将不可用;no 表示服务于其他散列槽的节点继续接受查询。

完整的配置参数如下:

bind 192.168.1.57
protected-mode yes
port 6380
tcp-backlog 511
timeout 0
tcp-keepalive 300
daemonize yes
supervised no
pidfile /var/run/redis_6380.pid
loglevel notice
logfile "/var/log/redis_6380.log"
database 16
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
dir /var/redis/6380
slave-serve-stale-data yes
slave-read-only yes
repl-diskless-sync no
repl-diskless-sync-delay 5
repl-disable-tcp-nodelay on
slave-priority 100
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
lua-time-limit 5000
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-slave-validity-factor 0
cluster-migration-barrier 1
cluster-require-full-coverage yes
slowlog-log-slower-than 10000
slowlog-max-len 128
latency-monitor-threshold 0
notify-keyspace-events ""
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-size -2
list-compress-depth 0
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
hll-sparse-max-bytes 3000
activerehashing yes
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
hz 10
aof-rewrite-incremental-fsync yes

创建

为了建立主从模式,将 6380.conf 拷贝一份 6381.conf,然后 修改所有端口相关参数,以及建立相应的 /var/redis/6380/var/redis/6381 目录。

集群的创建需要先启动实例,可以拷贝启动脚本 /usr/local/redis/redis-3.2.11/utils/redis_init_script
/etc/init.d/redis_6380/etc/init.d/redis_6381修改所有相关端口参数 后,再使用 sudo /etc/init.d/redis_6380 start 命令启动实例。

实例启动状态如下:

为了保证集群最小可用性,需要在 192.168.1.127192.168.1.8 上面也启动 63806381 实例。

另外需要安装:

sudo gem install redis

对于 Redis 3.2.11 版本来说,应该安装(否则,会遇到后面【重新分片】的坑):

sudo gem install redis -v 3.3.3

注意:gem 需要 ruby 2.2.2 以上版本,请知悉。

随后使用命令创建集群:

redis-trib.rb create --replicas 1 192.168.1.8:6380 192.168.1.8:6381 192.168.1.127:6380 192.168.1.127:6381 192.168.1.57:6380 192.168.1.57:6381

注意:--replicas 参数表示希望每个主节点都有指定的从节点,这里是 1 个。后面的 IP 地址 + 端口号,就是初始创建的集群列表。

创建成功:

如果多台服务器配置起来很繁琐,可以试着用一下:Redis Cluster 脚本

测试

参考官方文档进行测试。

尝试连接:

redis-cli -c -p 6380

连接失败:

这是集群 bind 了一个局域网地址,需要使用 -h 设置 IP 地址参数:

redis-cli -c -h 192.168.1.8 -p 6380

成功连接:

测试通过:

维护

首先,需要有 2.2.2 以上的 Ruby 环境,然后去 redis-rb-cluster 下载文件:

  • 简单示例 + 重新分片
  • 有趣示例 + 故障转移
  • 其他维护命令

简单示例 + 重新分片

对于 example.rb 文件,需要修改的地方是:

if ARGV.length != 2
        startup_nodes = [
                {:host => "192.168.1.8", :port => 6380},
                {:host => "192.168.1.8", :port => 6381}
        ]
else

然后开始运行 ruby ./example.rb,接着会得到一长串的数字递增,此时可以保留这个窗口。

打开新的窗口,准备重新分片:

redis-trib.rb reshard 192.168.1.8:6380

显示结果:

移动 1000 个哈希槽(建议保持 example.rb 在运行状态):

需要一个目标节点的 ID,这从【显示结果】的图中可以找到:

输入 0471fb34c39dbb9338b56c474f59b3e745a1cc8f 之后,会被询问从哪些节点获取哈希槽:

官方指引输入 all

但我这边 出现错误,那么使用 check 参数检查哪里出了问题:

再按照提示,使用 fix 参数修复问题(我尝试过从编译文件更新 redis-trib.rb 文件):

问题依然存在,自动修复出错。

搜索 错误提示 后,找到:redis cluster3.2.0注意点

登陆客户端:

redis-cli -c -h 192.168.1.8 -p 6380

执行命令:

cluster setslot 5461 stable

效果如图:

再检查一下:

有可能还需要对 192.168.1.127:6380 进行同样的操作:

OK!总算恢复了正常。

再试试在停止 example.rb 脚本的情况下,执行重新分片:

这是从 192.168.1.8 的 主节点 6380 开始,执行 1000 个哈希槽的重新分片,从所有节点转移到 192.168.1.127 的 主节点 6380 中,依然是同样的错误。

说明应该是 redis-trib.rb 脚本出了问题,但我尝试过拷贝相同版本编译后的文件,问题依然得不到解决。

百度不出来什么结果,于是谷歌一下,立即得到答案:

Just installing an earlier version of redis.rb fixes the issue. This worked for me:
gem install redis -v 3.3.3

原问题贴在这里:https://github.com/antirez/redis/issues/4272

执行效果:

那么,我最后再尝试一下 reshard,再不行不搞了。

当然,得先启动 example.rb,得到最佳效果,然后再重新分片:

完美!!!没有出错:

测试一下运行状态:

正如预期的那样,从其他主节点分配总共 1000 个哈希槽到 192.168.1.127 主节点中。

可以将 重新分片 的操作汇合成一条命令:

./redis-trib.rb reshard --from <node-id> --to <node-id> --slots <number of slots> --yes <host>:<port>

有趣示例 + 故障转移

接下来我们运行 consistency-test.rb 来看看一致性问题:

ruby ./consistency-test.rb 192.168.1.8 6380

效果如图:

手动重置计数器:

redis-cli -c -h 192.168.1.8 -p 6380 set key_217 0

并没有出现 114 lost,但我已经不想追究根源,还不如测试一下故障转移:

redis-cli -c -h 192.168.1.8 -p 6380 debug segfault

看到了信息:

现在我们重新启动 192.168.1.8:6380,然后查看集群状态:

可以发现:192.168.1.8:6380 成为新主节点 192.168.1.127:6381 的从节点,原来的从节点 192.168.1.8:6381 成为主节点 192.168.1.127:6380 的从节点(意味着并没有升级为主节点)。

其他维护命令

  • 手动故障转移:cluster failover(需要用 redis-cli 登录从节点)
    通常在没有故障但需要切换主从节点时使用,具体细节参考:cluster-failover
    效果如图:

  • 添加新节点:redis-trib.rb add-node 192.168.1.8:6382 192.168.1.8:6380
    第一个参数是新建立的 Redis 实例,它是一个空节点;第二个参数是集群中任何一个已存在的节点。
    效果如图:


    通过 192.168.1.8:6382 客户端,检查集群:

    提示:空节点已加入集群,但它没有分配哈希槽,因此也没有任何数据,不会被其他从节点选择作为主人。
    可以重新分片,以便重新分配哈希槽,但基本上无用,只是在重新分区。

  • 添加新节点为副本:redis-trib.rb add-node --slave 192.168.1.8:6382 192.168.1.8:6380
    但这是不可能有效的:


    必须要是一个空节点,才能这样做,那已经成为主节点的 192.168.1.8:6382 怎么办?
    可以使用 cluster replicate [id] 来成为目标节点的从节点:

  • 删除节点:redis-trib.rb del-node 192.168.1.8:6380 f049c4f7a81a34f5a66248306f82e6317404b84d
    第一个参数是集群中任何一个节点;第二个参数是需要删除的节点 ID。
    效果如图:


    如果要用这个命令删除主节点,那么此主节点 必须为空,否则就要把它的数据重新分配给所有其他主节点。另外一种办法是使用 cluster replicate [id] 将主节点降级,成为从节点之后,可以继续删除节点。如果你必须减少集群中的主节点数量,那么你应该重新分片,使某些主节点不再拥有哈希槽和数据,然后再删除它们。

  • 副本迁移:cluster replicate [id]
    简单来说,当你不希望某个主节点下的从节点先挂掉,然后主节点相继挂掉,此时集群处于不可用状态(没有挂掉主节点的哈希槽副本),那么你就应该执行这些步骤:

    1. 每个主节点至少分配一个从节点
    2. 额外增加一些从节点,可以是集群中的任意主节点
    3. 所有集群节点的配置参数,cluster-migration-barrier 设为 1,保证迁移功能正常
  • 升级节点:cluster replicate [id]
    同样的命令,但可以做很多事情。概念比较复杂,建议阅读官方文档 Redis Cluster,在此不做误人解释。

  • 迁移群集
    概念比较复杂,建议同上。

总结

Redis 集群比其他 NoSQL 数据库复杂得多,据我所知,CassnadraElasticsearch 只需要修改配置,启动,然后便是正常使用。即使前面以单机形式启动过,也只需要刷新一下系统信息表而已。

复杂的事物总显得高大上,希望后面维护起来会比 CassandraElasticsearch 要轻松很多吧。

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

推荐阅读更多精彩内容