PHP和分布式Memcache的一个小问题 单点故障

这几天做某个产品的时候遇到一个小问题,现象比较诡异

产品用了两台分布式的memcached服务器

某一个计数器取回来的数偶尔会不对,最后定位在php memcache client的failover机制上面。

我们知道,在memcached分布式环境下,某一个key是通过hash计算,分配到某一个memcached上面的

如果php.ini里面 memcache.allow_failover = 1的时候,在分布式环境下,某一台memcached出问题的话,会自动到其他的memcached尝试

就会出现上面的问题,原因如下:

这个key是hash到服务器A的,但是服务器A正好一瞬间连不上(网络或者其他问题),PHP就会去另一台服务器B去尝试。

经过很偶然发生的网络问题和很多次increment操作,有可能两台服务器上面都有这个key,而且值不一样……

get的时候有可能取到不同的值

如果对数据一致性要求很严格的话,可以关掉这个参数 memcache.allow_failover = 0,嗯,问题解决

 


虽然Memcached作为一个分布式缓存数据服务,但是每个服务之间根本没有进行相互通信,这里可能与 我理解的分布式有点区别,可能是我才疏学浅,也可能是每个人思考问题的角度不同。Memcached 客户端就是通过一种分布式算法将数据保存到不同的Memcached服务器上,将数据进行缓存。

Memcached分布式环境下,每个服务器端本身没有相互相连的关系,数据分布其实是由客户端来维持的(通俗点说,是客户端按照自己的分布算法, 将数据分配 给指定的服务端去存储,取值的时候,客户端再找指定的服务器拿数据。任何环境下,服务端都不可能主动去找客户端拿“东西”或者去操作客户端。B/S模式也 是的,web服务器不可能主动找浏览器拿东西,更不可能对浏览器端做任何操作)。memcached的服务端更不会这么聪明,自动去查找、匹配当前环境 中分布的其他服务器。

而且,据我所知,Memcached本身并没有为集群提供真的高可用方案,因为我个人认为,使用集群环境,通常是为了满足以下的需求:

1.压力分载 (负载均衡)    2.失效转发(故障转移)。

而memcached本身并不具备这两点,这对于以“分布式缓存”号称的memcached来说,是非常致命的。

  现象描述:
    在客户端连接的部分写入多个服务器端的ip地址,客户端将会自动的把缓存数据分布的放在每个不同的机器上

查看大图请点击这里

现象后果:
    如果其中一个缓存节点的机器down机,那么客户端存入的缓存数据将会丢失一部分,就是图中红色字体描述的“Losed 33% Cache Data”,也就是说那部分数据彻底没有了!如果是用户的关键性信息那么就玩大了
查看大图请点击这里

解决方案1:本地备份缓存
    在本地放一份缓存,同时也在分布式Memcached上放一份缓存,如果当其中一台节点当机了,客户端程序直接读取本地的缓存,本地客户端维护一个 HashMap即可,这样的方案虽然很简陋,但是可以满足一部分场景的需要,当你很急需的时候可以作为临时方案暂时替代一下。

解决方案2:采用缓存代理服务器
    采用 Magent 缓存代理,防止单点现象,缓存代理也可以做备份,通过客户端连接到缓存代理服务器,缓存代理服务器连接缓存服务器,缓存代理服务器可以连接多台Memcached机器可以将每台Memcached机器进行数据同步。这样的架构比较完善了,如果其中一台缓存代理服务器down机,系统依然可以继续工作,如果其中一台Memcached机器down掉,数据不会丢失并且可以保证数据的完整性 
查看大图请点击这里

还是那句话:没有任何架构是最完美的,只是最合适的,任何架构都不可能一步到位,都是经过一步一步演变过来的。

上一篇:新零售行业优质解决方案分享【餐饮行业会员管理解决方案】


下一篇:SpringBoot-09-之初阶整合篇(上)