最近我们团队在做Redis版本升级的准备工作。虽然Redis 8.0还在开发中,但根据官方发布的路线图和预览版,我们提前做了迁移方案的设计和测试。
Redis是我们系统中非常重要的组件,缓存、会话、排行榜、分布式锁、消息队列都在用。迁移Redis版本是一个高风险的操作,稍有不慎就会影响线上业务。这篇文章,我想分享一下我们的Redis迁移方案和实战经验,给需要做类似迁移的朋友一个参考。
为什么要迁移
先说说为什么要做Redis版本迁移。
我们目前线上用的是Redis 6.x,已经用了好几年了。虽然运行稳定,但新版本的Redis有很多我们需要的新特性和改进。
根据Redis官方的路线图,Redis 8.0预计会带来这些重要的变化:
第一个是,性能提升。新版本在多线程IO、内存管理、查询优化等方面都有改进,尤其是在高并发场景下,性能会有明显提升。
第二个是,新的数据类型和命令。新版本可能会引入新的数据结构,或者增强现有数据类型的功能。比如对Hash、Set、Sorted Set的增强,以及新的命令。
第三个是,安全增强。新版本会加强安全特性,比如更细粒度的权限控制、更好的加密支持、默认更安全的配置。
第四个是,可观测性提升。新版本会增强监控和诊断能力,提供更多的指标和日志,方便排查问题。
第五个是,长期支持。旧版本的Redis会逐渐停止维护,升级到新版本可以获得长期的支持和安全更新。
当然,迁移也有风险。新版本可能有不兼容的变化,可能有新的bug,迁移过程中可能有数据丢失或者服务中断。所以,我们需要一个完善的迁移方案,把风险降到最低。
迁移前的准备
迁移前的准备工作非常重要,准备得越充分,迁移的风险就越低。
第一步是,了解新版本的变化。我们仔细阅读了Redis官方的发布说明、迁移指南、不兼容变更列表。把所有可能影响我们的变化都列出来,逐一评估影响。
比如,某些命令被废弃了,某些配置项的默认值变了,某些数据结构的行为变了。这些变化,都需要在迁移前搞清楚,提前做好适配。
第二步是,评估业务影响。我们梳理了所有使用Redis的业务场景,包括:
- 缓存:哪些数据存在Redis里,过期策略是什么,缓存击穿/穿透/雪崩的防护措施。
- 会话:用户会话存在Redis里,迁移过程中不能丢失,否则用户会掉线。
- 排行榜:用Sorted Set实现的排行榜,数据一致性要求高。
- 分布式锁:用Redis实现的分布式锁,迁移过程中不能出现锁失效或者重复获取的问题。
- 消息队列:用Redis List或者Stream实现的消息队列,迁移过程中不能丢消息。
每个场景,我们都评估了迁移过程中可能出现的问题,以及对应的应对措施。
第三步是,准备测试环境。我们搭建了和生产环境一样的测试环境,包括相同的Redis版本、相同的配置、相同的数据量。在测试环境中反复演练迁移流程,发现问题及时调整。
第四步是,制定回滚方案。迁移不可能百分之百成功,必须有回滚方案。如果迁移后出现问题,能快速回滚到旧版本,把影响降到最低。回滚方案要提前演练,确保回滚流程顺畅。
第五步是,选择迁移时间。我们会选择业务低峰期进行迁移,比如凌晨或者周末。这样即使出问题,影响的用户也比较少。同时,提前通知相关人员,做好应急准备。
迁移方案
我们考虑了几种迁移方案,最终选择了"主从复制+切换"的方案。
方案的大致流程是:
- 搭建新版本的Redis实例,作为旧版本Redis的从库。
- 旧版本Redis的数据通过主从复制同步到新版本Redis。
- 等待数据同步完成,新旧版本的数据一致。
- 在业务低峰期,把应用的连接切换到新版本Redis。
- 观察一段时间,确认新版本运行正常。
- 下线旧版本Redis。
这个方案的优点是:
- 迁移过程中服务不中断,用户无感知。
- 数据一致性有保障,主从复制保证数据同步。
- 可以随时回滚,如果新版本有问题,切换回旧版本即可。
- 可以先在新版本上做验证,确认没问题再切换。
当然,这个方案也有一些前提条件:
- 旧版本Redis支持作为主库,新版本Redis支持作为从库。一般来说,Redis支持跨大版本的主从复制,但需要确认。
- 迁移过程中,旧版本Redis的写入量不能太大,否则主从同步可能跟不上。如果写入量很大,可能需要先做读写分离,把读流量切到新版本,再切写流量。
- 应用层要支持快速切换Redis连接,比如用配置中心或者DNS切换。
迁移的具体步骤
下面详细说说迁移的具体步骤。
第一步,搭建新版本Redis实例。
在新的服务器上安装新版本的Redis,配置好参数。配置要和旧版本保持一致,比如内存大小、持久化策略、最大连接数、慢查询阈值等。同时,根据新版本的变化,调整不兼容的配置项。
配置好之后,启动新版本Redis,确认服务正常运行。用redis-cli连接上去,执行info命令,查看版本和运行状态。
第二步,配置主从复制。
在新版本Redis上执行replicaof命令,把它设置为旧版本Redis的从库。比如:
replicaof old-redis-host 6379
如果旧版本Redis设置了密码,还要配置masterauth。
配置好之后,新版本Redis会开始从旧版本同步数据。先全量同步(RDB文件),然后增量同步(命令传播)。
第三步,监控同步进度。
用info replication命令查看主从复制的状态。关注几个指标:
- masterlinkstatus:是否是up状态。
- masterlastiosecondsago:主从之间最后一次IO的时间,正常应该是0或1。
- mastersyncin_progress:是否正在全量同步。
- slavereploffset:从库的复制偏移量,应该和主库接近。
等待全量同步完成,增量同步跟上,主从数据一致。这个过程的时间取决于数据量的大小和网络带宽。我们的数据量大概是几十GB,全量同步花了十几分钟。
第四步,验证数据一致性。
主从同步完成之后,要验证新旧版本的数据是否一致。我们用了几种方法:
- 用redis-cli的dbsize命令,对比新旧版本的key数量。
- 随机抽取一些key,对比新旧版本的值是否一致。
- 用一些业务场景做验证,比如读取排行榜、读取用户会话,确认数据正确。
如果发现数据不一致,要排查原因,可能是同步还没完成,或者有大key导致同步延迟。
第五步,切换应用连接。
数据一致之后,就可以切换应用的连接了。我们用的是配置中心,把Redis的地址从旧版本改成新版本,然后刷新配置,应用会自动重连到新版本。
切换的时候要注意:
- 先切一小部分流量,观察新版本的运行情况。
- 确认没有问题之后,再全量切换。
- 切换过程中,监控应用的错误率、响应时间、Redis的命令处理量等指标。
- 如果出现问题,立即切回旧版本。
第六步,观察和验证。
切换完成之后,要持续观察一段时间。我们观察了24小时,确认新版本运行正常。关注的指标包括:
- Redis的CPU、内存、网络、连接数。
- 命令的响应时间,尤其是慢查询。
- 主从复制的状态(如果新版本也有从库的话)。
- 应用的错误率和业务指标。
同时,做一些业务验证,比如用户登录、下单、查询排行榜等,确认功能正常。
第七步,下线旧版本。
观察一段时间确认没问题之后,就可以下线旧版本Redis了。下线之前,再做一次数据备份,以防万一。然后停止旧版本Redis,释放服务器资源。
迁移中遇到的问题
迁移过程中,我们遇到了一些问题,在这里分享一下。
第一个问题是,大key导致全量同步慢。我们有一个大key,存了几百万个元素,全量同步的时候,这个key的传输花了很长时间,导致同步延迟。
解决方法是,在迁移前把大key拆分成小key,或者用scan命令分批迁移。我们最后是提前拆分了大key,迁移就顺利了。
第二个问题是,配置项不兼容。新版本Redis有一些配置项的默认值变了,比如maxmemory-policy的默认值、slowlog-log-slower-than的默认值。如果不注意,可能会导致行为不一致。
解决方法是,仔细对比新旧版本的配置,把关键的配置项显式设置成和旧版本一致,避免默认值变化带来的影响。
第三个问题是,客户端版本不兼容。我们用的一些Redis客户端库,版本比较旧,对新版本Redis的某些命令支持不好。
解决方法是,升级客户端库到最新版本,或者在迁移前做兼容性测试。我们升级了Jedis和Lettuce的版本,问题就解决了。
第四个问题是,切换时的连接风暴。切换应用连接的时候,大量应用同时断开旧连接、建立新连接,导致新版本Redis的连接数瞬间飙升,CPU占用率升高。
解决方法是,分批切换,不要一次性全量切换。先切10%,再切30%,再切50%,最后全量。这样连接数是逐步上升的,不会对Redis造成冲击。
第五个问题是,持久化导致的性能抖动。新版本Redis在做RDB持久化的时候,fork子进程会占用大量内存,导致主进程响应变慢。
解决方法是,调整持久化策略,在业务低峰期做RDB持久化。或者用AOF持久化,减少fork的频率。还可以调整rdb-save-incremental-fsync等参数,减少持久化对性能的影响。
迁移后的优化
迁移完成之后,我们还做了一些优化,充分利用新版本的特性。
第一个是,利用新的数据类型和命令。新版本Redis增强了一些数据类型,我们把一些用旧方式实现的功能,改成用新的数据类型,简化了代码,提高了性能。
第二个是,调整内存管理策略。新版本的内存管理有改进,我们根据新版本的特点,调整了maxmemory、maxmemory-policy、hash-max-ziplist-entries等参数,提高了内存利用率。
第三个是,优化慢查询。新版本的慢查询日志更详细,我们根据慢查询日志,优化了一些慢命令,比如把大范围的keys命令改成scan,把复杂的事务改成管道。
第四个是,加强监控。新版本提供了更多的监控指标,我们把这些指标接入监控系统,设置告警阈值,能更及时地发现问题。
一些经验总结
这次Redis迁移,我总结了一些经验。
第一,准备工作要做足。迁移前的准备,包括了解新版本变化、评估业务影响、搭建测试环境、制定回滚方案,每一步都不能少。准备得越充分,迁移越顺利。
第二,测试要充分。在测试环境中反复演练迁移流程,把可能遇到的问题都提前暴露出来。不要在生产环境中做第一次尝试。
第三,选择合适的迁移方案。根据业务场景和数据量,选择合适的迁移方案。主从复制+切换适合大多数场景,但如果数据量特别大或者写入量特别高,可能需要其他方案。
第四,切换要分批。不要一次性全量切换,先切一小部分观察,没问题再逐步扩大。这样即使出问题,影响也比较小。
第五,监控要到位。迁移过程中和迁移后,都要密切监控Redis和应用的状态。发现异常,及时处理,必要时回滚。
第六,回滚方案要随时可用。即使准备得再充分,也可能出现意外。回滚方案要提前演练,确保出问题时能快速回滚。
第七,关注大key和热key。大key会影响同步和迁移的性能,热key会导致单节点压力过大。迁移前要处理好大key和热key。
写在最后
Redis迁移是一个高风险但又必须做的事情。随着Redis版本的不断更新,旧版本终会被淘汰,升级到新版本是必然的趋势。
只要做好充分的准备,选择合适的方案,严格按照流程操作,Redis迁移并没有想象中那么可怕。我们这次迁移,从准备到完成,花了大概两周时间,迁移过程中服务没有中断,用户无感知,迁移后运行稳定。
当然,Redis 8.0还没有正式发布,我们的方案是基于预览版和官方文档做的。等正式版发布之后,可能还会有一些调整。但整体的迁移思路和流程,应该是通用的。
希望这篇文章能给需要做Redis迁移的朋友一些参考。如果你有更好的迁移方案或者遇到过其他问题,欢迎在评论区交流。
评论(0)
暂无评论,快来抢沙发~
评论功能仅对会员开放,请先登录
登录