Redis实战总结-Redis的高可用性

在之前的博客《Redis实战总结-配置、持久化、复制》给出了一种Redis主从复制机制,简单地实现了Redis高可用。然后,如果Master服务器宕机,会导致整个Redis瘫痪,这种方式的高可用性较低。正常会采用多台Redis服务器构成一个集群,即使某台,或者某几台Redis宕机,Redis集群仍能正常运行,从而提高其高可用性。

在Redis中,主要存在两种方式实现Redis集群机制:

  • Redis Sentinel集群机制:在Redis2.X版本,往往都是通过这种方式实现Redis的高可用。redis-sentinel是在master-slave机制上加入监控机制哨兵Sentinel实现的。

  • Redis Cluster集群机制:在Redis3.0版本后推出了redis-cluster集群机制。redis-cluster集群中各个节点之间是对等的,即master-master模式。

**注意:**Redis Sentinel集群是解决HA问题的(主从同步),Redis Cluster集群是解决sharding问题的(分区),两种不重复,可以混合使用。

下面详解这两种集群,并给出具体的演示示例。

1. Redis Sentinel集群机制

Redis-Sentinel是在master-slave机制上加入监控机制哨兵Sentinel实现的。Sentinel主要功能就是为Redis Master-Slave集群提供:

  • 监控(Monitoring): Sentinel 会不断地检查你的主服务器和从服务器是否运作正常。
  • 提醒(Notification): 当被监控的某个 Redis 服务器出现问题时, Sentinel 可以通过 API 向管理员或者其他应用程序发送通知。
  • 自动故障迁移(Automatic failover): 当一个主服务器不能正常工作时, Sentinel 会开始一次自动故障迁移操作, 它会将失效主服务器的其中一个从服务器升级为新的主服务器, 并让失效主服务器的其他从服务器改为复制新的主服务器; 当客户端试图连接失效的主服务器时, 集群也会向客户端返回新主服务器的地址, 使得集群可以使用新主服务器代替失效服务器。

在Sentinel集群中,一个最小的Master-Slave单元包含一个master和一个slave服务器。当master失效后,sentinel自动将slave提升为master,从而可以减少管理员的人工切换slave的操作过程。

1.1 Redis-Sentinel集群架构图

1.2 各个机器配置

部署在本地机器上,保证各个端口号不一样,具体配置如下

  • Redis服务器:

    • master:127.0.0.1:6379
    • slave01:127.0.0.1:6389
    • slave02:127.0.0.1:6399
  • Sentinel服务器

    • sentinel01:127.0.0.1:26379
    • sentinel02:127.0.0.1:26389
    • sentinel03:127.0.0.1:26399

1.3 redis.conf和sentinel.conf配置

  • redis.conf

    • master特殊配置如下:
    
    # 后台线程启动
    
    daemonize yes
    
    # 监听端口号
    
    port 6379
    
    # 访问验证密码
    
    requirepass "123456"
    • slave特殊配置如下:
    
    # 后台线程启动
    
    daemonize yes
    
    # 监听端口号,如果为slave02,端口号为6399
    
    port 6389
    
    # 主节点访问密码
    
    masterauth "123456"
    
    # 访问验证密码
    
    requirepass "123456"
    
    # 主节点服务器IP和端口号
    
    slaveof 127.0.0.1 6379
  • sentinel.conf

# 后台线程启动
daemonize yes
# 监听端口号,如果为sentinel02,则端口号为26389,如果为sentinel01,则端口号为26399
port 26379
#1表示在sentinel集群中只要有两个节点检测到redis主节点出故障就进行切换   
sentinel monitor mymaster 127.0.0.1 6379 1
# master节点密码验证
sentinel auth-pass mymaster 123456
#如果3秒内mymaster无响应,则认为mymaster宕机了
sentinel down-after-milliseconds mymaster 3000
# 选项指定了在执行故障转移时, 最多可以有多少个从服务器同时对新的主服务器进行同步, 这个数字越小, 完成故障转移所需的时间就越长
sentinel parallel-syncs mymaster 1
#如果10秒后,mysater仍没活过来,则启动failover 
sentinel failover-timeout mymaster 10000

注意:

  • 1.如果上述涉及的所有配置均放置在同一目录下,需保证各配置名称不同;
  • 2.在配置中,不同实例的日志输出、快照文件要求名称不能一样,具体可自行配置;
  • 3.一定要保证”sentinel myid”不相同,否则无法进行故障转移

1.4 启动集群及启动后结果详情展示

  • 各Redis节点启动:

    redis-server redis_****.conf
  • 各Sentinel节点启动

    redis-sentinel sentinel_*****.conf
  • Redis Master节点详情展示
  •  

