分布式缓存的一起问题

标签: data cache memcached | 发表时间:2014-05-22 13:40 | 作者:Tim
出处:http://timyang.net

背景说明

分布式缓存中为了可用性及高性能的考虑,可以使用如下一种master/slave设计模式。

图中的proxy是逻辑的概念,可以是基于client的包装实现,也可以是独立的proxy服务,但本文大部分是指独立的服务。几个主要的问题说明如下。

为什么cache要使用两个集群((master/slave)来存放?

主要出于可用性及高性能的考虑。传统的架构使用基于一致性哈希的分布式缓存,数据只存在一份副本,在出现cache节点单点故障时,虽然可以由一致性哈希算法将请求均匀落到其他节点,但由于穿透的请求较多,仍然给数据库带来较大的访问压力。为了避免对数据穿透带来的冲击,数据使用两份副本可以避免穿透的问题。同时在数据访问较大时候,也可以更好的分担流量,避免峰值单份数据跑满对系统带来的冲击。

为什么两份副本要使用master/slave结构?

由于大型系统中通常存在多个client同时操作同一份数据,需要确保所有client对数据修改时数据的一致性。为了避免两cluster两份副本数据不一致带来的困扰,使用了一个简单的做法,在配置中人为指定一个cluster为master,所有的数据以master为准。

为什么一些场景需要使用CAS?

CAS在计算机并发领域通常指 Compare-and-swap,在memcached中,也称为 Check And Set. 在分布式系统中,一份数据可能同时被多个调用修改,比如微博中的@箱,一个用户同时收到多个@的情况还是比较常见,比如当原来@箱里面记录是{1,2,3}时,4和5由不同的调用来源同时到达,如果没有同步的保护,系统的数据有可能最终被写成{1,2,3,4}或{1,2,3,5},由于memcached没有原生的list结构,list都是一个自定义的value, 则很容易出现client A覆盖了同时在写的client B的数据。因此假如两个调用方同时读到{1,2,3}时,第一个写入{1,2,3,4}会成功,后续的{1,2,3,5}CAS写入就会失败,因为此时服务器已经不是{1,2,3}了,失败的调用向服务端取回{1,2,3,4},最终写入{1,2,3,4,5}

在master/slave场景,比起普通的memcache CAS有什么区别?

目前的做法是master cas成功之后,直接修改slave,并不同时在slave执行cas操作。由于数据存在两份副本,当数据不一致时,无法自动处理数据的不一致冲突。因此在实践上只以master操作为准。

为什么使用proxy?

使用proxy主要是出于可用性、命中率以及可运维方面的考虑
可用性与可运维:当进行服务器增容或缩容时,如果client的数量较大,如果未使用proxy模式,client所在服务器通常需要修改配置并且逐个重启。重启(系统维护)一方面带来可用性方面的问题,运维方面也较为繁琐。
命中率:如果业务场景需要较高的命中率(比如>90%),则增容或缩容就变得较为复杂,需要client配合做一些策略,比如扩容后仍然访问扩容前旧的节点的数据以保证命中率。如果用proxy模式则极大降低client的访问复杂性,将相关逻辑都封装在proxy之后。

分布式缓存的一起问题

最近某业务有一起master单点故障,导致在问题的时间段内,用户看不到最近发生变更的数据。由于在上述场景中,实现cas时候的流程如下
1) master.cas(k,v)
2) 如果1成功,slave.set(k,v)
3) 如果1失败,不执行slave.set(),直接return;

由于第三步在失败时,并不会set slave,导致数据出现一致性问题,即使slave依然可用,新的数据不会写入cache。

首先看在master failure时,为什么不切换到slave cas?
先说自动切换的问题
上文也提过,两份数据副本在出现数据不一致后,并不能自动仲裁达到最终一致性,但是指定master角色可以达到最终一致性。如果master角色可以由调用方自动切换,则会带来数据的混乱。调用方存在多个节点,至少需要统一的config server来保证切换的一致性。另外,自动切换发生后,无法达到两份数据的最终一致性。
再说由运维手工切换
由于不牵涉到代码的逻辑判断,虽然切换也会带来一些数据一致性问题,在具体场景下(比如master长久宕机)切换可以接受。

在出现上述问题后,其他一些解决方案如下。
1. proxy在master cas失败时候delete slave data
2. client在master cas失败时set slave, 并且将数据过期时间设成5分钟

上述方案很难完美,一些明显存在的问题如下
方案1:
命中率的问题。由于delete导致修改的数据迅速失效,会导致读取量的增加,在读写均密集的业务场景,可能会导致数据访问出现波动。
接口职责单一性的问题。proxy在cas调用中隐藏了删除数据的逻辑,这是一个未在正常期望范围内的额外操作,在特殊情况下,可能会导致不可预料的情况出现。(尽管在实际操作中proxy提供配置开关选项)

方案2:
依然是命中率的问题,5分钟过期延缓了过期的访问数据库的压力,但相关压力仍然会传递到数据库。

希望通过上面说明读者能理解这个场景的问题。在这个场景下,完美的方案应当如何设计?

Similar Posts:

相关 [分布 缓存 问题] 推荐:

