一次redis数据迁移实施方案

背景

       最近上线了一个项目,项目中使用到了redis为服务提供数据缓存和数据存储。刚开始业务还能正常运行,单机redis基本可以满足服务的性能要求。由于业务增长加快,随着服务的QPS流量越来越大,引起redis的QPS也急剧上升。这是由于服务中有3个接口的QPS流量迅猛上升,而且每个接口中都多次访问redis,因此出现redis的访问QPS越来越大,达到了将近7W/s的量,引起公司监控系统多次告警。

解决方案1

      问题出现后,面对近乎疯狂的QPS增长,最直接想到的解决方案是想办法削弱3个接口的单次调用的redis操作次数,减少不必要的redis get操作,从业务逻辑方面压缩单次调用服务的redis操作次数。采用这种思路也是基于小步优化的考虑,而且改动较小,能够快速上线,不影响线上服务正常运行,实际的工程效果也显示上线之后redis的QPS流量增幅得到小幅度遏制,为后面实施redis的从单机到集群迁移置换了许多宝贵的时间。

解决方案2

       解决方案1轻便易施行,但缺点是治标不治本,短期内redis的QPS稍微压了下来,业务如果继续迅速增长,必然会吃掉方案1优化出来的余量,后来服务运行也正是如此。从服务的高可用性来说,也应该避免单机裸奔在情况不定的线上环境,因此使用redis集群代替单机redis势在必行,redis集群方案既能支撑更高的业务量,也能保证服务的高可用。那么问题出现了,我的服务已经上线了,难道为了从单机redis切换到redis集群,要停掉线上服务,造成服务停用,给我们的用户造成不便吗,如果这样的话那就没必要写本篇博客了,毕竟,还是要记录点有价值的东西嘛。

      问题的难点在于如何保证线上功能的平稳运行,不影响线上业务。总结我的解决方案就是一句话:单点到集群的复制 + 单点&集群双写。

redis中保存的数据有缓存,也有部分是存储的数据。缓存的数据可以丢失,不管。要解决的是redis被当作存储使用的那部分数据。方案分两步走,分别是复制和双写。redis集群系统使用公司内部的redis集群中间件访问,为配合本次迁移,针对两个步骤,分别设置三个开关:

 xxx.msgBox.redis.write--双写开关,开关为true,redis get/set操作同时写入单点和集群redis系统,保持双写过程;开关为false,redis get/set操作只向集群redis系统写入,单点redis不在更新数据。

 xxx.msgBox.redis.query--服务redis查询选择开关。开关值为0,表示服务从单点redis系统查询数据,此时redis流量均在单点redis上,开关值为100,表示服务从redis集群系统查询数据,此时redis流量均在集群redis系统上。开关值为n(0

xxx.msgBox.redis.sync--单点redis向集群redis系统复制开关。开关值为true,开启单点redis复制数据到集群redis系统,开关值为false,关闭单点redis复制数据到集群系统。


操作步骤:

1、打开redis的双写开关,置xxx.msgBox.redis.write=true,单点redis和集群redis系统同时接受服务的写操作,并保持双写。双写的过程中,单点redis数据正常提供读写服务,就像没有集群redis系统一样,集群redis系统此时会不断地有新的redis key写入,并更新已经存在的部分key,但集群redis系统的数据基本是错误的,因为集群redis系统没有服务的之前数据,redis集群数据库中普遍是脏数据。

2、打开redis的单点到集群的复制开关,置xxx.msgBox.redis.sync=true,实现单点redis中的老数据同步复制到集群redis系统,经过步骤1和2的操作,集群redis系统的数据已经和单点redis系统数据保持一致。从而使数据准确无误滴迁移到了新的集群系统。

     仅就数据迁移而言,数据已经迁移完毕,为了实现服务由单redis向集群redis系统的过渡,另外设置了灰度控制开关( xxx.msgBox.redis.query),实现Redis QPS流量逐渐地由单点向集群过渡,多次调大灰度开关值,使得redis集群系统逐渐承担起redis流量的主体,也避免了新部署的集群系统不可用或者我们的迁移出现失误导致的服务不可用现象,大约经过一周的灰度调控,服务上的redis操作已经完全使用集群redis系统承担了。同时,数据迁移完成之后,保持一段时间的新旧redis双写,也是出于安全稳定性考虑。

     至此,本次redis的数据迁移才算完成。

你可能感兴趣的:(redis)