关于redis集群:Redis学习-复制以及三种部署模式

30次阅读

共计 17420 个字符,预计需要花费 44 分钟才能阅读完成。

Redis 学习 – 复制以及三种部署模式

什么是复制

单机的 redis 通常状况是无奈满足我的项目需要的,个别都倡议应用集群部署的形式进行数据的多机备份和部署,这样既能够保障数据安全,同时在 redis 宕机的时候,复制也能够对于数据进行疾速的修复。

<!– more –>

采取的形式

  1. 单机部署(疏忽)
  2. 主从链
  3. 一主多从
  4. 哨兵模式
  5. 集群模式

复制的前提

  1. 须要保障 redis.conf 外面的配置是正确的,比方:
dir ./
dbfilename "dump.rdb"
  1. 须要保障指定的门路对于 redis 来说是 可写 的,意味着如果当前目录没有写权限同样会失败

从服务器连贯主服务器的几种形式

  1. 在从服务器的配置文件外面配置连贯那个主服务器:

连贯的具体配置如下:

在 5.0 版本中应用了 replicaof 代替了 slaveof(github.com/antirez/red…),slaveof 还能够持续应用,不过倡议应用replicaof

上面是集体的配置

# replicaof <masterip> <masterport> 
replicaof 127.0.0.1 16379

正告:此大节只阐明了这一个配置的更改,进行主从配置的时候还有其余几个参数须要更改,这里只作为局部内容参考

  1. 在启动的适宜,在 redis 从服务器 的 redis-cli 当中敲击如下的命令:
127.0.0.1:16380> slaveof 127.0.0.1 16379
OK Already connected to specified master

这样就能够在从服务器动静的指定要连贯哪个主服务器了,然而这种配置是 以后运行时无效,下次再次进入的时候,会依据配置文件进行配置或者依照默认的规定以后实例就是master3.

  1. 在从服务器执行slaveof no one,以后实例脱离管制主动成为master

redis 复制启动的过程 ==(重点)==

主服务器操作 从服务器操作
1.(期待命令) 1. 连贯(从新连贯)主服务器,发送 sync 命令
2. 开始执行 bgsave,应用缓冲区记录 bgsave 之后执行所有写命令 2. 依据配置选项是应用现有的数据(存在)解决客户端申请,还是向申请的客户端返回错误信息
3. bgsave 执行结束,向从服务器发送 快照文件,同时异步执行缓冲区记录的写命令 3. 抛弃所有的旧数据,载入主服务器的快照文件
4. 快照文件发送结束,开始向着从服务器发送存储在缓冲区的写命令 4. 实现对于快照的解释操作,复原日常的申请操作
5. 缓冲区写命令发送实现,同时当初每执行一个写命令就像从服务器发送雷同写命令 5. 执行主服务器发来的所有存储在缓冲区的写命令,并且从当初开始承受主服务器的每一个命令

倡议:因为 bgsave 须要开启进行子线程的创立写入缓冲区的创立,所以最好在零碎中预留 30% – 45% 内存用于 redis 的 bgsave 操作

特地留神:当从服务器连贯主服务器的那一刻,执行到第三步会 清空 以后 redis 外面的所有数据。

配置形式和命令形式的区别:

redis.conf 配置 slaveof 的形式:不会马上进行主服务器同步,而是 先载入以后本地存在的 rdb 或者 aof到 redis 中进行数据恢复,而后才开始同步复制

命令 slaveof 形式:会 立刻 连贯主服务器进行同步操作

对于 redis 的主主复制:

如果咱们尝试让两台服务器相互 slaveof 那么会呈现下面状况呢?

从下面的复制过程能够看到,当一个服务器 slaveof 另一个服务器,产生的后果只会是两边互相笼罩,也就是从服务器会去同步主服务器的数据,如果此时依照主主的配置,两边相互同步对方的数据,这样产生的数据可能会不统一,或者数据罗唆就是不残缺的。不仅如此,这种操作还会大量占用资源区让两台服务器相互晓得对方

当一台服务器连贯另一台服务器的时候会产生什么?

当有新服务器连贯的时候 主服务器操作
步骤 3 还没有执行 所有从服务器都会收到雷同的快照文件和雷同缓冲区写命令
步骤 3 正在执行或者曾经执行 实现了之前同步的五个操作之后,会跟新服务器从新执行一次新的五个步骤

