一种基于哨兵的缓存访问策略

14年双11大促缓存方案,今天有点闲暇时间,回顾一下当时的思路。

1.场景介绍:

大促活动下,对于某些产品进行整点秒杀活动。预计流量是平时峰值5+倍
商品计算逻辑比较复杂:某个最终展示的商品属性和价格,可能需要上亿次动态条件计算获得,
动态条件每时每刻都在变化,并且商品的库存属性属于行业共有库存,每时每刻都在变化。
**计算模型:**前端机并发去后端获取实时计算数据,然后合并结果,根据用户信息给商品打属性,排序。

2.头脑风暴

 针对这种场景,有很多方案可以尝试,不过总结起来,大概俩个方向:扩容和缓存

3.扩容

 扩容是最容易想到的方式,而且每年大促,根据压测和运营活动预期,都可能有相应扩容。
 扩容从某种程度上说,也是最简单的方式,如果应用规划足够好,没有状态,那么基本不用开发介入就能完成。
 但是如果应用涉及状态信息,那么扩容就没有说的那么轻巧,扩容涉及到增加集群状态;活动结束后,机器下线涉及集群减少状态,这一增一减,增加了运维的成本和系统稳定性。
 扩容还有一个不好的地方就是活动结束后,系统水位下降,闲下来4倍的机器,比较浪费。

4.缓存

 相对扩容,缓存是一种从应用角度出发,优化系统的方案。
 缓存的方案可细分不同粒度,分别适用不同场景。静态化能最大限度降低最大限度降低后端压力,
 一般静态内容可以定时或者通过数据更像触发生成,然后推送到CDN节点。
 静态化适用于1)读多写少的数据,或者2)能够容忍数据变化延迟的场景。
 对于本文介绍的场景,并不适合,原因在于商品不满足前面说的两点,并且每个登陆用户看到的产品价格和属性是不同的。

5.缓存中间结果

 静态化这种”一刀切”模式,不能满足针对每个用户的个性化展示需求,如果把每个用户看到的数据都静态化,
 那缓存的命中率有会很低,基本每个用户请求一两次就不会再来了。
 而且缓存数据量巨大。由此想到把缓存粒度缩小,把缓存从展示层后推到前端机上。
 因为前端机负责汇总后端结算结果,并根据用户信息给商品打属性,排序。

6.缓存方案尝试

 经过头脑风暴,最终确定采用缓存中间结果方式。接下来讨论一下方案细节。

7.简单粗暴方式

 **如果缓存有数据,取缓存数据,如果没有,请求后端并把结果更新到缓存。
 **这是一种最简单的缓存模式,但不幸的是不适合秒杀场景,因为秒杀开始的时候,缓存很能没有数据,请求会穿透到后端。

8.实时缓存,异步更新方式

 实时请求数据来自缓存,缓存数据定时异步更新。粗看起来,这个方案不存在缓存穿透的情况,
 因为数据不会实时从后端计算获取,而是从缓存获取,如果缓存数据存在,直接获取即可。缓存更新可以把用户请求汇总后去重,定时更新。上面讨论的两种方式都一个共性问题:第一批请求

 问题:**如果第一批请求缓存没有数据怎么办?**
 
 简单粗暴的方式会让这样的请求穿透缓存,后端去处理并更新缓存。
 这样会给后端计算带来压力,秒杀开始那一刹那,很可能支撑不住。
 而实时缓存的牺牲了这样的请求,因为这些请求根本看不到数据,所以请求失败。
 这两种方式在本文的应用场景都不合适。

9.为何不提前初始化缓存

 的确,上面两个方案如果能在第一批请求到达前初始化好缓存,那基本上可以满足本文的应用场景的。
 而且看起来也很容易做到,提前模拟一次请求或者提前往缓存放一份数据不就可以了吗?
 不幸的是,本文场景因为涉及数据范围巨大,不能在较短时间内遍历缓存key,初始化好缓存,即使采取并发方式。
 而且,初始化缓存请求过多,也将给后端机器造成压力。

10 . 缓存失效又该怎么办?

 根据需求,两种方案的缓存不会永久有效,如果缓存失败了怎么办?
 对于简单粗暴方式,如果缓存失效,又会遇到第一批请求问题,一批请求发现缓存失效,怎么办?
 看来即使解决了缓存初始化问题,还有可能导致缓存穿透。
 实时缓存模式也有类似问题,如果异步更新前数据已经失效了,那么将牺牲一批数据失效后到更新前这批用户。因为没有人去更新数据。

11 . 缓存更新问题

   不管哪种方式,分布式缓存更新都存在并发问题,尤其在整点秒杀场景更为突出。
   对于简单粗暴方式,可以采用分布式锁解决:如果缓存穿透的一批请求只有一个会真正打到后端是不是就可以解决了?
   实时缓存也有同样的问题,只不过异步请求可以把一段时间内的重复请求合并成一个,从侧面避免了并发问题。

12 . 更好的缓存方式

  把上面的讨论结合,可以得到一种更优雅的缓存方案,既不牺牲第一批请求,也不存在缓存穿透问题,同时避免并发更新问题。

  哨兵
  想象有这样一个哨兵线程,只有它能去后端请求实时数据,并更新缓存。

  第一批请求场景:
image
   第一批请求中,选取最早的那个请求为哨兵,这个线程不会去读缓存,直接去后端获取计算结果并更新缓存。
   其他普通线程则自旋+sleep等待,直到哨兵更新缓存后,能拿到数据为止。

13 . 缓存失效场景:


image
哨兵的作用是让缓存永不失效。哨兵线程提前苏醒,去后端获取计算数据并更新缓存。
这样,其他普通线程根本不会感知到缓存已经失效,他们能一直拿到最新的缓存。

例如,某个key的缓存失效时间的12:00:00,那么哨兵可能在11:59:55的时候苏醒,
请求后端并于11:59:57的时候完成缓存数据更新,后续请求线程感知不到数据的更新,一直能取到非过期的数据。

14 . 实现细节

 **哨兵:**其实哨兵也是一个普通请求。
 可以用原子计数器(redis或tair)实现,一个数据有两个key:原子计数器key和数据缓存key,
 二者缓存时间一致,但是计数器key失效时间比数据key的要早(**至少提前一个后端请求RT时间**,这样能保证哨兵更新缓存后,不被其他线程感知到)。
 当请求线程发现缓存没有数据的时候,每个线程去更新计数器,更新后,得到计数器为1的线程,
 被设置成哨兵线程,其他线程则等待哨兵。
 普通请求没有获取到数据的时候,自旋+sleep应该有个超时时间,防止意外情况。
 如果超时了,根据业务场景选择请求后端数据还是处理失败。
image.png

引用: http://blog.lichengwu.cn/architecture/2015/06/14/distributed-cache/

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容