Redis Slave节点效果截图展示 

各个Sentinel节点详情展示 

1.5 高可用性场景测试

  • Master宕机 

  • sentinel使用failover机制重新选举出master
  • Master恢复 

  • master节点恢复后,由Master变成slave
  • Slave宕机 

  • 哨兵发现6399已经宕机,等待6399的恢复(主观下线)
  • Slave重启6399节点 

如果想详细了解sentinel机制的话,可以参考博客: 
http://shift-alt-ctrl.iteye.com/blog/1884370

2. Redis Cluster集群机制

2.1 Redis-cluster介绍

Redis-cluster是一种服务器Sharding技术,Redis3.0以后版本正式提供支持。

Redis-cluster没有使用一致性hash,而是引入了哈希槽的概念。Redis-cluster中有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽。Cluster中的每个节点负责一部分hash槽(hash slot),比如集群中存在三个节点,则可能存在的一种分配如下:

  • 节点A包含0到5500号哈希槽;
  • 节点B包含5501到11000号哈希槽;
  • 节点C包含11001 到 16384号哈希槽。

这种集群架构很容易扩展,如果扩充一个节点D,只需要将A、B、C节点中的部分槽放置在D上;如果想移除节点A,只需要将A的slot转移到B和C节点上。由于将哈希槽从一个节点移动到另一个节点不需要停止服务,只需要通过命令直接再分配,因而上述拓展不会造成集群不可用。目前这种方式还是一种半自动的方式,需要人工介入。

2.2 Redis-Cluster主从复制

在Redis-Cluster中,如果某个节点宕机或者处在不可用状态时,那它负责的Hash槽也将失效,导致整个集群不可用。因而为了提供高可用性,正常会将每个节点配置成主从式结构,即一个master节点,挂在多个slave节点。如果Master节点失效时,集群便会选取一个slave节点作为master,继续提供服务,从而不会导致整个集群不可用。

2.3 Redis-Cluster集群模拟

2.3.1 Redis-Cluster集群准备

  • 集群部署图 

  • 集群由三个节点组成,每个节点均为主从式架构。因而共需要创建6个Redis实例,分配如下:

    • Redis01:127.0.0.1:7000
    • Redis02:127.0.0.1:7001
    • Redis03:127.0.0.1:7002
    • Redis04:127.0.0.1:7003
    • Redis05:127.0.0.1:7004
    • Redis06:127.0.0.1:7005

    对于每个实例的redis_700*.conf配置如下:

    # 监听端口号
    port 700*
    # 开启集群
    cluster-enabled yes
    # 修改集群加载配置文件,不需要手动创建,启动后默认生成,并且需要时自动更新
    cluster-config-file /Users/guweiyu/develop/redis/redis-cluster/workpid/nodes-7000.conf
    # 集群中的节点能够失联的最大时间,超过这个时间,该节点就会被认为故障
    cluster-node-timeout 15000
    # 默认为“no”,表示部分Key所在的节点不可用时,集群仍然为可达节点提供服务;如果为“yes”,表示部分key所在的节点不可用时,则整个集群停止服务。注意:实际使用中要修改为"yes"
    cluster-require-full-coverage no
  • 安装ruby,如果为Mac OS系统,直接执行即可:

    brew install ruby

2.3.2 集群启动

  • 启动所有Redis实例,可以编写一个启动和停止所有redis实例的脚本(start.sh,stop.sh)

    redis-server redis_7000.conf
    redis-server redis_7001.conf
    redis-server redis_7002.conf
    redis-server redis_7003.conf
    redis-server redis_7004.conf
    redis-server redis_7005.conf
    
    ps -ef | grep redis-server
    echo "redis 7000-7005全部启动完成"
  • redis-cli -p 7000 shutdown
    redis-cli -p 7001 shutdown
    redis-cli -p 7002 shutdown
    redis-cli -p 7003 shutdown
    redis-cli -p 7004 shutdown
    redis-cli -p 7005 shutdown
    
    ps -ef | grep redis-server
    echo "redis-server 7000-7005节点已全部停止"
  • 1创建redis-cluster

Redis中创建集群是通过redis-trib.rb命令实现的,redis-trib.rb位于Redis源码的src目录下,可将其直接拷贝到当前目录下。

运行命令

./redis-trib.rb create --replicas 1 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

如果出现如下错误:

