Redis想必大家都或多或少有点了解,一个开源的内存数据库,支持持久化,支持各种过期策略,可以用作缓存,消息代理。

像一些Redis安装的细节在这里就不说了,这里主要总结一下,Redis运行的几种模式,这里有参考一些其他文章,参考的文章我会在文章结尾贴上链接。

Redis支持单实例运行,主从复制,以及基于主从复制的哨兵模式,以及集群模式。

在单实例下,若节点失败,则服务无法从redis获取数据,如果开启了主从复制,则在master节点失败后可以手动把slave节点切换为master节点,当然这中间会有一定的时间间隔。

在哨兵模式下,sentinel会监控master和slave的健康状况,当master节点失败后,sentinel会发起选举,重新选择一个master节点,这样新的master节点自动上线,不需要人工干预。

在集群模式下,数据会被分散到多个不同的节点,从而解决一个节点数据量过大的问题。

下面所有的测试都是基于一台电脑上,最多使用多个端口(测试用)。

 

单实例

单实例就是启动一台服务器,相信不需要多说什么:

redis-server /path/to/config.conf

默认情况下,监听地址127.0.0.1, 端口6379,database 16个,启用RDB持久化。

 

主从复制

配置主从复制,一个master,多个slave。默认情况下master可读可写,slave只可读不可写。

编辑master配置文件:

redis.conf

bind 127.0.0.1
port 6379
daemonize yes

将原来的配置文件复制一份,然后编辑配置文件:

redis-slave.conf

bind 127.0.0.1
port 6380
replicaof 127.0.0.1 6379
daemonize yes

分别启动master和slave节点:

redis-server redis.conf
redis-server redis-slave.conf

连接master节点添加数据:

redis-cli -p 6379
set a 1

连接slave节点获取数据:

redis-cli -p 6380
get a

应该可以见到数据在此slave节点上是存在的,因为主从配置是有效的。

 

哨兵模式

Redis的哨兵模式(sentinel)为redis提供了高可用性,它可以自动从某个节点失败中恢复过来而不需要人工干预。

Redis哨兵模式宏观上提供了以下几种能力:

  • 监控(Monitoring): 持续监控redis实例是否是可用的
  • 提供(Notification): 当某个redis实例失败后,sentinel可以通知系统管理员,或者调调用指定系统程序。
  • 自动故障转移(Automatic failover): 当master节点失败后,Sentinel启动故障转移, 选举某个slave为新的master,并且配置其他的slave节点使用新的master节点。应用程序再次连接的时候会被告知新的master节点的地址。
  • 配置提供(Configuration provider): 提供master节点的地址。master失败后提供新的master地址。

关于哨兵模式,有几点需要注意的地方:

  1. 配置文件是必须的,如果没有配置文件,redis无法启动哨兵模式。因为Sentinel需要在重启的时候保存当前状态,重启完成后恢复状态。
  2. 需要至少三个Sentinel实例,这样使系统更加健壮。
  3. 哨兵模式需要客户端库的支持,大多数流行的redis库都支持哨兵模式,但不是所有的都支持。

这里为了演示,只用1个master, 2个slave, 1个sentinel。

Redis.conf

bind 127.0.0.1
port 6379
daemonize yes

Redis-slave-01.conf

bind 127.0.0.1
port 6380
daemonize yes
replicaof 127.0.0.1 6379

Redis-slave-02.conf

bind 127.0.0.1
port 6381
daemonize yes
replicaof 127.0.0.1 6379

Redis-sentinel.conf

bind 127.0.0.1
port 26379
daemonize yes
sentinel monitor mymaster 127.0.0.1 6379 1

然后启动master, slave, sentinel

redis-server redis.conf
redis-server redis-slave-01.conf
redis-server redis-slave-02.conf
redis-server redis-sentinel.conf

 

首先查看当前master的地址(mymaster是sentinel配置文件中默认的master名称)

redis-cli -p 26379 sentinel get-master-addr-by-name mymaster
1) "127.0.0.1"
2) "6379"

可见master地址是127.0.0.1:6379,接下来模拟master失败的情景,让master睡眠1分钟:

redis-cli -p 6379 debug sleep 60

然后查看当前master的地址:

redis-cli -p 26379 sentinel get-master-addr-by-name mymaster
1) "127.0.0.1"
2) "6380"