系统故障解决

复制和长久化尽管曾经根本能够保证系统的数据安全,然而总有意外的状况,比方忽然断电断网,零碎磁盘故障,服务器宕机等一系列状况,那么会呈现各种莫名微妙的问题,上面针对这些状况阐明一下解决形式:

验证快照文件以及 aof 文件

在 redis 的 bin 目录上面,存在如下的两个 sh

-rwxr-xr-x 1 root root 9722168 Nov 15 20:53 redis-check-aof
-rwxr-xr-x 1 root root 9722168 Nov 15 20:53 redis-check-rdb

他们的命令作用和内容如下:

[xd@iZwz99gyct1a1rh6iblyucZ bin]$ ./redis-check-aof 
Usage: ./redis-check-aof [--fix] <file.aof>
[xd@iZwz99gyct1a1rh6iblyucZ bin]$ ./redis-check-rdb 
Usage: ./redis-check-rdb <rdb-file-name>

redis-check-aof:如果退出 --fix 选项,那么命令会尝试修复 aof 文件,会将内容外面呈现谬误的命令以及上面的所有命令清空,个别状况下回清空尾部的一些未实现命令。

redis-check-rdb:遗憾的是目前这种修复收效甚微。倡议在修复 rdb 的时候,用 SHA1 和 SHA256 验证文件是否残缺。

校验和与散列值:

redis2.6 之后退出了校验和与散列值进行验证。

快照文件减少 CRC64 校验和

什么是 crc循环冗余校验

https://zh.wikipedia.org/wiki…

更换故障主服务器:

  1. 假如 A 故障,存在 BC 两台机器,B 为从服务,C 为将要替换的主服务器
  2. 向机器 B 发送 save 命令,同时创立一个新的快照文件,同步实现之后,发送给 C
  3. 机器 C 下面启动 redis, 让 C 成为 B 的主服务器

Redis sentienel 哨兵

能够监督指定主服务器以及属下的从服务器

也就是咱们罕用的 哨兵模式

然而随着时代提高,目前应用 redis 根本还是以 cluster 模式 为主

redis 主从复制模式(redis6.0 版本):

前提阐明:

有条件的能够弄三台虚拟机查看成果,这样模仿进去的成果算是比拟实在的。

三台从服务器以及一台主服务器的配置

集体的方法是 copy 一个专用的配置,而后进行批改(这里只列举区别以及改变较多的中央,其余中央依据须要配置):

第一台机器的配置:

pidfile /var/run/redis_16379.pid
port 16379
dbfilename dump16379.rdb
appendfilename "appendonly16379.aof"
logfile "log16379"

第二台机器的配置:

pidfile /var/run/redis_16380.pid
port 16380
dbfilename dump16380.rdb
appendfilename "appendonly16380.aof"
logfile "log16380"

第三台机器的配置:

pidfile /var/run/redis_16381.pid
port 16381
dbfilename dump16381.rdb
appendfilename "appendonly16381.aof"
logfile "log16381"

这时候要配置一台主服务器

pidfile /var/run/redis_10000.pid
port 10000
dbfilename dump10000.rdb
appendfilename "appendonly10000.aof"
logfile "log10000"

启动 redis 一主多从:

配置很简略,能够用 手动 进行主从复制,也能够应用 redis.conf 提前配置,具体区别上文曾经进行过介绍,这里不再赘述。

从服务器能够通过命令:slaveof 127.0.0.1 10000 实现主从复制拷贝

能够通过命令info replication 查看主从配置的信息。

主服务器启动日志:

127.0.0.1:10000> info replication
# Replication
role:master
connected_slaves:0
master_replid:e2a92d8c59fbdde3b162da12f4d74ff28bab4fbb
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
127.0.0.1:10000> info replication
# Replication
role:master
connected_slaves:3
slave0:ip=127.0.0.1,port=16381,state=online,offset=14,lag=1
slave1:ip=127.0.0.1,port=16380,state=online,offset=14,lag=1
slave2:ip=127.0.0.1,port=16379,state=online,offset=14,lag=1
master_replid:029e455ee6f8fdc0e255b6d5c4f63136d933fb24
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:14
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:14

