美文网首页
【实践】Redis 集群搭建

【实践】Redis 集群搭建

作者: mrzhqiang | 来源:发表于2018-07-11 15:54 被阅读0次

    背景

    在测试服务器(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 要轻松很多吧。

    相关文章

      网友评论

          本文标题:【实践】Redis 集群搭建

          本文链接:https://www.haomeiwen.com/subject/zgzxpftx.html