可见地址变成了127.0.0.1:6380.

通过sentinel控制台的输出也能看到结果:

8989:X 31 May 2020 15:31:27.540 # +try-failover master mymaster 127.0.0.1 6379
8989:X 31 May 2020 15:31:27.543 # +vote-for-leader 453f7858cac7017fde75a3b3f806150248aedd99 1
8989:X 31 May 2020 15:31:27.543 # +elected-leader master mymaster 127.0.0.1 6379
8989:X 31 May 2020 15:31:27.543 # +failover-state-select-slave master mymaster 127.0.0.1 6379
8989:X 31 May 2020 15:31:27.631 # +selected-slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
8989:X 31 May 2020 15:31:27.631 * +failover-state-send-slaveof-noone slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
8989:X 31 May 2020 15:31:27.733 * +failover-state-wait-promotion slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
8989:X 31 May 2020 15:31:28.152 # +promoted-slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
8989:X 31 May 2020 15:31:28.152 # +failover-state-reconf-slaves master mymaster 127.0.0.1 6379
8989:X 31 May 2020 15:31:28.226 * +slave-reconf-sent slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
8989:X 31 May 2020 15:31:29.202 * +slave-reconf-inprog slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
8989:X 31 May 2020 15:31:29.202 * +slave-reconf-done slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
8989:X 31 May 2020 15:31:29.270 # +failover-end master mymaster 127.0.0.1 6379
8989:X 31 May 2020 15:31:29.270 # +switch-master mymaster 127.0.0.1 6379 127.0.0.1 6380

好了,这就是Sentinel的功能实现。

 

集群模式

Redis Cluster提供了一种可以自动把数据分散到多个Redis实例的实现方式。Redis Cluster提供了一定程度的高可用性,当小部分节点失败后,正常工作的节点仍然可以提供服务,但是当大部分的master节点失败后就不能提供服务了。

Redis Cluster需要使用两个TCP端口,一个是正常的数据端口,比如6379,另一个是数据端口加10000,比如数据端口时6379, 则另一个端口是16379,16379端口主要是为了Cluster之间的通信,使用二进制协议进行通信。其中,数据端口和Cluster端口的偏移值是固定的10000。

Redis Cluster使用哈希槽(hash slot)的而不是一致性哈希(consistent hashing)来实现数据分片。

为了在一部分master节点失败后维持可用性,Redis Cluster使用master-slave的模型,每个哈希槽可以有1(master节点)个或多个备份。当master节点失败后,Cluster会选举备份节点为新的master。

那么如何创建集群模式?

这里我们创建6个节点,3个master, 3个slave,首先创建一个master节点

port 7000
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes

然后启动此节点

redis-server redis-01.conf

然后其次启动其他五个节点,记得替换port的值和cluster-config-file的值,cluster-config-file的值也不允许重复,否则会报错Sorry, the cluster configuration file nodes.conf is already used by a different Redis Cluster node. Please make sure that different nodes use different cluster configuration files..

同时记得注释掉replaceof,否则会报错replicaof directive not allowed in cluster mode.

然后创建集群

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

出现Can I set the above configuration? (type 'yes' to accept)时输yes回车即可。

然后连到第一个master节点:

redis-cli -p 7000

查看集群信息

127.0.0.1:7000> cluster nodes
2719a4e524741a07cbddd1fa4b0fb659b7793de0 127.0.0.1:7002@17002 master - 0 1590920566507 3 connected 10923-16383
94eb8c60334014670a4c8fef4fe7d25b8269c8f7 127.0.0.1:7000@17000 myself,master - 0 1590920565000 1 connected 0-5460
71b2d00856c40f830b31a91c50d5e1454f093735 127.0.0.1:7003@17003 slave 4342388d50c1506151c91620730401e4516a1857 0 1590920565592 4 connected
e87c97aa5530b96144ab410e83956b0b0685cbe8 127.0.0.1:7005@17005 slave 94eb8c60334014670a4c8fef4fe7d25b8269c8f7 0 1590920566506 6 connected
3dbee1fce0156b3be7886743b4abaa0eadeee01f 127.0.0.1:7004@17004 slave 2719a4e524741a07cbddd1fa4b0fb659b7793de0 0 1590920565999 5 connected
4342388d50c1506151c91620730401e4516a1857 127.0.0.1:7001@17001 master - 0 1590920567518 2 connected 5461-10922