能够看到进行主从配置之后,以后的目录上面多出了对应备份文件

当进行主从配置之后,从服务就无奈进行写入了,主服务器才能够写入:

127.0.0.1:16379> set key 1
(error) READONLY You can't write against a read only replica.
测试一主多从复制:

主服务器敲入如下命令:

127.0.0.1:10000> hset key1 name1 value1
(integer) 1
127.0.0.1:10000> keys *
1) "key1"

从服务器:

127.0.0.1:16379> hget key1 name1
"value1"
127.0.0.1:16380> hget key1 name1
"value1"
127.0.0.1:16381> hget key1 name1
"value1"

主从链

配置形式:

和主从配置一样,只不过主节点换为从节点。

留神:主从链的配置仍然只能是 master 节点能够写数据,同时两头的节点也是 slave

扩大

如何检测磁盘是否写入数据?

  1. 主从服务器通过一个虚标值(unique dummy value)来验证从服务器是否真的把数据写入到本人的磁盘。
  2. 通过命令:info查看后果当中的 aof_appending_bio_fsync的值是否为 0:

\# 5.0 版本之后改为如下模式验证

repl_backlog_active:0

redis 主从哨兵模式(Redis sentienel)(redis6.0 版本)

哨兵模式有什么作用:

Redis 的哨兵模式就是对 redis 零碎进行实时的监控,其次要性能有上面两点

1.监测 主数据库和从数据库是否失常运行。

2. 当咱们的主数据库呈现故障的时候,能够主动将从数据库转换为主数据库,实现 主动的切换

为什么要应用哨兵模式:

  1. 主从复制在主节点宕机的状况下,须要人工干预复原 redis,无奈实现高可用。
  2. 主节点宕机的状况下须要备份数据到新的从节点,而后其余节点将主节点设置为新的 redis,须要一次全量复制同步数据的过程

哨兵模式原理

主节点故障的时候,由 redis sentinel 主动实现故障发现和转移

如何部署哨兵模式:

  1. 首先依照上一节配置,曾经设置了一个主节点三个从节点的配置

上面的配置如下:

主节点:10000

从节点 1:16379

从节点 2:16380

从节点 3:16381

[xd@iZwz99gyct1a1rh6iblyucZ ~]$ ps -ef | grep redis
xd        2964  2910  0 18:02 pts/0    00:00:00 grep --color=auto redis
root     26412     1  0 Nov23 ?        00:06:07 ./redis-server 127.0.0.1:10000
root     26421     1  0 Nov23 ?        00:05:37 ./redis-server 127.0.0.1:16379
root     26428     1  0 Nov23 ?        00:05:37 ./redis-server 127.0.0.1:16380
root     26435     1  0 Nov23 ?        00:05:37 ./redis-server 127.0.0.1:16381
  1. sentinel.conf 配置文件在装置 redis 的源码包外面有,所以如果误删了能够下回来而后把文件弄到手,其实能够配置一个罕用的或者通用的配置放到本人的本地有须要间接替换
  2. 配置 5 个 sentienl.conf 文件(倡议奇数个哨兵,不便宕机选举产生新的节点)
[xd@iZwz99gyct1a1rh6iblyucZ bin]$ sudo cp sentinel.conf sentinel_26379.conf
[xd@iZwz99gyct1a1rh6iblyucZ bin]$ sudo cp sentinel.conf sentinel_26380.conf
[xd@iZwz99gyct1a1rh6iblyucZ bin]$ sudo cp sentinel.conf sentinel_26381.conf
[xd@iZwz99gyct1a1rh6iblyucZ bin]$ sudo cp sentinel.conf sentinel_10000.conf
  1. 四个配置文件的改变顺次如下:

所有的sentinel.conf 配置如下:

