Redis主从复制和集群搭建

Redis 主从复制

主从复制,是指将一台 Redis 服务器的数据,复制到其他的 Redis 服务器。前者称为主节点(master/leader),后者称为从节点(slave/follower);数据的复制是单向的,只能由主节点到从节点。Master 以写为主,Slave 以读为主。

Redis主从复制和集群搭建_第1张图片

默认情况下,每台 Redis 服务器都是主节点;且一个主节点可以有多个从节点(或没有从节点),但一个从节点只能有一个主节点。

主从复制的作用

  1. **数据冗余:**主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。
  2. **故障恢复:**当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复;实际上是一种服务的冗余。
  3. **负载均衡:**在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务(即写Redis数据时应用连接主节点,读Redis数据时应用连接从节点),分担服务器负载;尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高 Redis 服务器的并发量。
  4. **高可用基石:**除了上述作用以外,主从复制还是哨兵和集群能够实施的基础,因此说主从复制是 Redis 高可用的基础。

一般来说,要将 Redis 运用于工程项目中,只使用一台 Redis 是万万不能的,原因如下:

  1. 从结构上,单个 Redis 服务器会发生单点故障,并且一台服务器需要处理所有的请求负载,压力较大;
  2. 从容量上,单个 Redis 服务器内存容量有限,就算一台 Redis 服务器内存容量为256G,也不能将所有
    内存用作 Redis 存储内存,一般来说,单台 Redis 最大使用内存不应该超过20G。

主从复制的配置

1、拷贝多个 redis.conf 文件(配置主从复制,至少需要三个,一主二从)

[root@iZwz98zi7ua638a1dxozhyZ myredis]# ll
total 84
-rw-r--r-- 1 root root 83393 Aug 16 21:04 redis.conf
[root@iZwz98zi7ua638a1dxozhyZ myredis]# cp redis.conf redis6379.conf 
[root@iZwz98zi7ua638a1dxozhyZ myredis]# cp redis.conf redis6380.conf 
[root@iZwz98zi7ua638a1dxozhyZ myredis]# cp redis.conf redis6381.conf 
[root@iZwz98zi7ua638a1dxozhyZ myredis]# ll
total 336
-rw-r--r-- 1 root root 83393 Aug 22 13:19 redis6379.conf
-rw-r--r-- 1 root root 83393 Aug 22 13:19 redis6380.conf
-rw-r--r-- 1 root root 83393 Aug 22 13:20 redis6381.conf
-rw-r--r-- 1 root root 83393 Aug 16 21:04 redis.conf

2、三个配置文件需要修改的参数

redis6379.conf

port 6379
pidfile /var/run/redis_6379.pid
dbfilename dump6379.rdb

redis6380.conf

port 6380
pidfile /var/run/redis_6380.pid
dbfilename dump6380.rdb

redis6381.conf

port 6381
pidfile /var/run/redis_6381.pid
dbfilename dump6381.rdb

3、启动三个 redis 服务进程

# ============================================================
# 启动 redis6379 服务器
# ============================================================
[root@iZwz98zi7ua638a1dxozhyZ bin]# redis-server myredis/redis6379.conf 
21602:C 22 Aug 2021 13:43:39.870 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
21602:C 22 Aug 2021 13:43:39.870 # Redis version=6.0.6, bits=64, commit=00000000, modified=0, pid=21602, just started
21602:C 22 Aug 2021 13:43:39.870 # Configuration loaded

# ============================================================
# 启动 redis6380 服务器
# ============================================================
[root@iZwz98zi7ua638a1dxozhyZ bin]# redis-server myredis/redis6380.conf
21604:C 22 Aug 2021 13:44:05.034 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
21604:C 22 Aug 2021 13:44:05.034 # Redis version=6.0.6, bits=64, commit=00000000, modified=0, pid=21604, just started
21604:C 22 Aug 2021 13:44:05.034 # Configuration loaded

# ============================================================
# 启动 redis6381 服务器
# ============================================================
[root@iZwz98zi7ua638a1dxozhyZ bin]# redis-server myredis/redis6381.conf
21610:C 22 Aug 2021 13:44:18.583 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
21610:C 22 Aug 2021 13:44:18.583 # Redis version=6.0.6, bits=64, commit=00000000, modified=0, pid=21610, just started
21610:C 22 Aug 2021 13:44:18.583 # Configuration loaded

# ============================================================
# 查看 redis 服务进程信息
# ============================================================
[root@iZwz98zi7ua638a1dxozhyZ myredis]# ps -ef | grep redis
root     20370     1  0 Aug21 ?        00:00:58 redis-server 127.0.0.1:6379
root     21605     1  0 13:44 ?        00:00:00 redis-server 127.0.0.1:6380
root     21611     1  0 13:44 ?        00:00:00 redis-server 127.0.0.1:6381
root     21617 21471  0 13:49 pts/0    00:00:00 grep --color=auto redis

