Redis主从复制
首先需要设置一个master节点,两个slave节点,然后修改各自的redis.conf,让两个slave节点指向主master节点:
(1)设置master节点的port=7000,bind=0.0.0.0
(2)分别设置两个slave节点的port为7001和7002,同时bind=0.0.0.0
(3)在slave节点上开启主从复制——修改Replicof选项:
1 | replicaof 192.168.193.129 7000 |
(4)定位到redis-server安装目录(ubuntu使用apt install默认安装在/usr/bin
位置),然后使用以下命令:
1 | ./redis-server /home/cat/master/redis.conf #启动主master节点 |
结果如下:
也可以在客户端redis-cli下登录master节点查看结果:
1 | 127.0.0.1:6379> info replication |
在主节点设置两个key后,可以看出slave节点上也会自动同步相应的数据:
注意:从节点不负责请求处理,只负责同步主节点数据,即只读,因此默认情况下在slave节点上修改数据是不被允许的
1 | 127.0.0.1:7002> set age 24 |
且一旦master节点宕机,从节点也不能替代成为新的主节点(会一直报错):
1 | 29017:C 03 Jan 2023 22:50:58.074 # Failed opening the RDB file dump.rdb (in server root dir /usr/bin) for saving: Permission denied |
从节点仅作备份可用性不高,因此接下来介绍redis提供的哨兵机制:
哨兵机制
Sentinel(哨兵)是Redis 的高可用性解决方案:由一个或多个Sentinel实例组成的Sentinel 系统可以监视任意多个主服务器,以及这些主服务器属下的所有从服务器,并在被监视的主服务器进入下线状态时,自动将下线主服务器属下的某个从服务器升级为新的主服务器。简单的说哨兵就是带有自动故障转移
功能的主从架构。即当一个master节点的redis服务挂掉后,sentinel机制会发现, 并从剩余的slave节点的redis服务中, 选举出一个slave, 来充当新的master节点,并让其他存活slave节点指向新的master节点,当原master节点复活后自动降级为slave节点同样指向新master节点。
修改/etc/redis目录下的sentinel.conf配置文件(该配置文件对应默认端口号为6379的主节点),编辑内容如下:
1 | port 26379 # sentinel节点端口 |
查看redis服务,可以发现第一个哨兵已经运行在26379端口了:
1 | (base) cat@cat-virtual-machine:~/桌面$ ps -ef | grep redis |
1 | 4983:X 04 Jan 2023 18:56:43.168 # Sentinel ID is aa3d45daf2d6576fdf3d61a605cc2ca860930c32 |
且该哨兵所对应的sentinel.conf内容已经被自动修改:
1 | sentinel myid aa3d45daf2d6576fdf3d61a605cc2ca860930c32 |
切换主节点
配置哨兵前,如果从节点想要修改会提示无权限(仅有复制权限):
1 | 127.0.0.1:7001> set country france |
配置哨兵后,让master节点宕机—执行kill -9 4204
命令,然后slave1节点上执行数据修改操作会发现操作成功(即该节点已经成为新的主节点):
1 | 127.0.0.1:7001> set age 24 |
Redis集群
前面介绍了redis主从复制架构,知道了该工作模式下提供多台redis服务,选择其中的一台作为master节点向外提供读写服务,剩下的作为slave节点从master节点复制数据,只向外提供读服务。随后引入了Redis哨兵机制,实现了对所有redis节点的监控和master的自动故障转移。一般情况下来说,上面两种方式结合起来使用已经可以满足大部分的redis高可用场景,但它有一个很明显的缺点:只有一台master节点向外提供写服务,其他的slave节点只能提供读服务。所以,当写操作并发量很大的,无法缓解写操作的压力。针对这种场景,Redis在3.0版本中引入了Redis集群的部署架构
集群特性
(1) Redis集群是一个提供在多个Redis节点之间共享数据的程序集。它并不像Redis主从复制模式那样只提供一个master节点提供写服务,而是会提供多个master节点提供写服务,每个master节点中存储的数据都不一样,这些数据通过数据分片的方式被自动分割到不同的master节点上
(2)为了保证集群的高可用,每个master节点下面还需要添加至少1个slave节点,这样当某个master节点发生故障后,可以从它的slave节点中选举一个作为新的master节点继续提供服务(哨兵机制)。不过当某个master节点和它下面所有的slave节点都发生故障时,整个集群就不可用了
(3)节点的失效fail是通过集群中超过半数节点检测失效时才生效,且客户端与redis集群中节点直连,不需要中间代理proxy
(4)哈希槽:Redis集群中引入了哈希槽的概念,Redis集群有16384个哈希槽,进行set操作时,每个key会通过CRC16校验后再对16384取模来决定放置在哪个槽,搭建Redis集群时会给集群中每个master节点分配一部分哈希槽(因此redis集群中最大节点数为16384个)。比如当前集群有3个master节点,master1节点包含05500号哈希槽,master2节点包含550111000号哈希槽,master3节点包含11001~16384号哈希槽,当我们执行“set key value”时,假如 CRC16(key) % 16384
= 777,那么这个key就会被分配到master1节点上。某个物理节点由于故障进行主从切换时不涉及到哈希槽的重分配,而如果动态新增master物理节点时则会对哈希槽进行重新分配,且移动槽的过程中也会移动value
(5)集群中节点的通信:既然Redis集群中的数据是通过哈希槽的方式分开存储的,那么集群中每个节点都需要知道其他所有节点的状态信息,包括当前集群状态、集群中各节点负责的哈希槽、集群中各节点的master-slave状态、集群中各节点的存活状态等。Redis集群中,节点之间通过建立TCP连接,使用gossip协议来传播集群的信息,所谓gossip协议,指的是一种消息传播的机制,类似人们传递八卦消息似的,一传十,十传百,直至所有人都知道这条八卦内容。Redis集群中各节点之间传递消息就是基于gossip协议,最终达到所有节点都会知道整个集群完整的信息。gossip协议有4种常用的消息类型:PING、PONG、MEET、FAIL
集群搭建
搭建redis集群至少需要6个节点(3个master及其各自附属的slave节点)
搭建集群需要先安装相应依赖:
1
2apt-get install -y ruby
gem install redis新建7个目录保存各个节点,然后修改各个节点的配置文件(以/cluster/8000/redis.conf为例):
1
2
3
4
5
6
7
8
942 daemonize yes #以后台守护方式运行
46 pidfile "/var/run/redis/redis_8000.pid" #pid文件位置
50 port 8000 #监听端口
509 appendonly yes #以追加方式存储数据
513 appendfilename "appendonly8000.aof" #存储数据的文件
637 cluster-enabled yes #开启集群模式
645 cluster-config-file nodes-8000.conf #节点文件
651 cluster-node-timeout 5000 #节点超时时间然后启动这7个节点:
1
2
3
4
5
6
7
8
9
10root@cat-virtual-machine:/home/cat/cluster# ps -ef|grep redis
root 6552 1048 0 21:27 ? 00:00:00 redis-server 0.0.0.0:8000 [cluster]
root 6558 1048 0 21:27 ? 00:00:00 redis-server 0.0.0.0:8001 [cluster]
root 6564 1048 0 21:27 ? 00:00:00 redis-server 0.0.0.0:8002 [cluster]
root 6573 1048 0 21:27 ? 00:00:00 redis-server 0.0.0.0:8003 [cluster]
root 6579 1048 0 21:27 ? 00:00:00 redis-server 0.0.0.0:8004 [cluster]
root 6585 1048 0 21:27 ? 00:00:00 redis-server 0.0.0.0:8005 [cluster]
root 6591 1048 0 21:27 ? 00:00:00 redis-server 0.0.0.0:8006 [cluster]
root 6598 5508 0 21:27 pts/3 00:00:00 grep --color=auto redis将redis-trib.rb复制到 /usr/bin目录下:
1
2
3
4
5
6
7
8
9cp /usr/share/doc/redis-tools/examples/redis-trib.rb /usr/bin/redis-trib.rb
redis-trib.rb create --replicas 1 192.168.193.129:8000 192.168.193.129:8001 192.168.193.129:8002 192.168.193.129:8003 192.168.193.129:8004 192.168.193.129:8005 (旧版本redis)
replicas参数后面的1表示每个master节点有一个slave从节点, 且默认前三个地址对应的节点为主节点,后三个为从节点
ps:新版本redis使用以下命令创建集群:redis-cli --cluster SUBCOMMAND [ARGUMENTS] [OPTIONS]
例如 redis-cli --cluster create 192.168.193.129:8000 192.168.193.129:8001 192.168.193.129:8002 192.168.193.129:8003 192.168.193.129:8004 192.168.193.129:8005 --cluster-replicas 1 -a emei268
在执行完上述命令后,会输出以下结果:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24root@cat-virtual-machine:/home/cat/cluster# redis-cli --cluster create 192.168.193.129:8000 192.168.193.129:8001 192.168.193.129:8002 192.168.193.129:8003 192.168.193.129:8004 192.168.193.129:8005 --cluster-replicas 1 -a emei268
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 192.168.193.129:8004 to 192.168.193.129:8000
Adding replica 192.168.193.129:8005 to 192.168.193.129:8001
Adding replica 192.168.193.129:8003 to 192.168.193.129:8002
>> Trying to optimize slaves allocation for anti-affinity
[WARNING] Some slaves are in the same host as their master
M: 208dc519f5a74aae11915d1511dd7ff3624ffe7a 192.168.193.129:8000
slots:[0-5460] (5461 slots) master
M: ea5afe7e4e9468ee336f3da99dd67e7e7d5f9840 192.168.193.129:8001
slots:[5461-10922] (5462 slots) master
M: b5fa4e4f6c7c145393f4c968c9419d9298fa087d 192.168.193.129:8002
slots:[10923-16383] (5461 slots) master
S: 1793e4730091fcbb1c3c919b80aa372f0d5b75fe 192.168.193.129:8003
replicates 208dc519f5a74aae11915d1511dd7ff3624ffe7a
S: a200f785d7e51965a548f324b24caf0a2192d609 192.168.193.129:8004
replicates ea5afe7e4e9468ee336f3da99dd67e7e7d5f9840
S: dd107b4890ef4f51b7a284395b9b97c9d4ca4a40 192.168.193.129:8005
replicates b5fa4e4f6c7c145393f4c968c9419d9298fa087d
输出以上结果说明集群已经创建成功啦
集群测试
1 | 127.0.0.1:8000> set name lingard |
往集群里放入值时会先做重定向(crc16+hash映射槽),同样取值的时候也会做redirect操作
1 | python segment/predict.py --weights yolov7-seg.pt --source "videopath.mp4" |