# 指定哨兵端口
port 20000
# 监听主节点 10000
sentinel monitor mymaster 127.0.0.1 10000 2
# 连贯主节点时的明码,如果 redis 配置了明码须要填写
sentinel auth-pass mymaster 12345678
# 故障转移时最多能够有 2 从节点同时对新主节点进行数据同步
sentinel config-epoch mymaster 2
# 故障转移超时工夫 180s,sentinel failover-timeout mymasterA 180000 
# sentinel 节点定期向主节点 ping 命令,当超过了 300S 工夫后没有回复,可能就认定为此主节点呈现故障了……
sentinel down-after-milliseconds mymasterA 300000
# 故障转移后,1 代表每个从节点按程序排队一个一个复制主节点数据,如果为 3,指 3 个从节点同时并发复制主节点数据,不会影响阻塞,但存在网络和 IO 开销
sentinel parallel-syncs mymasterA 1
# 设置后盾启动
daemonize yes
# 过程的 pid 文件,保险起见设置不一样的,特地是设置后盾启动的时候
pidfile /var/run/redis-sentinel.pid

扩大:如何断定转移失败:

a – 如果转移超时失败,下次转移时工夫为之前的 2 倍;

b – 从节点变主节点时,从节点执行 slaveof no one 命令始终失败的话,当工夫超过 180S 时,则故障转移失败

c – 从节点复制新主节点工夫超过 180S 转移失败

上面为配好五个之后的配置:

-rw-r--r-- 1 root root   10772 Nov 28 21:00 sentienl_26382.conf
-rw-r--r-- 1 root root   10767 Nov 28 20:43 sentinel_10000.conf
-rw-r--r-- 1 root root   10772 Nov 28 21:03 sentinel_26379.conf
-rw-r--r-- 1 root root   10766 Nov 28 20:46 sentinel_26380.conf
-rw-r--r-- 1 root root   10772 Nov 28 20:59 sentinel_26381.conf
-rw-r--r-- 1 root root   10772 Nov 28 21:03 sentinel_26382.conf
-rw-r--r-- 1 root root   10744 Nov 28 18:06 sentinel.conf
  1. 上一节曾经启动过,这里不再介绍
  2. 启动 sentinel 服务

启动五个哨兵:

./redis-sentinel ./sentinel_10000.conf 
./redis-sentinel ./sentinel_26379.conf 
./redis-sentinel ./sentinel_263780.conf 
./redis-sentinel ./sentinel_263781.conf 
./redis-sentinel ./sentinel_263782.conf 

应用 ps 命令查看所有的服务:

root      3267     1  0 21:14 ?        00:00:01 ./redis-sentinel *:20000 [sentinel]
root      3280     1  0 21:15 ?        00:00:01 ./redis-sentinel *:26379 [sentinel]
root      3296     1  0 21:20 ?        00:00:00 ./redis-sentinel *:26380 [sentinel]
root      3303     1  0 21:21 ?        00:00:00 ./redis-sentinel *:26381 [sentinel]
root      3316  3254  0 21:28 pts/0    00:00:00 grep --color=auto redis
root     26412     1  0 Nov23 ?        00:06:17 ./redis-server 127.0.0.1:10000
root     26421     1  0 Nov23 ?        00:05:47 ./redis-server 127.0.0.1:16379
root     26428     1  0 Nov23 ?        00:05:47 ./redis-server 127.0.0.1:16380
root     26435     1  0 Nov23 ?        00:05:47 ./redis-server 127.0.0.1:16381
  1. 验证一下哨兵是否管用

10000 是主节点,他的 info 信息如下:

# Keyspace
db0:keys=1,expires=0,avg_ttl=0
127.0.0.1:10000> info replication
# Replication
role:master
connected_slaves:3

应用 kill -9 master 节点过程端口号 之后,咱们曾经干掉了额主过程,验证一下从节点是否启动

进入到 6379 端口的 redis-cli 当中,能够看到从节点 6379 的实例被选举为新的的节点

127.0.0.1:16379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=16380,state=online,offset=857706,lag=1
slave1:ip=127.0.0.1,port=16381,state=online,offset=858242,lag=1

挂掉的主节点复原之后,能不能进行复原为主节点?

尝试重启挂掉的 master 之后,能够发现他变成了从节点

127.0.0.1:10000> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:16379
master_link_status:up
master_last_io_seconds_ago:2

留神:生产环境倡议让 redis Sentinel 部署到不同的物理机上

如果不喜爱下面的启动哨兵模式,也能够应用上面的命令开启:

[root@dev-server-1 sentinel]# redis-server sentinel1.conf --sentinel
[root@dev-server-1 sentinel]# redis-server sentinel2.conf --sentinel
[root@dev-server-1 sentinel]# redis-server sentinel3.conf --sentinel