一主二仆

Redis主从复制和集群搭建_第2张图片

默认情况下,每台 Redis 服务器都是主节点,我们一般情况下只需要配置从机就好。

通过 slaveof 命令设置成为某个实例的从服务器

# ============================================================
# 配置 redis6380 服务器为从节点
# ============================================================
[root@iZwz98zi7ua638a1dxozhyZ bin]# redis-cli -p 6380
127.0.0.1:6380> slaveof 127.0.0.1 6379
OK
127.0.0.1:6380> info replication
# Replication
role:slave # 角色为从节点
master_host:127.0.0.1
master_port:6379
master_link_status:up
master_last_io_seconds_ago:3
master_sync_in_progress:0
slave_repl_offset:0
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:0a4a78af9e712f2525bc684f2db4c70f5f7afa7e
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:0

# ============================================================
# 配置 redis6381 服务器为从节点
# ============================================================
[root@iZwz98zi7ua638a1dxozhyZ bin]# redis-cli -p 6381
127.0.0.1:6381> slaveof 127.0.0.1 6379
OK
127.0.0.1:6381> info replication
# Replication
role:slave # 角色为从节点
master_host:127.0.0.1
master_port:6379
master_link_status:up
master_last_io_seconds_ago:1
master_sync_in_progress:0
slave_repl_offset:70
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:0a4a78af9e712f2525bc684f2db4c70f5f7afa7e
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:70
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:57
repl_backlog_histlen:14

# ============================================================
# 查看主节点 redis6379 服务器的信息
# ============================================================
[root@iZwz98zi7ua638a1dxozhyZ bin]# redis-cli -p 6379
127.0.0.1:6379> info replication
# Replication
role:master # 角色为主节点
connected_slaves:2 # 有两个从机
slave0:ip=127.0.0.1,port=6380,state=online,offset=112,lag=0
slave1:ip=127.0.0.1,port=6381,state=online,offset=112,lag=1
master_replid:0a4a78af9e712f2525bc684f2db4c70f5f7afa7e
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:112
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:112

上面的主从配置使用的是命令,只是暂时的,真实的主从配置应该再文件中配置,这样的话就是永久的。

注意:只有主机可以写入数据,从机不能写只能读,主机中的所有信息和数据,都会自动被从机保存。

如果主机断开连接,从机依旧连接到主机的,但是没有写操作,主机如果重新连接,从机依旧可以直接获取到主机写的数据。

如果从机断开连接,从机如果重启了,就会变回主机,就要再次设置为从机,立马就会从主机中获取数据。

薪火相传

在这里插入图片描述

上一个 Slave 可以是下一个 slave 的 Master,Slave 同样可以接收其他 slaves 的连接和同步请求,那么该 slave 作为了链条中下一个的 master, 可以有效减轻 master 的写压力,去中心化降低风险。

反客为主

一主二从的情况下,如果主机断了,从机可以使用命令 SLAVEOF NO ONE 将自己改为主机!这个时候其余的从机链接到这个节点。对一个从属服务器执行命令 SLAVEOF NO ONE 将使得这个从属服务器关闭复制功能,并从从属服务器转变回主服务器,原来同步所得的数据集不会被丢弃。主机再回来,也只是一个光杆司令了,从机为了正常使用跑到了新的主机上。

复制原理

Slave 启动成功连接到 master 后会发送一个 sync 命令。

Master 接到命令,启动后台的存盘进程,同时收集所有接收到的用于修改数据集命令,在后台进程执行。

完毕之后,master 将传送整个数据文件到 slave,并完成一次完全同步。

全量复制:而 slave 服务在接收到数据库文件数据后,将其存盘并加载到内存中。

增量复制:Master 继续将新的所有收集到的修改命令依次传给 slave,完成同步。

但是只要是重新连接 master,一次完全同步(全量复制)将被自动执行。

哨兵模式(sentinel)

主从切换技术的方法是:当主服务器宕机后,需要手动把一台从服务器切换为主服务器,这就需要人工干预,费事费力,还会造成一段时间内服务不可用。这不是一种推荐的方式,更多时候,我们优先考虑哨兵模式。Redis 从 2.8 开始正式提供了 Sentinel(哨兵) 架构来解决这个问题。

反客为主的自动版,能够后台监控主机是否故障,如果故障了根据投票数自动将从库转换为主库。

Redis主从复制和集群搭建_第3张图片

