浅谈Redis Cluster

2018-01-19 15:10:04
redis 集群方案概述

自从redis3.0起,redis官方就推出了redis cluster,是一个可以在多个 Redis 节点之间进行数据共享的设施.Redis 集群不支持那些需要同时处理多个键的 Redis 命令, 因为执行这些命令需要在多个 Redis 节点之间移动数据, 并且在高负载的情况下, 这些命令将降低 Redis 集群的性能, 并导致不可预测的行为

当然,也有一些开源的解决方案来提供redis的高可用性,主要有

  • Twitter的Redis/Memcached代理服务Twemproxy
    Twemproxy是一个轻量级的Redis代理服务器,它通过引入一个代理层,将应用程序后端的多台Redis实例进行统一管理,使应用程序只需要在Twemproxy上进行操作,而不用关心后面具体有多少个真实的Redis或Memcached实例,从而实现了基于Redis和Memcached的集群服务。当某个节点宕掉时,Twemproxy可以自动将它从集群中剔除,而当它恢复服务时,Twemproxy也会自动连接。由于是代理,所以Twemproxy会有微小的性能损失。根据 Redis作者的测试结果,在大多数情况下,Twemproxy的性能相当不错,同直接操作Redis相比,最多只有20%的性能损失

  • 豌豆荚的 Redis 集群解决方案Codis
    它由 codis-server、codis-proxy、codis Dashboard、codis Admin、Codis FE、Storage组成,
    基于proxy的codis,客户端对路由表变化无感知。客户端需要从codis dashhoard调用list proxy命令获取所有proxy列表,并根据自身的轮询策略决定访问哪个proxy节点以实现负载均衡,codis release 版本为 codis-3.2,codis-server 基于 redis-3.2.8,同时实现 select 命令,支持多db, 详细介绍参考这里

  • redis_sentinel
    Redis-Sentinel是Redis官方推荐的高可用性(HA)解决方案,当用Redis做Master-slave的高可用方案时,假如master宕机了,Redis本身(包括它的很多客户端)都没有实现自动进行主备切换,而Redis-sentinel本身也是一个独立运行的进程,它能监控多个master-slave集群,发现master宕机后能进行自动切换

  • redis+keepalive
    通过keepalived实现redis的高可用。keepalived利用shell脚本,定期检测redis服务是否正常。当redis服务异常时,利用虚拟IP的漂移实现故障切换

如果你使用的是云平台,会提供类似的产品,有兴趣的请参考这里

redis 集群方案对比

redis_sentinel 和 redis+keepalive 两个方案都是基于redis主从实现,都不是基于分布式的解决方案,前者可以一主多从,后者基本是一主一从。
如果redis写入压力比较大,在碰到网络问题导致闪断切换,redis_sentinel切换需要1-2s的时间,则客户端有可能因此约10w记录无法写入,需要客户端在编码中有异常处理机制,在返回失败是尝试延时重写. keepalive则切换较快,但由于只有一主一从,在读写压力比较大时依然无法满足性能要求,并且在master出现故障,需要人工干预才能重新形成新的主从关系。

codis和twemproxy都是比较稳定的生产集群解决方案,随着官方redis4.x的推出,官方的redis cluster集群也是一个不错的选择方案

redis 集群方案安装

这样主要讲解redis cluster集群的部署,基于redis4.0.6版本。

  • redis_sentinel
    redis_sentinel 的部署配置参考这里

  • redis cluster
    集群部署官方推荐3主3从,这里用两台机器模拟 172.168.10.44 建立3个master,172.168.10.45建立3个slave

  1. install

    1
    2
    3
    4
    5
    cd /usr/local/src
    wget http://download.redis.io/releases/redis-4.0.6.tar.gz
    tar zxf redis-4.0.6.tar.gz
    cd redis-4.0.6
    make
  2. config
    redis cluster 的部署配置参考这里

  3. create cluster

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    # yum install ruby ruby-devel rubygems  -y
    # gem install redis
    #注意master和slave的顺序是一一对应的
    # redis-trib.rb create --replicas 1 192.168.10.44:7000 192.168.10.44:7001 192.168.10.44:7002 192.168.10.45:7003 192.168.10.45:7004 192.168.10.45:7005
    yes

    # redis-cli -h 192.168.10.45 -c -p 7005

    # 查看集群节点情况
    192.168.10.45:7005> cluster info
  4. 新添加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
    # 查看集群节点槽占用情况
    192.168.10.45:7005> cluster nodes

    # 添加7006节点作为新节点
    # ./redis-trib.rb add-node 192.168.10.44:7006 192.168.10.44:7000
    add-node是加入指令,192.168.10.44:7006 表示新加入的节点,
    192.168.10.45:7000 表示加入的集群的一个节点,用来辨识是哪个集群,理论上哪个都可以

    # 给刚添加的7006结点分配槽
    ./redis-trib.rb reshard 192.168.10.44:7006
    ## 第二步:输入要分配的槽数量(输入:500,表示要分配500个槽)
    How many slots do you want to move (from 1 to 16384)? 500

    ## 第三步:输入接收槽的结点id 7006的ID是:065c9c2223949e77f407d20aefa6408aa1bcd181
    What is the receiving node ID? 065c9c2223949e77f407d20aefa6408aa1bcd181
    ## 第四步:输入源结点id(槽点会从源节点中拿,输入all从所有源节点中获取槽,输入done取消分配)
    Please enter all the source node IDs.
    Type 'all' to use all the nodes as source nodes for the hash slots.
    Type 'done' once you entered all the source nodes IDs.
    Source node #1:all
    ## 输入yes开始移动槽到目标结点id
    Do you want to proceed with the proposed reshard plan (yes/no)? yes
    # 查看集群中槽占用情况
    192.168.10.44:7006> cluster nodes
  5. 添加从节点

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    ./redis-trib.rb add-node --slave 192.168.10.45:7007 192.168.10.45:7000
    add-node的时候加上--slave表示是加入到从节点中,但是这样加,是随机的。
    这里的命令行完全像我们在添加一个新主服务器时使用的一样,
    所以我们没有指定要给哪个主服 务器添加副本。
    这种情况下,redis-trib 会将7006作为一个具有较少副本的随机的主服务器的副本

    我如果想指定一个主节点行不行?当然可以。我们再建一个7008节点。
    ./redis-trib.rb add-node –slave –master-id 主节点id 新节点的ip和端口 旧节点ip和端口

    ./redis-trib.rb add-node --slave --master-id 065c9c2223949e77f407d20aefa6408aa1bcd181 192.168.10.45:7008 192.168.10.44:7000
后记

这里推荐个redis集群的运维工具 CacheCloud,有兴趣的可以参考这里
一般影响cluster failover失败有:
(1)从节点超时过长,查看cluster-node-timeout和cluster-slave-validity-factor相关参数
(2)从节点的无法获取到集群中其他主节点的投票
(3)参与领导者选举的主节点不够一半以上
(3)从节点数达不到cluster-migration-barrier数量。
另外,需要注意的是没有负责任何槽的主节点没有投票权

ref
Redis cluster tutorial
Redis集群
Redis集群研究和实践(基于redis 3.0.5)


您的鼓励是我写作最大的动力

俗话说,投资效率是最好的投资。 如果您感觉我的文章质量不错,读后收获很大,预计能为您提高 10% 的工作效率,不妨小额捐助我一下,让我有动力继续写出更多好文章。