可见六个节点都在。

接下来set值试下:

127.0.0.1:7000> set a 1
(error) MOVED 15495 127.0.0.1:7002
127.0.0.1:7000> set b 3
OK

第一个a报错MOVED是因为它计算出来应该存储在127.0.0.1:7002这个实例上,当然这些如果使用了redis库,它们会帮我们自动处理的。

接下来模拟master失败,首先查看当前集群中节点信息:

127.0.0.1:7000> cluster nodes
2719a4e524741a07cbddd1fa4b0fb659b7793de0 127.0.0.1:7002@17002 master - 0 1590922745650 3 connected 10923-16383
94eb8c60334014670a4c8fef4fe7d25b8269c8f7 127.0.0.1:7000@17000 myself,master - 0 1590922744000 1 connected 0-5460
71b2d00856c40f830b31a91c50d5e1454f093735 127.0.0.1:7003@17003 slave 4342388d50c1506151c91620730401e4516a1857 0 1590922745000 4 connected
e87c97aa5530b96144ab410e83956b0b0685cbe8 127.0.0.1:7005@17005 slave 94eb8c60334014670a4c8fef4fe7d25b8269c8f7 0 1590922745145 6 connected
3dbee1fce0156b3be7886743b4abaa0eadeee01f 127.0.0.1:7004@17004 slave 2719a4e524741a07cbddd1fa4b0fb659b7793de0 0 1590922746158 5 connected
4342388d50c1506151c91620730401e4516a1857 127.0.0.1:7001@17001 master - 0 1590922745550 2 connected 5461-10922

可见7000端口的redis实例是master, 而7005端口的实例时7000端口的slave,让7000端口的redis睡眠:

redis-cli -p 7000 debug sleep 60

查看集群节点信息:

127.0.0.1:7001> cluster nodes
e87c97aa5530b96144ab410e83956b0b0685cbe8 127.0.0.1:7005@17005 master - 0 1590922885542 7 connected 0-5460
71b2d00856c40f830b31a91c50d5e1454f093735 127.0.0.1:7003@17003 slave 4342388d50c1506151c91620730401e4516a1857 0 1590922884530 4 connected
2719a4e524741a07cbddd1fa4b0fb659b7793de0 127.0.0.1:7002@17002 master - 0 1590922884530 3 connected 10923-16383
94eb8c60334014670a4c8fef4fe7d25b8269c8f7 127.0.0.1:7000@17000 master,fail - 1590922851081 1590922849000 1 connected
3dbee1fce0156b3be7886743b4abaa0eadeee01f 127.0.0.1:7004@17004 slave 2719a4e524741a07cbddd1fa4b0fb659b7793de0 0 1590922885037 5 connected
4342388d50c1506151c91620730401e4516a1857 127.0.0.1:7001@17001 myself,master - 0 1590922884000 2 connected 5461-10922

显示7000端口的redis已下线,而7005端口的实例变成了新的master。

当1分钟过去7000端口的redis睡眠时间过去重新加入集群后就变成了7005端口的slave

127.0.0.1:7001> cluster nodes
e87c97aa5530b96144ab410e83956b0b0685cbe8 127.0.0.1:7005@17005 master - 0 1590922923000 7 connected 0-5460
71b2d00856c40f830b31a91c50d5e1454f093735 127.0.0.1:7003@17003 slave 4342388d50c1506151c91620730401e4516a1857 0 1590922923000 4 connected
2719a4e524741a07cbddd1fa4b0fb659b7793de0 127.0.0.1:7002@17002 master - 0 1590922923083 3 connected 10923-16383
94eb8c60334014670a4c8fef4fe7d25b8269c8f7 127.0.0.1:7000@17000 slave e87c97aa5530b96144ab410e83956b0b0685cbe8 0 1590922922000 7 connected
3dbee1fce0156b3be7886743b4abaa0eadeee01f 127.0.0.1:7004@17004 slave 2719a4e524741a07cbddd1fa4b0fb659b7793de0 0 1590922924099 5 connected
4342388d50c1506151c91620730401e4516a1857 127.0.0.1:7001@17001 myself,master - 0 1590922921000 2 connected 5461-10922

好了,这就是所有内容了,关于和SpringBoot集成的配置,等有时间可能会补充到这里。