哨兵模式是一种特殊的模式,首先 Redis 提供了哨兵的命令,哨兵是一个独立的进程,作为进程,它会独立运行。其原理是哨兵通过发送命令,等待 Redis 服务器响应,从而监控运行的多个 Redis 实例。当哨兵监测 master 宕机,会自动将 slave 切换成 master,然后通过发布订阅模式通知其他的从服务器,修改配置文件,让它们切换主机。

Redis主从复制和集群搭建_第4张图片

哨兵模式的配置

1、自定义的 /myredis 目录下新建 sentinel.conf 文件(名字绝不能错)

[root@iZwz98zi7ua638a1dxozhyZ myredis]# touch sentinel.conf
[root@iZwz98zi7ua638a1dxozhyZ myredis]# ll
total 336
-rw-r--r-- 1 root root 83397 Aug 22 13:32 redis6379.conf
-rw-r--r-- 1 root root 83398 Aug 22 13:35 redis6380.conf
-rw-r--r-- 1 root root 83397 Aug 22 13:35 redis6381.conf
-rw-r--r-- 1 root root 83393 Aug 16 21:04 redis.conf
-rw-r--r-- 1 root root     0 Aug 22 15:00 sentinel.conf

2、配置哨兵,往 sentinel.conf 文件写入内容

# sentinel monitor 被监控的名称 host port 1(至少有多少个哨兵同意迁移的数量)
sentinel monitor myredis 127.0.0.1 6379 1

3、启动哨兵

