Molet

简单方式实现redis的master-master复制

Molet 运维技术 2018-05-05 2891浏览 0

众所周知,目前Redis只提供master- slave的数据复制方式,可以是一主一从或者是一主多从的方式,但是无法master-master复制。master-master相对实现复杂的原 因一个是数据的一致性,如果两头都同时插入同一个key的值,那么复制的时候很难判断哪个是正确值。

但是如果我需要对数据一致性要求不是很高的master-master复制结构,比如储存实时的数据分析系统的缓存,这个应用的 数据是不会改变, 中间计算结果缓存只要计算好后就不会过期。我的要求是保存全量的缓存数据到所有redis节点,每个服务器上都有一个应用服务和redis节点,做到缓存 数据相对应用的本地化调用,减少带宽消耗和网络传输时间。
master-master的replication方式redis无法提供,但我又没时间和能力去修改redis的复制实现,我只想做尽量少的工作去满足我的需求。我这里把要保存到所有redis节点的数据统一叫做data

方法一:最简单的方式是应用产生data后,发送data到每个redis节点,这个方式实现简单,但是效率很低,如果有多个redis节点,那么需要依次发送到所有节点,应用需要等待所有节点data保存完毕,这个是最傻的方法。
方法二:还是方法一的思路,但是修改了不足点,主要在保存data数据时,独立生成一个线程来操作data数据。这个问题是应用还要生成一个线程,加大系统开销,每次计算都需要产生线程操作,应用的复杂性也相对比较高。

方法三:基于redis本身队列的实现,redis本身提供队列的数据结构,rpop,lpush提供出队入队的接口。

实现机制:应用产生data直接发送到本地redis节点的队列里面,然后通过本地的脚本(推荐python)读取队列数据,并且发送到其他redis节点。
这样设计简化了应用的复杂性(应用只做lpush操作),把接下来的工作全部交给后台的脚本做(脚本只做rpop操作),脚本负责把从队列里取到的数据发送到所有redis节点。同时因为是基于redis队列,性能也是可以接受的。
脚本读取队列数据需要注意的是读取的策略,每次都是rpop一个数据,如果队列里没有数据,可以暂停一定的时候(比如1s),如果有数据操作完成后不暂停。

举个例子

1、应用a产生数据 key:123456, value:12334556767,那么应用lpush(“yiihsia”,”12345+12334556767″),应用a的工作到此结束
2、然后是脚本循环调用rpop(“yiihsia”)接口,发现有数据,取出数据然后解析,得到key:123456, value:1233455676
3、脚本首先发送到本地的redis节点,调用接口set(“123456″,”1233455676″),然后再依次调用其他redis节点的set接口
这个方法只是个大致思路,具体的细节需要不断完善 


继续浏览有关 redis 的文章
发表评论