哨兵模式部署倡议

a,sentinel 节点应部署在 多台 物理机(线上 环境)

b,至多三个且 奇数 个 sentinel 节点

c,通过以上咱们晓得, 3 个 sentinel可同时监控一个主节点或多个主节点

监听 N 个主节点较多时,如果 sentinel 出现异常,会对多个主节点有影响,同时还会造成 sentinel 节点产生过多的网络连接,

个别线上倡议还是, 3 个 sentinel监听一个主节点

也能够依照上面的形式在启动哨兵的时候启动:

哨兵模式的优缺点:

长处:

  1. 哨兵模式基于主从复制模式,所以主从复制模式有的长处,哨兵模式也有
  2. 哨兵模式下,master 挂掉能够主动进行切换,零碎可用性更高

毛病:

  1. 同样也继承了主从模式难以在线扩容的毛病,Redis 的容量受限于单机配置
  2. 须要额定的资源来启动 sentinel 过程,实现绝对简单一点,同时 slave 节点作为备份节点不提供服务

redis 集群模式(redis6.0 版本)

随着利用的扩大,尽管主从模式和哨兵模式的退出解决了高可用的问题,然而古代的利用根本都是要求能够动静扩大了,为了反对动静扩大,redis 在后续的版本当中退出了哨兵的模式

集群模式次要解决的问题是:

Cluster 模式实现了 Redis 的分布式存储,即每台节点存储不同的内容,来解决在线扩容的问题

redis 结构设计:

应用的是无核心的构造,每一个节点和节点之间相互连接

  1. redis 应用彼此互联的 (ping-pong) 的形式,进行相互关联,外部应用二进制协定优化速度
  2. 客户端与 redis 节点直连, 不须要两头代理层. 客户端不须要连贯集群所有节点, 连贯集群中任何一个可用节点即可
  3. 节点的 fail 是通过集群中超过 半数 的节点检测生效时才失效

redis 集群的工作机制

  1. 在 Redis 的每个节点上,都有一个插槽(slot),取值范畴为 0 -16383,redis 会依据接节点的数量调配槽的地位来进行断定发送给哪一个 cluster 节点
  2. 当咱们存取 key 的时候,Redis 会依据 CRC16 的算法得出一个后果,而后把后果对 16384 求余数,这样每个 key 都会对应一个编号在 0 -16383 之间的哈希槽,通过这个值,去找到对应的插槽所对应的节点,而后间接主动跳转到这个对应的节点上进行存取操作
  3. 为了保障高可用,Cluster 模式也引入 主从复制模式,一个主节点对应一个或者多个从节点,当主节点宕机的时候,就会启用从节点
  4. 当其它主节点 ping 一个主节点 A 时,如果半数以上的主节点与 A 通信超时,那么认为主节点 A 宕机了。如果主节点 A 和它的从节点都宕机了,那么 该集群就无奈再提供服务了

配置集群(重点):

为了不产生烦扰,先把上一节所有的 redis 过程干掉,包含哨兵的配置

应用 kil -9 过程端口号 间接抹掉整个利用

配置如下:

  1. 集群至多须要三主三从,同时须要奇数的节点配置。
  2. 咱们能够将之前的主从配置的一主三从 减少两个主节点,目前的配置如下:
-rw-r--r-- 1 root root   84993 Nov 28 21:41 redis10000.conf
-rw-r--r-- 1 root root   84936 Nov 28 21:35 redis16379.conf
-rw-r--r-- 1 root root   84962 Nov 28 21:35 redis16380.conf
-rw-r--r-- 1 root root   84962 Nov 28 21:35 redis16381.conf

# 减少两个次要节点
-rw-r--r-- 1 root root   84962 Nov 28 21:35 redis16382.conf
-rw-r--r-- 1 root root   84962 Nov 28 21:35 redis16383.conf

主节点的配置次要如下:

port 7100 # 本示例 6 个节点端口别离为 7100,7200,7300,7400,7500,7600 
daemonize yes # r 后盾运行 
pidfile /var/run/redis_7100.pid # pidfile 文件对应 7100,7200,7300,7400,7500,7600 
cluster-enabled yes # 开启集群模式 
masterauth passw0rd # 如果设置了明码,须要指定 master 明码
cluster-config-file nodes_7100.conf # 集群的配置文件,同样对应 7100,7200 等六个节点
cluster-node-timeout 15000 # 申请超时 默认 15 秒,可自行设置 

