redis 集群维护与Memcache高可用(小节7)
集群维护之动态删除节点
添加节点的时候是先添加node节点到集群,然后分配槽位,删除节点的操作与添加节点的操作正好相反,是先将被删除的 Redis node 上的槽位迁移到集群中的其他Redis node节点上,然后再将其删除。
如果一个Redis node节点上的槽位没有完全迁移,删除该node的时候会提示有数据且无法删除。
案例:
由于192.168.1.101 服务器使用年限已经超过三年,已经超过厂商质保期而且硬盘出现异常报警,经运维部提交方案并同开发同事开会商议,决定将现有 redis 集群的4台主服务器分别是 192.168.1.101/192.168.1.102/192.168.1.103/192.168.1.104/ 中的 192.168.1.103 临时下架,三台服务器的并发写入性能足够支持未来 1-2 年的业务需求,则删除 redis node 192.168.1.103 的操作如下:
迁移 mstart 的槽位至其他 mstart
被迁移 redis master 源服务器必须保证没有数据,否则迁移报错并会被强制中断。
101
如:把103 master下线
#确保103 master中没有数据
~]# redis-cli -h 192.168.1.103
192.168.1.103:6379> AUTH 123
OK
192.168.1.103:6379> KEYS *
(empty list or set)
重新做分片
~]# redis-trib.rb reshard 192.168.1.101:6379
>>> Performing Cluster Check (using node 192.168.1.101:6379)
M: f5f52b77c9057b2a8873a3d0b0c338de289c2552 192.168.1.101:6379
slots:1365-5460 (4096 slots) master
1 additional replica(s)
M: 9e7797f3a378b26421dc72ee1fe232a5616e073d 192.168.1.107:6379 <--107的ID、注2
slots:0-1364,5461-6826,10923-12287 (4096 slots) master
1 additional replica(s)
S: 8fe1dbdfb8e83ad7877b01f141db91701010483e 192.168.1.105:6379
slots: (0 slots) slave
replicates f5f52b77c9057b2a8873a3d0b0c338de289c2552
S: 36490069c66704baf5a0876ab7498f587d62f8ff 192.168.1.104:6379
slots: (0 slots) slave
replicates 60daad974abdc9057ef740dec8f33a13a49f44e2
M: 70a567ded84d43be0a7028e8186fa4085cd087f7 192.168.1.102:6379
slots:6827-10922 (4096 slots) master
1 additional replica(s)
M: 60daad974abdc9057ef740dec8f33a13a49f44e2 192.168.1.103:6379 <--103的ID、注意3
slots:12288-16383 (4096 slots) master <--槽位、注1
1 additional replica(s)
S: c09b3cd75041061baaf02df8707df841663d051a 192.168.1.106:6379
slots: (0 slots) slave
replicates 70a567ded84d43be0a7028e8186fa4085cd087f7
S: e812fe58bc3edb56635f151cece0176ab1ce6835 192.168.1.108:6379
slots: (0 slots) slave
replicates 9e7797f3a378b26421dc72ee1fe232a5616e073d
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
How many slots do you want to move (from 1 to 16384)? 4096 <--槽位、注1
What is the receiving node ID? 9e7797f3a378b26421dc72ee1fe232a5616e073d <--迁移到107上、所以写107的ID、注2
Please enter all the source node IDs.
Type 'all' to use all the nodes as source nodes for the hash slots.
Type 'done' once you entered all the source nodes IDs.
Source node #1:60daad974abdc9057ef740dec8f33a13a49f44e2 <--迁移主机的ID 此处是103的ID、注意3
Source node #2:done <--结束
...
Moving slot 16383 from 60daad974abdc9057ef740dec8f33a13a49f44e2
Do you want to proceed with the proposed reshard plan (yes/no)? yes <--是否确认
...
Moving slot 16382 from 192.168.1.103:6379 to 192.168.1.107:6379:
Moving slot 16383 from 192.168.1.103:6379 to 192.168.1.107:6379:
再次查看103的槽位没有了、全部迁移到107上
~]# redis-trib.rb check 192.168.1.101:6379
删除集群中的主机
~]# redis-trib.rb del-node 192.168.1.101:6379 60daad974abdc9057ef740dec8f33a13a49f44e2
>>> Removing node 60daad974abdc9057ef740dec8f33a13a49f44e2 from cluster 192.168.1.101:6379
>>> Sending CLUSTER FORGET messages to the cluster...
>>> SHUTDOWN the node.
103没有了
~]# redis-trib.rb check 192.168.1.101:6379
再下线103的slave、也就是104
~]# redis-trib.rb del-node 192.168.1.101:6379 36490069c66704baf5a0876ab7498f587d62f8ff
>>> Removing node 36490069c66704baf5a0876ab7498f587d62f8ff from cluster 192.168.1.101:6379
>>> Sending CLUSTER FORGET messages to the cluster...
>>> SHUTDOWN the node.
104也没有了
~]# redis-trib.rb check 192.168.1.101:6379
集群维护之模拟 master 宕机
目前架构三主三从,互为跨主机 master slave 模式,测试 master 宕机之后是否会自动切换至slave。
105
查看105从节点信息
~]# redis-cli
127.0.0.1:6379> AUTH 123
OK
127.0.0.1:6379> info Replication
# Replication
role:slave
master_host:192.168.1.101 <--此时主还是 101
master_port:6379
master_link_status:up <--
master_last_io_seconds_ago:9
master_sync_in_progress:0
slave_repl_offset:1246
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:f6db2223d13da3ca97803ee1013a7a44260c005a
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:1246
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:43
repl_backlog_histlen:1204
101
把101关闭
~]# systemctl stop redis
105
看会不会接管101的master
~]# tail -f /apps/redis/log/redis.log
...
11792:S 08 Dec 20:42:12.101 # Error condition on socket for SYNC: Connection refused
11792:S 08 Dec 20:42:12.907 # Starting a failover election for epoch 10.
11792:S 08 Dec 20:42:12.912 # Failover election won: I'm the new master. <--成为新的master
11792:S 08 Dec 20:42:12.912 # configEpoch set to 10 after successful failover
11792:M 08 Dec 20:42:12.912 # Setting secondary replication ID to f6db2223d13da3ca97803ee1013a7a44260c005a, valid up to offset: 1471. New replication ID is 422648a10e882945000450f26446a3546f09b7a2
11792:M 08 Dec 20:42:12.912 * Discarding previously cached master state.
11792:M 08 Dec 20:42:12.912 # Cluster state changed: ok
105已经接管101、变成了master
~]# redis-cli
127.0.0.1:6379> AUTH 123
OK
127.0.0.1:6379> info Replication
# Replication
role:master <--变成了master
connected_slaves:0
master_replid:422648a10e882945000450f26446a3546f09b7a2
master_replid2:f6db2223d13da3ca97803ee1013a7a44260c005a
master_repl_offset:1470
second_repl_offset:1471
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:43
repl_backlog_histlen:1428
reidis 扩展集群方案
除了redis官方自带的redis cluster集群之外,还有一些开源的集群解决方案可供参考使用。
codis
Codis 是一个分布式 redis 解决方案,对于上层的应用来说,连接到 Codis Proxy 和连接原生的 redis server 没有明显的区别 (不支持的命令列表),上层应用可以像使用单机的 Redis 一样使用,Codis 底层会处理请求的转发,不停机的数据迁移等工作,所有后边的一切事情,对于前面的客户来说是透明的,可以简单的认为后边连接的是一个内存无限大的Redis服务:
Codis是豌豆荚的开源方案,目前在redis集群实现方式对比,codis集群比较稳定的方案,并且客户端不需要做任何修改,相对redis cluster兼容性更强,可节约大量开发成本并减少大量后期维护成本,豌豆荚githab地址:github.com/pingcap,豌豆荚….
memcached
memcache 官网: memcached.org
memcache 本身没有像redis所具备的数据持久化功能,比如RDB和AOF都没有,但是可以通过做集群同步的方式,让各memcache服务器的数据进行同步,从而实现数据的一致性,即保证各memcache的数据是一样的,即使有任何一台memcache发生故障,只有集群中有一台memcache可用就不会出现数据丢失,当其他memcache重新加入到集群的时候可以自动从有数据的memcache当中自动获取数据并提供服务。memcache借助了操作系统的libevent工具做高效的读写。libevent是个程序库,它将linux的epol、BSD类操作系统的kqueue等事件处理功能封装成统一的接口。即使对服务器的连接数增加,也能发挥高性能。memcache的使用这个libevent库,因此能在Linux、BSD、Solaris等操作系统上发挥其高性能。
memcache支持最大的内存存储对象为1M,超过1M的数据可以使用客户端压缩或拆分报文放到多个key中,比较大的数据在进行读取的时候需要消耗的时间比较长,memcache最适合保存用户的session实现session共享,memcached存储数据时,memcached会去申请1MB的内存,把该块内存称为1个slab,也成为一个page,memcached具有多种语言的客户端开发包,包括:Perl\PHP\JAVA\C\Python\Ruby\C#
repcached 实现原理
在master上可以通过 -X 指定 replication port,在 slave 上通过 -x/-X 找到 master 并 connect 上去,事实上,如果同时指定了 -x/-X ,repcached 一定会尝试连接,但如果连接失败,它就会用 -X 参数来自己 listen (成为 master);如果 master 坏掉, master 也会侦测到连接端,它就会重新 listen 等待新的 slave 加入。
从这方案的技术实现来看,其实它是一个但 master 单 slave 的方案,但它的 master/slave 都是可读写的,而且可以相互同步,所以从功能上看,也可以认为它是双机 master-master 方案。
101和102
部署repcached
repcached网址:repcached.sourceforge.net/
~]# yum install -y libevent libevent-devel
上传安装包repcached
~]# ll
-rw-r--r-- 1 root root 228578 Dec 9 2022 memcached-1.2.8-repcached-2.2.1.tar.gz
解压缩
~]# tar xvf memcached-1.2.8-repcached-2.2.1.tar.gz
编译安装
~]# cd memcached-1.2.8-repcached-2.2.1/
memcached-1.2.8-repcached-2.2.1]# ./configure --prefix=/usr/local/repcached --enable-replication
memcached-1.2.8-repcached-2.2.1]# make #会报错、看下图及解决办法
解决办法:
memcached-1.2.8-repcached-2.2.1]# vim memcached.c
#删除56-60行内容
56 #ifndef IOV_MAX
57 #if defined(__FreeBSD__) || defined(__APPLE__)
58 # define IOV_MAX 1024
59 #endif
60 #endif
#改为如下内容
56 #ifndef IOV_MAX
57 # define IOV_MAX 1024
58 #endif
#再次编译安装
memcached-1.2.8-repcached-2.2.1]# make
memcached-1.2.8-repcached-2.2.1]# make install
启动memcache
通过repcached 安装的 memcached 命令启动 memcache 服务并实现 memcache 主备结构,其中 -x 为对方即主 memcache 的IP, -X为本地启动的用数据同步的端口:
-d 放在后台 -m 2048 内存2G -P 11211 端口 -u root 用户 -c 最大连接数 -x 对方 memcache 的 IP -X 1600 同步的端口
101
memcached-1.2.8-repcached-2.2.1]# /usr/local/repcached/bin/memcached -d -m 2048 -p 11211 -u root -c 4096 -x 192.168.1.102
102
memcached-1.2.8-repcached-2.2.1]# /usr/local/repcached/bin/memcached -d -m 2048 -p 11211 -u root -c 4096 -x 192.168.1.101
101和102
查看端口
memcached-1.2.8-repcached-2.2.1]# ss -ntlp|grep 11211
LISTEN 0 1024 *:11211 *:* users:(("memcached",pid=16174,fd=9))
LISTEN 0 1024 :::11211 :::* users:(("memcached",pid=16174,fd=10))