/System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require': cannot load such file -- redis (LoadError)
    from /System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require'
    from ./redis-trib.rb:25:in `<main>'

这是由于没有安装redis的第三方接口导致的。因此需要给Ruby安装client包,如下(必须加上sudo执行,否则会执行失败):

sudo gem install redis

再执行创建集群命令,结果如下:

>>> Creating cluster
>>> Performing hash slots allocation on 6 nodes...
Using 3 masters:
127.0.0.1:7000
127.0.0.1:7001
127.0.0.1:7002
Adding replica 127.0.0.1:7004 to 127.0.0.1:7000
Adding replica 127.0.0.1:7005 to 127.0.0.1:7001
Adding replica 127.0.0.1:7003 to 127.0.0.1:7002
>>> Trying to optimize slaves allocation for anti-affinity
[WARNING] Some slaves are in the same host as their master
M: aab0162a039d2f224322afe6caf2e153230f2d82 127.0.0.1:7000
   slots:0-5460 (5461 slots) master
M: 058204226f52757925a606b9697a8e39756bfdff 127.0.0.1:7001
   slots:5461-10922 (5462 slots) master
M: 857075aef280cf35cd369ebc30738cd31c05e479 127.0.0.1:7002
   slots:10923-16383 (5461 slots) master
S: 7dac141fa9510315905f505be52bba0208c391ab 127.0.0.1:7003
   replicates aab0162a039d2f224322afe6caf2e153230f2d82
S: 65a2bc432e5930e97f0fd172eb838af9f07229b6 127.0.0.1:7004
   replicates 058204226f52757925a606b9697a8e39756bfdff
S: 3d2a665d2e2eb28acb0a187c1a0b4bbce9ce87d2 127.0.0.1:7005
   replicates 857075aef280cf35cd369ebc30738cd31c05e479
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join...
>>> Performing Cluster Check (using node 127.0.0.1:7000)
M: aab0162a039d2f224322afe6caf2e153230f2d82 127.0.0.1:7000
   slots:0-5460 (5461 slots) master
   1 additional replica(s)
S: 3d2a665d2e2eb28acb0a187c1a0b4bbce9ce87d2 127.0.0.1:7005
   slots: (0 slots) slave
   replicates 857075aef280cf35cd369ebc30738cd31c05e479
S: 65a2bc432e5930e97f0fd172eb838af9f07229b6 127.0.0.1:7004
   slots: (0 slots) slave
   replicates 058204226f52757925a606b9697a8e39756bfdff
S: 7dac141fa9510315905f505be52bba0208c391ab 127.0.0.1:7003
   slots: (0 slots) slave
   replicates aab0162a039d2f224322afe6caf2e153230f2d82
M: 857075aef280cf35cd369ebc30738cd31c05e479 127.0.0.1:7002
   slots:10923-16383 (5461 slots) master
   1 additional replica(s)
M: 058204226f52757925a606b9697a8e39756bfdff 127.0.0.1:7001
   slots:5461-10922 (5462 slots) master
   1 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.

创建成功,16384个Hash槽分配完成,所有节点(Master和slave节点)均已加入到集群中。三个Master节点分配的Hash槽及从节点如下:

  • Master01:127.0.0.1:7000

    M: aab0162a039d2f224322afe6caf2e153230f2d82 
    slots:0-5460 (5461 slots) master
    127.0.0.1:7004 to 127.0.0.1:7000
  • Master02:127.0.0.1:7001
  • M: 058204226f52757925a606b9697a8e39756bfdff 
    slots:5461-10922 (5462 slots) master
    127.0.0.1:7005 to 127.0.0.1:7001
  • Master03:127.0.0.1:7002
  • M: 857075aef280cf35cd369ebc30738cd31c05e479 
    slots:10923-16383 (5461 slots) master
    127.0.0.1:7003 to 127.0.0.1:7002

2.3.3 集群测试

  • 测试集群存取值

客户端命令redis-cli连接集群需要带上”-c”, 比如redis-cli -c -p 端口号

127.0.0.1:7000> set test1 guweiyu
OK
127.0.0.1:7000> set name  guweiyu
-> Redirected to slot [5798] located at 127.0.0.1:7001
OK
127.0.0.1:7001> get name
"guweiyu"
127.0.0.1:7001> get test1
-> Redirected to slot [4768] located at 127.0.0.1:7000
"guweiyu"
127.0.0.1:7000>

测试发现”set test1 guweiyu”,直接返回OK,说明该值就是存储在7000上,执行“set name guweiyu”发生了Redirected到7001上,获取的时候,同样出现上述情况。这个是Redis Cluster去中心特性,访问集群中的任一节点,均可直接操作集群。

  • 主节点宕机测试

  • 从节点宕机

原文地址:https://www.cnblogs.com/austinspark-jessylu/p/8960961.html