启动如下:

[root@iZwz99gyct1a1rh6iblyucZ bin]# ./redis-server ./cluster/redis17000_cluster.conf
[root@iZwz99gyct1a1rh6iblyucZ bin]# ./redis-server ./cluster/redis17100_cluster.conf
[root@iZwz99gyct1a1rh6iblyucZ bin]# ./redis-server ./cluster/redis17200_cluster.conf
[root@iZwz99gyct1a1rh6iblyucZ bin]# ./redis-server ./cluster/redis17300_cluster.conf
[root@iZwz99gyct1a1rh6iblyucZ bin]# ./redis-server ./cluster/redis17400_cluster.conf
[root@iZwz99gyct1a1rh6iblyucZ bin]# ./redis-server ./cluster/redis17500_cluster.conf
[root@iZwz99gyct1a1rh6iblyucZ bin]# ps -ef | grep redis
root      4761     1  0 15:55 ?        00:00:00 ./redis-server 127.0.0.1:17000 [cluster]
root      4767     1  0 15:55 ?        00:00:00 ./redis-server 127.0.0.1:17100 [cluster]
root      4773     1  0 15:55 ?        00:00:00 ./redis-server 127.0.0.1:17200 [cluster]
root      4779     1  0 15:55 ?        00:00:00 ./redis-server 127.0.0.1:17300 [cluster]
root      4785     1  0 15:55 ?        00:00:00 ./redis-server 127.0.0.1:17400 [cluster]
root      4791     1  0 15:55 ?        00:00:00 ./redis-server 127.0.0.1:17500 [cluster]
root      4797  4669  0 15:55 pts/0    00:00:00 grep --color=auto redis

启动了下面六个节点之后,应用上面的命令并且敲入 yes 让他们变为集群:

[root@iZwz99gyct1a1rh6iblyucZ bin]# ./redis-cli --cluster create 127.0.0.1:17000 127.0.0.1:17100 127.0.0.1:17200 127.0.0.1:17300 127.0.0.1:17400 127.0.0.1:17500 --cluster-replicas 1

>>> 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:17400 to 127.0.0.1:17000
Adding replica 127.0.0.1:17500 to 127.0.0.1:17100
Adding replica 127.0.0.1:17300 to 127.0.0.1:17200
>>> Trying to optimize slaves allocation for anti-affinity
[WARNING] Some slaves are in the same host as their master
M: 1179bb5f47e7f8221ba7917b5852f8064778e0db 127.0.0.1:17000
   slots:[0-5460] (5461 slots) master
M: 153afa1b9b14194de441fffa791f8d9001badc66 127.0.0.1:17100
   slots:[5461-10922] (5462 slots) master
M: 4029aeeb6b80e843279738d6d35eee7a1adcd2ff 127.0.0.1:17200
   slots:[10923-16383] (5461 slots) master
S: 3ceb11fe492f98432f124fd1dcb7b2bb1e769a96 127.0.0.1:17300
   replicates 1179bb5f47e7f8221ba7917b5852f8064778e0db
S: 66eaea82ccf69ef96dbc16aac39fd6f6ed3d0691 127.0.0.1:17400
   replicates 153afa1b9b14194de441fffa791f8d9001badc66
S: c34aeb59c8bedc11b4aeb720b70b0019e7389093 127.0.0.1:17500
   replicates 4029aeeb6b80e843279738d6d35eee7a1adcd2ff
验证集群:
  1. 输出 redis-cli 进入任意的一个主节点,留神是主节点,从节点不能做写入操作

Redirected to slot [9189] located at 127.0.0.1:17100依据 Hash 的算法,算出连贯那个节点槽,而后提醒 slot[9189] 落到了 17100 下面,所以集群会主动跳转进行 Key 的退出

[root@iZwz99gyct1a1rh6iblyucZ bin]# ./redis-cli -p 17000
127.0.0.1:17000> set key1 1
[root@iZwz99gyct1a1rh6iblyucZ bin]# ./redis-cli -p 17000
127.0.0.1:17000> set key1 1
(error) MOVED 9189 127.0.0.1:17100
[root@iZwz99gyct1a1rh6iblyucZ bin]# ./redis-cli -p 17000 -c
127.0.0.1:17000> set key1 ke
-> Redirected to slot [9189] located at 127.0.0.1:17100
OK