[root@iZwz98zi7ua638a1dxozhyZ myredis]# cd ..
[root@iZwz98zi7ua638a1dxozhyZ bin]# redis-sentinel myredis/sentinel.conf 
21700:X 22 Aug 2021 15:05:57.933 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
21700:X 22 Aug 2021 15:05:57.933 # Redis version=6.0.6, bits=64, commit=00000000, modified=0, pid=21700, just started
21700:X 22 Aug 2021 15:05:57.933 # Configuration loaded
                _._                                                  
           _.-``__ ''-._                                             
      _.-``    `.  `_.  ''-._           Redis 6.0.6 (00000000/0) 64 bit
  .-`` .-```.  ```\/    _.,_ ''-._                                   
 (    '      ,       .-`  | `,    )     Running in sentinel mode
 |`-._`-...-` __...-.``-._|'` _.-'|     Port: 26379
 |    `-._   `._    /     _.-'    |     PID: 21700
  `-._    `-._  `-./  _.-'    _.-'                                   
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'_.-'    |           http://redis.io        
  `-._    `-._`-.__.-'_.-'    _.-'                                   
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'_.-'    |                                  
  `-._    `-._`-.__.-'_.-'    _.-'                                   
      `-._    `-.__.-'    _.-'                                       
          `-._        _.-'                                           
              `-.__.-'                                               

21700:X 22 Aug 2021 15:05:57.935 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
21700:X 22 Aug 2021 15:05:57.937 # Sentinel ID is 3da2734fb049fcdfa8c424b9f98fbb43dbb92d22
21700:X 22 Aug 2021 15:05:57.937 # +monitor master mymaster 127.0.0.1 6379 quorum 1
21700:X 22 Aug 2021 15:05:57.938 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
21700:X 22 Aug 2021 15:05:57.941 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379

4、当主机挂掉,从机选举中产生新的主机

大概 10 秒左右可以看到哨兵窗口日志,切换了新的主机,根据优先级别:slave-priority 选择一台从机会被选举为主机,如果原来主机重启后,那么就会默认变为从机

哨兵模式的优缺点

优点:

  1. 哨兵集群模式是基于主从模式的,所有主从的优点,哨兵模式同样具有。
  2. 主从可以切换,故障可以转移,系统可用性更好。
  3. 哨兵模式是主从模式的升级,系统更健壮,可用性更高。

缺点:

  1. Redis 较难支持在线扩容,在集群容量达到上限时在线扩容会变得很复杂。
  2. 实现哨兵模式的配置也不简单,甚至可以说有些繁琐。

哨兵配置文件说明

# Example sentinel.conf 

# 哨兵sentinel实例运行的端口 默认26379 
port 26379 

# 哨兵sentinel的工作目录 
dir /tmp 

# 哨兵sentinel监控的redis主节点的 ip port 
# master-name 可以自己命名的主节点名字 只能由字母A-z、数字0-9 、这三个字符".-_"组成。 
# quorum 配置多少个sentinel哨兵统一认为master主节点失联 那么这时客观上认为主节点失联了 
# sentinel monitor     
sentinel monitor mymaster 127.0.0.1 6379 2

# 当在Redis实例中开启了requirepass foobared 授权密码 这样所有连接Redis实例的客户端都 要提供密码 
# 设置哨兵sentinel 连接主从的密码 注意必须为主从设置一样的验证密码 
# sentinel auth-pass   
sentinel auth-pass mymaster MySUPER--secret-0123passw0rd 

# 指定多少毫秒之后 主节点没有应答哨兵sentinel 此时 哨兵主观上认为主节点下线 默认30秒 
# sentinel down-after-milliseconds   
sentinel down-after-milliseconds mymaster 30000 

# 这个配置项指定了在发生failover主备切换时最多可以有多少个slave同时对新的master进行同步
# 这个数字越小,完成failover所需的时间就越长
# 但是如果这个数字越大,就意味着越 多的slave因为replication而不可用。 
# 可以通过将这个值设为 1 来保证每次只有一个slave 处于不能处理命令请求的状态。 
# sentinel parallel-syncs   
sentinel parallel-syncs mymaster 1 

# 故障转移的超时时间 failover-timeout 可以用在以下这些方面: 
# 1. 同一个sentinel对同一个master两次failover之间的间隔时间。 
# 2. 当一个slave从一个错误的master那里同步数据开始计算时间。直到slave被纠正为向正确的 master那里同步数据时。 
# 3.当想要取消一个正在进行的failover所需要的时间。 
# 4.当进行failover时,配置所有slaves指向新的master所需的最大时间。不过,即使过了这个超 时,slaves依然会被正确配置为指向master,但是就不按parallel-syncs所配置的规则来了 
# 默认三分钟 
# sentinel failover-timeout   
sentinel failover-timeout mymaster 180000 

# SCRIPTS EXECUTION 

# 配置当某一事件发生时所需要执行的脚本,可以通过脚本来通知管理员,例如当系统运行不正常时发邮 件通知相关人员。 
# 对于脚本的运行结果有以下规则: 
# 若脚本执行后返回1,那么该脚本稍后将会被再次执行,重复次数目前默认为10 
# 若脚本执行后返回2,或者比2更高的一个返回值,脚本将不会重复执行。 
# 如果脚本在执行过程中由于收到系统中断信号被终止了,则同返回值为1时的行为相同。 
# 一个脚本的最大执行时间为60s,如果超过这个时间,脚本将会被一个SIGKILL信号终止,之后重新执行。
# 通知型脚本:当sentinel有任何警告级别的事件发生时(比如说redis实例的主观失效和客观失效等 等),将会去调用这个脚本,这时这个脚本应该通过邮件,SMS等方式去通知系统管理员关于系统不正常 运行的信息。调用该脚本时,将传给脚本两个参数,一个是事件的类型,一个是事件的描述。如果 sentinel.conf配置文件中配置了这个脚本路径,那么必须保证这个脚本存在于这个路径,并且是可执 行的,否则sentinel无法正常启动成功。 
# 通知脚本 
# sentinel notification-script   
sentinel notification-script mymaster /var/redis/notify.sh 

# 客户端重新配置主节点参数脚本 
# 当一个master由于failover而发生改变时,这个脚本将会被调用,通知相关的客户端关于master 地址已经发生改变的信息。 
# 以下参数将会在调用脚本时传给脚本: 
#        
# 目前总是“failover”, 
# 是“leader”或者“observer”中的一个。 
# 参数 from-ip, from-port, to-ip, to-port是用来和旧的master和新的master(即旧的 slave)通信的
# 这个脚本应该是通用的,能被多次调用,不是针对性的。 
# sentinel client-reconfig-script   
sentinel client-reconfig-script mymaster /var/redis/reconfig.sh

Redis 集群搭建

产生的问题

容量不够,Redis 如何进行扩容?并发写操作,Redis 如何分摊?另外,主从模式,薪火相传模式,主机宕机,导致 ip 地址发生变化,应用程序中配置需要修改对应的主机地址、端口等信息。

之前通过代理主机来解决,但是 redis3.0 中提供了解决方案。就是无中心化集群配置。

什么是集群

Redis 集群实现了对 Redis 的水平扩容,即启动 N 个 Redis 节点,将整个数据库分布存储在这 N 个节点中,每个节点存储总数据的 1/N。

Redis 集群通过分区(partition)来提供一定程度的可用性(availability): 即使集群中有一部分节点失效或者无法进行通讯, 集群也可以继续处理命令请求。

集群的配置

核心配置说明:

cluster-enabled yes 打开集群模式
cluster-config-file nodes-6379.conf 设定节点配置文件名
cluster-node-timeout 15000 设定节点失联时间,超过该时间(毫秒),集群自动进行主从切换

1、制作 6 个实例,6379,6380,6381,6389,6390,6391

[root@iZwz98zi7ua638a1dxozhyZ myredis]# ll
total 112
-rw-r--r-- 1 root root   192 Aug 22 21:14 redis6379.conf
-rw-r--r-- 1 root root   192 Aug 22 21:14 redis6380.conf
-rw-r--r-- 1 root root   192 Aug 22 21:14 redis6381.conf
-rw-r--r-- 1 root root   192 Aug 22 21:15 redis6389.conf
-rw-r--r-- 1 root root   192 Aug 22 21:15 redis6390.conf
-rw-r--r-- 1 root root   192 Aug 22 21:15 redis6391.conf
-rw-r--r-- 1 root root 83393 Aug 16 21:04 redis.conf
-rw-r--r-- 1 root root   430 Aug 22 15:05 sentinel.conf

2、修改 6 个实例的配置参数

# ============================================================
# redis6379.conf 的配置参数
# ============================================================
include /usr/local/bin/myredis/redis.conf
port 6379
pidfile /var/run/redis_6379.pid
dbfilename dump6379.rdb
cluster-enabled yes
cluster-config-file nodes-6379.conf
cluster-node-timeout 15000

# ============================================================
# redis6380.conf 的配置参数
# ============================================================
include /usr/local/bin/myredis/redis.conf
port 6380
pidfile /var/run/redis_6380.pid
dbfilename dump6380.rdb
cluster-enabled yes
cluster-config-file nodes-6380.conf
cluster-node-timeout 15000

# ============================================================
# redis6381.conf 的配置参数
# ============================================================
include /usr/local/bin/myredis/redis.conf
port 6381
pidfile /var/run/redis_6381.pid
dbfilename dump6381.rdb
cluster-enabled yes
cluster-config-file nodes-6381.conf
cluster-node-timeout 15000

# ============================================================
# redis6389.conf 的配置参数
# ============================================================
include /usr/local/bin/myredis/redis.conf
port 6389
pidfile /var/run/redis_6389.pid
dbfilename dump6389.rdb
cluster-enabled yes
cluster-config-file nodes-6389.conf
cluster-node-timeout 15000

# ============================================================
# redis6390.conf 的配置参数
# ============================================================
include /usr/local/bin/myredis/redis.conf
port 6390
pidfile /var/run/redis_6390.pid
dbfilename dump6390.rdb
cluster-enabled yes
cluster-config-file nodes-6390.conf
cluster-node-timeout 15000

# ============================================================
# redis6391.conf 的配置参数
# ============================================================
include /usr/local/bin/myredis/redis.conf
port 6391
pidfile /var/run/redis_6391.pid
dbfilename dump6391.rdb
cluster-enabled yes
cluster-config-file nodes-6391.conf
cluster-node-timeout 15000

3、启动 6 个Redis 服务

# ============================================================
# 启动 redis6379 服务器
# ============================================================
[root@iZwz98zi7ua638a1dxozhyZ myredis]# redis-server redis6379.conf 
22118:C 22 Aug 2021 21:26:38.831 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
22118:C 22 Aug 2021 21:26:38.831 # Redis version=6.0.6, bits=64, commit=00000000, modified=0, pid=22118, just started
22118:C 22 Aug 2021 21:26:38.831 # Configuration loaded

# ============================================================
# 启动 redis6380 服务器
# ============================================================
[root@iZwz98zi7ua638a1dxozhyZ myredis]# redis-server redis6380.conf 
22125:C 22 Aug 2021 21:26:54.857 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
22125:C 22 Aug 2021 21:26:54.857 # Redis version=6.0.6, bits=64, commit=00000000, modified=0, pid=22125, just started
22125:C 22 Aug 2021 21:26:54.857 # Configuration loaded

# ============================================================
# 启动 redis6381 服务器
# ============================================================
[root@iZwz98zi7ua638a1dxozhyZ myredis]# redis-server redis6381.conf 
22131:C 22 Aug 2021 21:26:57.590 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
22131:C 22 Aug 2021 21:26:57.590 # Redis version=6.0.6, bits=64, commit=00000000, modified=0, pid=22131, just started
22131:C 22 Aug 2021 21:26:57.590 # Configuration loaded

# ============================================================
# 启动 redis6389 服务器
# ============================================================
22091:C 22 Aug 2021 21:23:02.640 # Configuration loaded
[root@iZwz98zi7ua638a1dxozhyZ myredis]# redis-server redis6389.conf 
22093:C 22 Aug 2021 21:23:05.705 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
22093:C 22 Aug 2021 21:23:05.705 # Redis version=6.0.6, bits=64, commit=00000000, modified=0, pid=22093, just started
22093:C 22 Aug 2021 21:23:05.705 # Configuration loaded

# ============================================================
# 启动 redis6390 服务器
# ============================================================
[root@iZwz98zi7ua638a1dxozhyZ myredis]# redis-server redis6390.conf 
22099:C 22 Aug 2021 21:23:09.709 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
22099:C 22 Aug 2021 21:23:09.709 # Redis version=6.0.6, bits=64, commit=00000000, modified=0, pid=22099, just started
22099:C 22 Aug 2021 21:23:09.709 # Configuration loaded

# ============================================================
# 启动 redis6391 服务器
# ============================================================
[root@iZwz98zi7ua638a1dxozhyZ myredis]# redis-server redis6391.conf 
22105:C 22 Aug 2021 21:23:12.200 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
22105:C 22 Aug 2021 21:23:12.200 # Redis version=6.0.6, bits=64, commit=00000000, modified=0, pid=22105, just started
22105:C 22 Aug 2021 21:23:12.200 # Configuration loaded

# ============================================================
# 查看 redis 服务进程信息
# ============================================================
[root@iZwz98zi7ua638a1dxozhyZ myredis]# ps -ef | grep redis
root     22094     1  0 21:23 ?        00:00:00 redis-server 127.0.0.1:6389 [cluster]
root     22100     1  0 21:23 ?        00:00:00 redis-server 127.0.0.1:6390 [cluster]
root     22106     1  0 21:23 ?        00:00:00 redis-server 127.0.0.1:6391 [cluster]
root     22119     1  0 21:26 ?        00:00:00 redis-server 127.0.0.1:6379 [cluster]
root     22126     1  0 21:26 ?        00:00:00 redis-server 127.0.0.1:6380 [cluster]
root     22132     1  0 21:26 ?        00:00:00 redis-server 127.0.0.1:6381 [cluster]

4、将六个节点合成一个集群

组合之前,请确保所有 redis 实例启动后,nodes-xxxx.conf 文件都生成正常

[root@iZwz98zi7ua638a1dxozhyZ myredis]# ll
total 136
-rw-r--r-- 1 root root   114 Aug 22 21:26 nodes-6379.conf
-rw-r--r-- 1 root root   114 Aug 22 21:26 nodes-6380.conf
-rw-r--r-- 1 root root   114 Aug 22 21:26 nodes-6381.conf
-rw-r--r-- 1 root root   114 Aug 22 21:23 nodes-6389.conf
-rw-r--r-- 1 root root   114 Aug 22 21:23 nodes-6390.conf
-rw-r--r-- 1 root root   114 Aug 22 21:23 nodes-6391.conf
-rw-r--r-- 1 root root   192 Aug 22 21:14 redis6379.conf
-rw-r--r-- 1 root root   192 Aug 22 21:18 redis6380.conf
-rw-r--r-- 1 root root   192 Aug 22 21:18 redis6381.conf
-rw-r--r-- 1 root root   192 Aug 22 21:18 redis6389.conf
-rw-r--r-- 1 root root   192 Aug 22 21:19 redis6390.conf
-rw-r--r-- 1 root root   192 Aug 22 21:19 redis6391.conf
-rw-r--r-- 1 root root 83393 Aug 16 21:04 redis.conf
-rw-r--r-- 1 root root   430 Aug 22 15:05 sentinel.conf

进入 cd /opt/redis-6.2.1/src 目录,执行一下命令进行合体

redis-cli --cluster create --cluster-replicas 1 192.168.11.101:6379 192.168.11.101:6380 192.168.11.101:6381 192.168.11.101:6389 192.168.11.101:6390 192.168.11.101:6391

此处IP地址不能用 127.0.0.1, 需要用真实IP地址。

--replicas 1 表示采用最简单的方式配置集群,一台主机,一台从机,正好三组。

[root@iZwz98zi7ua638a1dxozhyZ src]# redis-cli --cluster create --cluster-replicas 1 192.168.11.101:6379 192.168.11.101:6380 192.168.11.101:6381 192.168.11.101:6389 192.168.11.101:6390 192.168.11.101:6391
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 127.0.0.1:6390 to 127.0.0.1:6379
Adding replica 127.0.0.1:6391 to 127.0.0.1:6380
Adding replica 127.0.0.1:6389 to 127.0.0.1:6381
>>> Trying to optimize slaves allocation for anti-affinity
[WARNING] Some slaves are in the same host as their master
M: 5579845d82abf2255247e4dccc4aee82b4582a66 127.0.0.1:6379
   slots:[0-5460] (5461 slots) master
M: 9c59803bee9334c813f28a7f08818bb225b51930 127.0.0.1:6380
   slots:[5461-10922] (5462 slots) master
M: 01969d736a756d07bbdfa0142f97462a795336fb 127.0.0.1:6381
   slots:[10923-16383] (5461 slots) master
S: 91b0da494f0c2ffa066f15cde1c990deeedc3084 127.0.0.1:6389
   replicates 9c59803bee9334c813f28a7f08818bb225b51930
S: f45bd4e51467ba48a8b2df169c3e25dc856000b6 127.0.0.1:6390
   replicates 01969d736a756d07bbdfa0142f97462a795336fb
S: a2d85b5b341b6efab9ce75d9d098743b3c613a39 127.0.0.1:6391
   replicates 5579845d82abf2255247e4dccc4aee82b4582a66
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:6379)
M: 5579845d82abf2255247e4dccc4aee82b4582a66 127.0.0.1:6379
   slots:[0-5460] (5461 slots) master
   1 additional replica(s)
S: 91b0da494f0c2ffa066f15cde1c990deeedc3084 127.0.0.1:6389
   slots: (0 slots) slave
   replicates 9c59803bee9334c813f28a7f08818bb225b51930
M: 01969d736a756d07bbdfa0142f97462a795336fb 127.0.0.1:6381
   slots:[10923-16383] (5461 slots) master
   1 additional replica(s)
S: f45bd4e51467ba48a8b2df169c3e25dc856000b6 127.0.0.1:6390
   slots: (0 slots) slave
   replicates 01969d736a756d07bbdfa0142f97462a795336fb
M: 9c59803bee9334c813f28a7f08818bb225b51930 127.0.0.1:6380
   slots:[5461-10922] (5462 slots) master
   1 additional replica(s)
S: a2d85b5b341b6efab9ce75d9d098743b3c613a39 127.0.0.1:6391
   slots: (0 slots) slave
   replicates 5579845d82abf2255247e4dccc4aee82b4582a66
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.

集群的登录

普通方式登录,可能直接进入读主机,存储数据时,会出现MOVED重定向操作。所以,应该以集群方式登录。

[root@iZwz98zi7ua638a1dxozhyZ myredis]# redis-cli -p 6379
127.0.0.1:6379> set k1 v1
(error) MOVED 12706 192.168.11.101:6381

-c 采用集群策略连接,设置数据会自动切换到相应的写主机

[root@iZwz98zi7ua638a1dxozhyZ myredis]# redis-cli -c -p 6379
127.0.0.1:6379> set k1 v1
-> Redirected to slot [12706] located at 192.168.11.101:6381
OK

查看集群信息

通过 cluster nodes 命令查看集群信息

127.0.0.1:6381> cluster nodes
91b0da494f0c2ffa066f15cde1c990deeedc3084 192.168.11.101:6389@16389 slave 9c59803bee9334c813f28a7f08818bb225b51930 0 1629640173000 2 connected
a2d85b5b341b6efab9ce75d9d098743b3c613a39 192.168.11.101:6391@16391 slave 5579845d82abf2255247e4dccc4aee82b4582a66 0 1629640174000 1 connected
5579845d82abf2255247e4dccc4aee82b4582a66 192.168.11.101:6379@16379 master - 0 1629640173000 1 connected 0-5460
f45bd4e51467ba48a8b2df169c3e25dc856000b6 192.168.11.101:6390@16390 slave 01969d736a756d07bbdfa0142f97462a795336fb 0 1629640174961 3 connected
01969d736a756d07bbdfa0142f97462a795336fb 192.168.11.101:6381@16381 myself,master - 0 1629640172000 3 connected 10923-16383
9c59803bee9334c813f28a7f08818bb225b51930 192.168.11.101:6380@16380 master - 0 1629640174000 2 connected 5461-10922

如何分配节点

redis cluster 如何分配这六个节点?

一个集群至少要有三个主节点。

选项 --cluster-replicas 1 表示我们希望为集群中的每个主节点创建一个从节点。

分配原则尽量保证每个主数据库运行在不同的 IP 地址,每个从库和主库不在一个 IP 地址上。

什么是 slots

# 合体成功后提示的信息
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.

一个 Redis 集群包含 16384 个插槽(hash slot), 数据库中的每个键都属于这 16384 个插槽的其中一个,

集群使用公式 CRC16(key) % 16384 来计算键 key 属于哪个槽, 其中 CRC16(key) 语句用于计算键 key 的 CRC16 校验和 。

集群中的每个节点负责处理一部分插槽。 举个例子, 如果一个集群可以有主节点, 其中:

节点 A 负责处理 0 号至 5460 号插槽。

节点 B 负责处理 5461 号至 10922 号插槽。

节点 C 负责处理 10923 号至 16383 号插槽。

在集群中录入值

在 redis-cli 每次录入、查询键值,redis 都会计算出该 key 应该送往的插槽,如果不是该客户端对应服务器的插槽,redis 会报错,并告知应前往的 redis 实例地址和端口。

redis-cli 客户端提供了 –c 参数实现自动重定向。

如 redis-cli -c –p 6379 登入后,再录入、查询键值对可以自动重定向。

127.0.0.1:6379> set k1 v1
-> Redirected to slot [12706] located at 192.168.11.101:6381
OK
127.0.0.1:6381> # 自动重定向到6381

不在一个 slot 下的键值,是不能使用 mget,mset 等多键操作。

127.0.0.1:6381> mset k1 v1 k2 v2
(error) CROSSSLOT Keys in request don't hash to the same slot

可以通过 {} 来定义组的概念,从而使 key 中 {} 内相同内容的键值对放到一个 slot 中去。

127.0.0.1:6381> mset k1{cust} v1 k2{cust} v2
-> Redirected to slot [4847] located at 192.168.11.101:6379
OK
127.0.0.1:6379>

查询集群中的值

CLUSTER GETKEYSINSLOT 返回 count 个 slot 槽中的键。

127.0.0.1:6379> cluster keyslot cust
(integer) 4847
127.0.0.1:6379> cluster countkeysinslot 4847
(integer) 2
127.0.0.1:6379> cluster getkeysinslot 4847 10
1) "k1{cust}"
2) "k2{cust}"

故障恢复

如果主节点下线?从节点能否自动升为主节点?注意:15秒超时

[root@iZwz98zi7ua638a1dxozhyZ myredis]# redis-cli -c -p 6380
127.0.0.1:6380> cluster nodes
a2d85b5b341b6efab9ce75d9d098743b3c613a39 192.168.11.101:6391@16391 master - 0 1629640874536 7 connected 0-5460
9c59803bee9334c813f28a7f08818bb225b51930 192.168.11.101:6380@16380 myself,master - 0 1629640873000 2 connected 5461-10922
5579845d82abf2255247e4dccc4aee82b4582a66 192.168.11.101:6379@16379 master,fail - 1629640850484 1629640845471 1 disconnected
91b0da494f0c2ffa066f15cde1c990deeedc3084 192.168.11.101:6389@16389 slave 9c59803bee9334c813f28a7f08818bb225b51930 0 1629640874000 2 connected
01969d736a756d07bbdfa0142f97462a795336fb 192.168.11.101:6381@16381 master - 0 1629640873000 3 connected 10923-16383
f45bd4e51467ba48a8b2df169c3e25dc856000b6 192.168.11.101:6390@16390 slave 01969d736a756d07bbdfa0142f97462a795336fb 0 1629640873533 3 connected

主节点恢复后,主从关系会如何?主节点回来变成从机。

[root@iZwz98zi7ua638a1dxozhyZ myredis]# redis-server redis6379.conf 
22195:C 22 Aug 2021 22:03:24.654 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
22195:C 22 Aug 2021 22:03:24.654 # Redis version=6.0.6, bits=64, commit=00000000, modified=0, pid=22195, just started
22195:C 22 Aug 2021 22:03:24.654 # Configuration loaded
[root@iZwz98zi7ua638a1dxozhyZ myredis]# redis-cli -c -p 6379
127.0.0.1:6379> cluster nodes
9c59803bee9334c813f28a7f08818bb225b51930 192.168.11.1016380@16380 master - 0 1629641020595 2 connected 5461-10922
01969d736a756d07bbdfa0142f97462a795336fb 192.168.11.101:6381@16381 master - 0 1629641020000 3 connected 10923-16383
f45bd4e51467ba48a8b2df169c3e25dc856000b6 192.168.11.101:6390@16390 slave 01969d736a756d07bbdfa0142f97462a795336fb 0 1629641019000 3 connected
91b0da494f0c2ffa066f15cde1c990deeedc3084 192.168.11.101:6389@16389 slave 9c59803bee9334c813f28a7f08818bb225b51930 0 1629641021598 2 connected
a2d85b5b341b6efab9ce75d9d098743b3c613a39 192.168.11.101:6391@16391 master - 0 1629641019592 7 connected 0-5460
5579845d82abf2255247e4dccc4aee82b4582a66 192.168.11.101:6379@16379 myself,slave a2d85b5b341b6efab9ce75d9d098743b3c613a39 0 1629641018000 7 connected

如果所有某一段插槽的主从节点都宕掉,Redis 服务是否还能继续?

如果某一段插槽的主从都挂掉,而 cluster-require-full-coverage 为 yes ,那么 ,整个集群都挂掉。

如果某一段插槽的主从都挂掉,而 cluster-require-full-coverage 为 no ,那么,该插槽数据全都不能使用,也无法存储。

redis.conf 中的参数 cluster-require-full-coverage

Redis 的优缺点

优点:

  1. 实现扩容

  2. 分摊压力

  3. 无中心配置相对简单

缺点:

  1. 多键操作是不被支持的

  2. 多键的 Redis 事务是不被支持的。lua脚本不被支持

  3. 由于集群方案出现较晚,很多公司已经采用了其他的集群方案,而代理或者客户端分片的方案想要迁移至 redis cluster,需要整体迁移而不是逐步过渡,复杂度较大。

你可能感兴趣的