缓存及缓存常见问题

缓存:存储在计算机上一个原始数据复制集,以便于访问。

1 缓存优缺点

1.1 缓存优点:加速读写,降低后端负载。

  (1) 加速读写:因为缓存通常都是全内存的(例如Redis、Memcache),而存储层通常读写能力差,通过缓存的使用可以有效的加速读写,优化用户体验。
  (2) 降低后端负载:缓存可以减少访问量和复杂计算(例如复杂的SQL语句),在很大程度降低后端的负载。


1.2 缓存缺点:数据不一致、代码维护成本和运维成本。

  (1) 数据不一致:缓存层和存储层有一定时间窗口的不一致性。
  (2) 代码维护成本和运维成本:加入缓存后,需要同时处缓存层和处理层的逻辑,增加了代码的复杂性,同样也增加了运维成本。

2 缓存穿透

  缓存穿透:查询一个一定不存在的数据,由于缓存是不命中时需要从数据库查询,查不到数据则不写入缓存,这将导致不存在的数据每次请求都要到数据库去查询,失去了缓存保护后端存储的意义。
  解决缓存穿透措施:缓存空对象和布隆过滤器。

  2.1 缓存空对象

  如果一个查询返回的数据为空,就将这个空结果进行缓存,设置5分钟的过期时间。



  缓存空对象的存在的问题:
  (1) 空值做了缓存,意味着缓存层中存了更多的键,需要更多的内存空间(如果是攻击,问题更严重),比较有效的方法就是针对这类数据设置一个较短的过期时间,让其自动剔除。
  (2) 缓存层和存储层会有一段时间窗口的不一致,可能对业务有一定的影响。可以通过设置过期时间或者利用消息系统清除缓存中的空对象。

  2.2 布隆过滤器

  在访问缓存层和存储层之前,将存在的key用布隆过滤器提前保存起来,做第一层拦截。如果一个要查询的key在布隆过滤器中判断肯定不存在,则不会查询直接返回。


  布隆过滤器基本原理及要点:位数组+k个独立的hash函数。
  一个值通过多个哈希函数计算得到在数组中对应的位,并将该位的标识改为1。如果请求查询一个数,先通过哈希函数计算,如果得到的位存在标识有0,说明这个值肯定不存在,这样可以避免不必要的数据库查询。
  如下图,如果有另外一个key,经3个hash函数算出的位分别是2,4,6,因为6位对应的值为0,说明存储层中肯定不存在这样的key,所以直接返回,不用在继续向下执行了。

适用:利用布隆过滤器减少磁盘IO或网络请求,因为一旦一个值必定不存在的话,就可以不用进行后续昂贵的查询操作。
优点:查询快,占用空间小。
缺点:存在误判,删除困难。

如何减少布隆过滤器的误判:增大位数组的长度,增加哈希函数的数量。

3 缓存雪崩

  缓存雪崩:缓存层由于某些原因整体crash掉,导致大量请求到达后端数据库,从而导致数据库崩溃,整个系统崩溃。

  3.1 缓存雪崩发生的原因:

(1) Redis服务器宕机,所有的请求都走存储层。
(2) 对设置过期时间的数据,在某段时间内大量的数据同时失效。对于这种情况可以在缓存的时候加上一个随机值,这样会大幅度减少缓存在同一时间过期。

  3.2 缓存雪崩解决方法:保证缓存层服务高可用性、熔断、限流和降级。

  (1) 保证缓存层服务高可用性。如主从架构、Sentinel或者Redis Cluster都实现了高可用。
  (2) 降级、熔断和限流

  降级:服务降级是当服务器压力剧增的情况下,根据当前业务情况及流量对一些服务和页面有策略的降级,以此释放服务器资源以保证核心任务的正常运行。
  限流:限流可以认为服务降级的一种,限流就是限制系统的输入和输出流量已达到保护系统的目的。一般来说系统的吞吐量是可以被测算的,为了保证系统的稳定运行,一旦达到的需要限制的阈值,就需要限制流量并采取一些措施以完成限制流量的目的。比如:延迟处理,拒绝处理,或者部分拒绝处理等等。
  熔断:一般是指软件系统中,由于某些原因使得服务出现了过载现象,为防止造成整个系统故障,从而采用的一种保护措施,所以很多地方把熔断亦称为过载保护。很多时候刚开始可能只是系统出现了局部的、小规模的故障,然而由于种种原因,故障影响的范围越来越大,最终导致了全局性的后果。