小贴士:集群之后不能应用传统的连贯形式,因为每一个 key 都要通过一次 hash 的操作找到对应的槽 -》节点之后能力做后续的操作

应用如下命令进入后失常

./redis-cli -p 17000 -c

-c 代表以集群的形式连贯

  1. 能够应用如下命令验证集群的信息:
127.0.0.1:17000> cluster nodes
66eaea82ccf69ef96dbc16aac39fd6f6ed3d0691 127.0.0.1:17400@27400 slave 153afa1b9b14194de441fffa791f8d9001badc66 0 1606639411000 2 connected
4029aeeb6b80e843279738d6d35eee7a1adcd2ff 127.0.0.1:17200@27200 master - 0 1606639411000 3 connected 10923-16383
3ceb11fe492f98432f124fd1dcb7b2bb1e769a96 127.0.0.1:17300@27300 slave 1179bb5f47e7f8221ba7917b5852f8064778e0db 0 1606639410000 1 connected
1179bb5f47e7f8221ba7917b5852f8064778e0db 127.0.0.1:17000@27000 myself,master - 0 1606639410000 1 connected 0-5460
153afa1b9b14194de441fffa791f8d9001badc66 127.0.0.1:17100@27100 master - 0 1606639412002 2 connected 5461-10922
c34aeb59c8bedc11b4aeb720b70b0019e7389093 127.0.0.1:17500@27500 slave 4029aeeb6b80e843279738d6d35eee7a1adcd2ff 0 1606639413005 3 connected

  1. 接下来咱们验证一下当一个主节点挂掉会产生什么状况:

还是和主从复制的验证一样,间接 Kill 过程:

kill 掉 17000 之后,咱们能够发现 17300 被降级为主节点

127.0.0.1:17300> info replication
# Replication
role:master
connected_slaves:0

此时的节点状况如下:

127.0.0.1:17100> cluster nodes
4029aeeb6b80e843279738d6d35eee7a1adcd2ff 127.0.0.1:17200@27200 master - 0 1606640582000 3 connected 10923-16383
153afa1b9b14194de441fffa791f8d9001badc66 127.0.0.1:17100@27100 myself,master - 0 1606640581000 2 connected 5461-10922
66eaea82ccf69ef96dbc16aac39fd6f6ed3d0691 127.0.0.1:17400@27400 slave 153afa1b9b14194de441fffa791f8d9001badc66 0 1606640581000 2 connected
c34aeb59c8bedc11b4aeb720b70b0019e7389093 127.0.0.1:17500@27500 slave 4029aeeb6b80e843279738d6d35eee7a1adcd2ff 0 1606640582624 3 connected
3ceb11fe492f98432f124fd1dcb7b2bb1e769a96 127.0.0.1:17300@27300 master - 0 1606640580619 7 connected 0-5460
1179bb5f47e7f8221ba7917b5852f8064778e0db 127.0.0.1:17000@27000 master,fail - 1606640370074 1606640367068 1 disconnected
  1. 如果这时候主节点复原呢?

和哨兵的模式一样,复原之后也变为 slave 了。

集群模式优缺点:

长处:

  1. 无核心架构,数据依照 slot 散布在多个节点。
  2. 集群中的每个节点都是平等的关系,每个节点都保留各自的数据和整个集群的状态。每个节点都和其余所有节点连贯,而且这些连贯放弃沉闷,这样就保障了咱们只须要连贯集群中的任意一个节点,就能够获取到其余节点的数据。
  3. 可线性扩大到 1000 多个节点,节点可动静增加或删除
  4. 可能实现主动故障转移,节点之间通过 gossip 协定替换状态信息,用投票机制实现 slave 到 master 的角色转换

