前两天写了一篇文章《从零搭建Redis Cluster分片集群》,但是在实际部署的过程中,还是发现了很多问题。主要集中在Redis Cluster分片迁移Slot和Redis主从同步数据两个方面。
Redis Cluster集群数据迁移
Redis Cluster搭建好以后涉及到划分Slot槽位和迁移数据。一般情况下如果是新建的一套Redis Cluster集群就不会涉及到该问题。但是如果项目之前已经在运行Redis,需要把原redis的数据导入新的Redis Cluster集群中。
Redis Cluster数据导入
默认情况下使用以下命令:
./redis-cli -a Mypassword --cluster import 10.16.99.157:6379 --cluster-from 10.16.99.133:6379 --cluster-from-pass Mypassword --cluster-replace
其中10.16.99.157
是集群中的一个主节点,10.16.99.133
是原Redis服务器。然而在实际数据迁移过程中,由于原redis服务器内存不足,迁移到一半,服务器就崩了。使用以下命令在原服务器上可以看出由于内存耗尽,Redis服务被强制退出:
dmesg -T | egrep -i -B100 “killed process” out of memory, Killed process
Redis Cluster主节点数据导入
如果无法直接从原Redis服务器把数据导入至Redis Cluster集群。那么我们可以使用另外一种方案。首先需要先将所有的slot移动到一台主节点上,随后把旧数据通过rdb文件导入到该主节点。然而,如果原有的Redis服务器没有开启RDB,只能尝试连入Redis以后,使用bgsave在后台做Redis备份,正常情况下,20分钟以内可以完成。
BGSAVE持久化失败
但是在生产环境中却不是那么回事。在Redis中执行RDB,结果显示失败,应该还是内存不足导致子进程被强制关闭。
因此,我尝试开启AOF模式。在Redis Cli中执行:
config set appendonly yes
正常情况下,大约也需要20分钟才能完成。
心得
在Redis服务器内存不足的情况下,是否能够持久化成功,完全就看运气。因为不能停机,所以无法升级服务器的内存,只能想办法删除占用内存大的主键,具体方法后文中会提到。
对现有数据进行分片和移动槽位
接下来,我把RDB数据拷贝到新Redis集群的主节点上后,重启Redis主节点读取持久化的数据,并通过以下命令重新分片:
./redis-cli -a Mypassword --cluster reshard 10.16.99.157:6379
上述命令会询问要移动多少个slot(范围是1到16383),来源主节点和目标主节点等信息。随后会自动迁移Slot到目标节点中。然而在自动分片迁移的过程中,分片的主节点又崩了。目前最大的问题是,当前服务器是8核32G的云主机,Redis启动以后使用了31G内存,以下是当前内存状态:
因此在目前情况下,只有想办法提升主机的内存或者减少Redis的内存使用才能顺利分片。如果条件允许,可以购买同区域的64G内存的服务器,并加入到Redis集群中。在实际操作中,我通过扫描Redis中的所有主键并检查每个主键的内存使用情况,最后决定删除无效主键从而降低Redis的内存使用。
rc_end = [] try: rc_end = rc.scan_iter("*") except Exception as e: print(e) for key in rc_end: size = 0 memory = rc.memory_usage(key) keyType = rc.type(key) if keyType == b'set': size = rc.scard(key) elif keyType == b'zset': size = rc.zcard(key) print(f"info:{key.decode('utf-8')}\t{size}\t{memory}")
随后使用bash命令行把数据格式化成csv文件,并分析哪个主键占用了较大的内存空间,删除掉无用的主键即可。
grep 'info:' a.log | sed 's/.*info://' > slots1.txt
Slot过大导致迁移超时
在迁移的过程中又遇到新的问题。有一个槽位迁移过程中卡住了,最终导致迁移超时分片失败。在我遇到的情况中,其中一个set类型的key中有79,492,879个值,使用约6G内存。目前决定暂不迁移这个槽位,以下是检查该槽位的一个方法步骤:
- 查看槽位4000中有多少个主键:
CLUSTER COUNTKEYSINSLOT 4000
CLUSTER GETKEYSINSLOT 4000 3
MEMORY USAGE key
总结
Redis集群分片和槽位移动直接影响到每一个主节点的内存占用情况。如果槽位划分不均匀,或者某一个槽位中的主键规模非常大,就很可能导致该节点内存使用量过大。因此,在实际项目中,要时长关注Redis的内存使用情况,对于内存使用量飙升的Redis主节点,要检查槽位情况和主键情况。
相关文档
Redis Reshard机制:http://redisdoc.com/topic/cluster-spec.html#live-reconfiguration
Redis槽位操作文档:https://redis.io/commands/cluster-setslot
Redis主键迁移文档:https://redis.io/commands/migrate
扫码联系船长