4 热点key重建优化

  如果一个key是热点key,并发量非常大,当这个key缓存失效,可能是一个复杂的SQL、多次IO等造成重建缓存不能短时间完成,在失效的瞬间,有大量的线程来重建缓存,造成后端负载加大。



  常见的优化方案:互斥锁(mutex key)、永远不过期

  4.1 互斥锁

  这种解决方案比较简单,就是让一个线程构建缓存,其他线程等待构建缓存的线程完成,重新从缓存中获取数据。



  这种方案的优缺点很明显。优点是实现简单,后端负载小。缺点阻塞其他线程,造成等待。

  4.2 永远不过期

(1) 从缓存层上看,没有设置过期时间,所以不会出现热点key过期后产生的问题。
(2) 从功能层上看,为每个value设置一个逻辑过期时间,当发现超过逻辑过期时间后,会使用单独的线程区构建线程。


  这种方案的优缺点也很明显。优点是杜绝了热点key过期的问题。缺点是在重建缓存期间,会出现数据不一致的情况,这取决于业务是否能容忍这种不一致。

  4.3 两种方案的比较

互斥锁:思路简单,能够较好的保证一致性。但是存在死锁和线程阻塞等问题。
永远不过期:没有热点key产生的一系列问题,但是会存在数据不一致的情况,同时代码复杂度增大。

5 无底洞优化

  无底洞问题:随着缓存的数据量增大,为了满足业务需求需要增加节点,但是增加节点没有让性能好转反而降低的现象。

  5.1 无底洞问题的原因

  键值数据库由于通常采用的是哈希函数将key映射到各个节点上,造成key的分布和业务无关,但是由于数据量的持续增加,造成需要添加节点做水平扩容,导致键值分布到更多的节点上。所以在批量操作时需要从不同的节点上获取,相比于单机批量操作只涉及一次网络操作,分布式批量操作会涉及多次网络操作。



  无底洞优化思路

(1) 命令本身优化,如优化SQL语句等。
(2) 减少网络通信次数。
(3) 降低接入成本。

  下面从减少网络通信次数来优化:
  以Redis批量获取n个字符串为例,有三种实现方法:

(1) 客户端n次get:n次网络 +n次get命令本身。
(2) 客户端1次pipeline get:1次网络 + n次get命令本身。
(3) 客户端1次mget:1次网络 + 1次mget命令。

  5.2 串行命令

  由于n个key是比较均匀地分布在Redis Cluster的各个节点,所以最简单的方法就是逐次执行n个get命令。这种操作时间复杂度较高,它的操作时间 = n次网络时间+n次命令时间。


  5.3 串行IO

  Redis Cluster使用CRC16算法计算出散列值,再取16383的余数就可以计算出slot值,可以根据这些将属于同一个节点的key进行归档,得到每个节点的key子列表,之后对每个节点执行mget或者pipeline操作,它的操作时间 = node次网络时间 + n次命令时间,网络次数是node的个数。


  这是对串行命令的优化,但是节点数太多,还是有一定的性能问题。

  5.4 并行IO

  此方案是串行IO的改进方案,网络次数虽然还是节点个数,在mget命令执行时使用多线程,使用多线程网络时间变为O(1)。


  5.5 hash_tag实现

  由于Redis Cluster中计算slot的算法,可以使用hash_tag将多个key强制分配到一个节点上,它的操作时间 = 1次网络时间 + n次命令时间。



  如图所示,所有的key都在Redis 2节点。


  5.6 四种批量操作解决方案对比

(1) 串行命令
优点:编程简单。
缺点:大量keys请求延迟严重。
网络IO:O(keys)。

(2) 串行IO
优点:编程简单,是串行命令的改进版。
缺点:如果有大量nodes延迟严重。
网络IO:O(nodes)。

(3) 并行IO
优点:利用并行特性,延迟取决于最慢的节点。
缺点:编程复杂,由于多线程,问题定位比较难。
网络IO:O(max_slow(nodes))

(4) hash_tag
优点:性能最高。
缺点:容易造成数据倾斜。
网络IO:O(1)。

  本文完


  注:本文参考《Redis开发与运维》,如发现错误,请指正!

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