毛病:

  1. 客户端实现简单,驱动要求实现 Smart Client,缓存 slots mapping 信息并及时更新,进步了开发难度。目前仅 JedisCluster 绝对成熟,异样解决还不欠缺,比方常见的“max redirect exception”
  2. 节点会因为某些起因产生阻塞(阻塞工夫大于 cluster-node-timeout)被判断下线,这种 failover 是没有必要的
  3. 数据通过异步复制,不保证数据的强一致性
  4. slave 充当“冷备”,不能缓解读压力
  5. 批量操作限度,目前只反对具备雷同 slot 值的 key 执行批量操作,对 mset、mget、sunion 等操作反对不敌对
  6. key 事务操作反对有线,只反对多 key 在同一节点的事务操作,多 key 散布不同节点时无奈应用事务性能
  7. 不反对多数据库空间,单机 redis 能够反对 16 个 db,集群模式下只能应用一个,即 db 0

Redis Cluster 模式不倡议应用 pipeline 和 multi-keys 操作,缩小 max redirect 产生的场景。

cluster 的相干疑难

为什么 redis 的槽要用 16384

值得快乐的是:这个问题作者出门答复了:

能了解作者意思的能够不必看上面的内容

地址:https://github.com/redis/redi…

The reason is:

Normal heartbeat packets carry the full configuration of a node, that can be replaced in an idempotent way with the old in order to update an old config. This means they contain the slots configuration for a node, in raw form, that uses 2k of space with16k slots, but would use a prohibitive 8k of space using 65k slots.
At the same time it is unlikely that Redis Cluster would scale to more than 1000 mater nodes because of other design tradeoffs.
So 16k was in the right range to ensure enough slots per master with a max of 1000 maters, but a small enough number to propagate the slot configuration as a raw bitmap easily. Note that in small clusters the bitmap would be hard to compress because when N is small the bitmap would have slots/N bits set that is a large percentage of bits set.
  1. 首先咱们查看一下构造体,对于 cluster 的源代码:cluster.h

代码如下:

typedef struct {char sig[4];        /* Signature "RCmb" (Redis Cluster message bus). */
    uint32_t totlen;    /* Total length of this message */
    uint16_t ver;       /* Protocol version, currently set to 1. */
    uint16_t port;      /* TCP base port number. */
    uint16_t type;      /* Message type */
    uint16_t count;     /* Only used for some kind of messages. */
    uint64_t currentEpoch;  /* The epoch accordingly to the sending node. */
    uint64_t configEpoch;   /* The config epoch if it's a master, or the last
                               epoch advertised by its master if it is a
                               slave. */
    uint64_t offset;    /* Master replication offset if node is a master or
                           processed replication offset if node is a slave. */
    char sender[CLUSTER_NAMELEN]; /* Name of the sender node */
    unsigned char myslots[CLUSTER_SLOTS/8];
    char slaveof[CLUSTER_NAMELEN];
    char myip[NET_IP_STR_LEN];    /* Sender IP, if not all zeroed. */
    char notused1[34];  /* 34 bytes reserved for future usage. */
    uint16_t cport;      /* Sender TCP cluster bus port */
    uint16_t flags;      /* Sender node flags */
    unsigned char state; /* Cluster state from the POV of the sender */
    unsigned char mflags[3]; /* Message flags: CLUSTERMSG_FLAG[012]_... */
    union clusterMsgData data;
} clusterMsg;

集群节点之间的通信内容无非就是 IP 信息,申请头,申请内容,以及一些参数信息,这里着重看一下参数myslots[CLUSTER_SLOTS/8]

define CLUSTER_SLOTS 16384 这里就是 16384 的起源

在 redis 节点发送心跳包时须要把所有的槽放到这个心跳包里,以便让节点晓得以后集群信息,16384=16k,在发送心跳包时应用 char 进行 bitmap 压缩后是 2k(2 * 8 (8 bit) * 1024(1k) = 2K),也就是说应用 2k 的空间创立了 16k 的槽数。

尽管应用 CRC16 算法最多能够调配 65535(2^16-1)个槽位,65535=65k,压缩后就是 8k(8 * 8 (8 bit) * 1024(1k) = 8K),也就是说须要须要 8k 的心跳包,作者认为这样做不太值得;并且个别状况下一个 redis 集群不会有超过 1000 个 master 节点,所以 16k 的槽位是个比拟适合的抉择。

参考资料:

https://juejin.cn/post/684490…

https://juejin.cn/post/684490…

为什么 Redis 集群有 16384 个槽

正文完
 0