分布式缓存的一起问题

- - Tim[后端技术]
分布式缓存中为了可用性及高性能的考虑,可以使用如下一种master/slave设计模式. 图中的proxy是逻辑的概念,可以是基于client的包装实现,也可以是独立的proxy服务,但本文大部分是指独立的服务. 为什么cache要使用两个集群((master/slave)来存放. 主要出于可用性及高性能的考虑.

分布式缓存-Memcached

- - 人月神话的BLOG
分布式缓存出于如下考虑,首先是缓存本身的水平线性扩展问题,其次是缓存大并发下的本身的性能问题,再次避免缓存的单点故障问题(多副本和副本一致性). 分布式缓存的核心技术包括首先是内存本身的管理问题,包括了内存的分配,管理和回收机制. 其次是分布式管理和分布式算法,其次是缓存键值管理和路由. 原文: http://wenku.baidu.com/view/8686d46c7e21af45b307a8c3.html.

浅谈分布式缓存

- - CSDN博客推荐文章
在前面的一些文章中,从实战的角度,讲解了有关 memcached的应用、容灾、监控等等. 但是缺乏对理论的讲解和原理性的剖析. 本文将从理论的角度去介绍,让大家从宏观上对“分布式缓存、nosql”等技术有所了解,以便进一步学习和使用. 在构建大规模的web应用时,缓存技术可以说是必备的,学习的必要性不言而喻.

缓存击穿问题分析

- - 数据库 - ITeye博客
缓存一般作为RDS的前置组件,将常用的资源缓存,用来减少RDS的读取压力,也是诸多系统常用的一种方案,如果允许访问缓存失败直接访问数据库,然后再将数据回写到缓存中,那么就会存在缓存击穿的问题,. 缓存击穿:缓存中的数据未被命中,进而请求直接对数据库进行查询,当大量的类似查询瞬间出现,就会出现数据库的压力爆炸甚至引起数据库的雪崩,本质就是一种缓存失效引发的极端问题.

缓存级别与缓存更新问题

- - Float_Luuu的博客
缓存失效问题被认为是计算机科学中最难的两件事之一,这篇文章来自翻译,内容主要包括缓存级别与缓存更新常见的几种模式. 缓存常用来加快页面的加载速度,减少服务器或数据库服务的负载. 缓存应用的常见模式如上图所示:. 检索缓存,尝试查找之前相同请求的执行结果,如果找到了则返回,省去了重新执行的步骤;. 如果缓存未命中,则重新执行计算逻辑并将结果保存至缓存;.

分布式缓存ignite与其他缓存特效比较

- - 互联网 - ITeye博客
如下内容摘自于:http://www.infoq.com/cn/articles/apache-ignite-explorer.  在Ignite以前,大规模、大数据量、高并发企业级或者互联网应用为了解决数据缓存、降低数据库负载、提高查询性能等突出问题,很多采用了Hazelcast或者Oracle Coherence或者GemFire(比如12306网站)或者目前应用越来越广泛的Redis等缓存技术,本文对这些相关的技术做了简单的比较,基本内容来源于其官方网站,进行了翻译整理,方便更多的人了解他.

hibernate一二级缓存,查询缓存,n+1次查询问题

- - 行业应用 - ITeye博客
在本篇随笔里将会分析一下hibernate的缓存机制,包括一级缓存(session级别)、二级缓存(sessionFactory级别)以及查询缓存,当然还要讨论下我们的N+1的问题. 随笔虽长,但我相信看完的朋友绝对能对hibernate的 N+1问题以及缓存有更深的了解. 首先我们来探讨一下N+1的问题,我们先通过一个例子来看一下,什么是N+1问题:.

分布式缓存系统 Xixibase

- Le - 开源中国社区最新软件
Xixibase是一个高性能,跨平台的分布式缓存系统. Xixibase server 采用 C++ 实现,底层网络库采用的是Boost Asio. Xixibase 主要特点: 1. 实现'Local Cache'功能, 当客户端打开'Local Cache'选项, 客户端可以将数据同时存储在Server 端和本地,并且保证本地数据和Server 端的数据的一致性.

Ajax解决浏览器的缓存问题

- - 博客园_首页
        今天做项目,几乎所有的提交都是通过ajax来提交,我测试的时候发现,每次提交后得到的数据都是一样的,调试可以排除后台. 代码的问题,所以问题肯定是出在前台. 每次清除缓存后,就会得到一个新的数据,所以归根到底就是浏览器缓存问题. 久,终于解决了,在这里总结一下.         我们都知道ajax能提高页面载入的速度主要的原因是通过ajax减少了重复数据的载入,也就是说在载入数据的同时将数据缓存到.

OSCache 缓存重建在 Race Condition 下的 NRE 问题

- - 博客园_旁观者
高并发情况下,使用 OSCache 作为本地缓存中间件的前端服务,日志文件中会出现大量如下错误信息:. 无论你使用哪一种本地缓存中间件,如果你缓存数据片段时设置了过期时间,都需要考虑缓存失效后的缓存重建(repopulate the cache)场景. 进一步必须考虑 Race Condition (同进程下多线程,或不同进程)下如何重建.