Redis使用场景之缓存

Redis使用场景系列文章目录

第一章 Redis使用场景概况



前言

本系列文章基本参考付磊、张益军的《Redis开发与运维》。同时参考了网上其他的一些资料。

缓存能够加速应用的速写速度、同时降低后端后端负载,应用非常广泛。但同时也会对架构造成影响。本文尝试从多个方面来说明缓存使用技巧和设计方案。


一、缓存的收益和成本分析

1. 收益

  1. 加速读写
  2. 降低后端负载

2. 成本

  1. 数据不一致性:缓存层和存储层的数据存在一定时间窗口的不一致性,时间窗口跟策略有关。
  2. 代码维护成本:同时处理缓存层和存储层的逻辑。
  3. 运维成本:如Redis Cluster。

3. 场景

在明白了收益和成本以后,我们就能大概知道什么样的场景适合使用缓存,是收益大于成本的,比如:

  1. 开销大的复杂计算:以MySQL为例,一些复杂的操作或计算(如大量链表操作、分组计算等),如果不加缓存,不但无法满足高并发量,同时也会给MySQL带来巨大负担。
  2. 加速请求响应:如果QPS要求非常高,那么即使查询单条后端数据足够快,也依然可以使用缓存,比如Redis每秒可以达到数万次读写,批量操作也可以优化整个IO链的响应时间。

二、缓存更新策略

缓存中的数据通常都具有生命周期,需要在指定时间后删除或更新,以保证缓存空间在可控的范围。但缓存数据会和数据源中的真实数据有一段时间窗口的不一致,需要利用某些策略进行更新。

1.LRU、LFU、FIFO算法剔除

  • 使用场景:缓存使用量超过预设的最大值。
  • 一致性:清楚哪些数据是有算法决定的,一致性最差。
  • 维护成本:无需开发人员维护,配置最大缓存和策略即可。

2.超时剔除

  • 使用场景:业务可以容忍一段时间内缓存层数据和存储层数据不一致。
  • 一致性:过期时间内存在一致性问题。
  • 维护成本:不高,设置过期时间即可。

3. 主动更新

  • 使用场景:数据一致性要求高,需要在真实数据更新后立即更新缓存。
  • 一致性:一致性最高。
  • 维护成本:比较高,需要开发者完成更新并保证更新操作的正确性。

三、缓存粒度控制

缓存时是缓存全部属性还是只缓存部分重要属性,需要从以下几个角度考虑:

  1. 通用性
  2. 空间占用:内存、网络、序列化反序列化的CPU等开销
  3. 代码维护

四、穿透优化

缓存穿透是指查询一个根本不存在的数据,缓存层和存储层都不会命中。每次穿透都会导致存储层查询,加大后端存储负载,甚至宕机。

一般导致穿透有两个原因:

  • 自身业务代码或数据出现问题
  • 恶意攻击、爬虫等

1. 缓存空对象

第一次发生穿透时在缓存中存储空对象,以保护后端数据源。但这也会导致新的问题:

  • 浪费空间,如果是恶意攻击就更加严重。一种应对方法是设置较短的过期时间
  • 可能存在一段时间窗口的数据不一致,影响业务。可以利用消息系统或其他方式清除空对象

2. 布隆过滤器拦截

类似白名单,将所有有效数据存放在过滤器中,查询缓存时先查询过滤器,通过才会继续查询。对于数据命中不高、但相对固定、实时性低的应用场景比较适用,代码维护成本较高。

五、无底洞优化

缓存的无底洞现象是指当存在大量节点时,继续添加节点性能不升反降。这是由于键值数据库采用哈希函数将key进行映射,如果节点过多,批量查询时就需要更多的网络操作,而且网络连接增多,也会影响节点性能。解决办法一般为以下几种:

  • 命令本身的优化
  • 减少网络通信次数
  • 降低接入成本,如使用长连、连接池,NIO等

命令、客户端连接就不多说了,说说网络操作次数。假设Redis批量获取那个字符串:

  • 客户端n次get:n次网络+n次get命令本身
  • 客户端1次pipeline get:1次网络+n次get命令本身
  • 客户端1次mget:1次网络+1次mget命令本身

显然,针对单个节点批量操作优化方式就是mget,那么如果是RedisCluster,则需要另外的思路。

1. 串行命令

由于n个key是较均匀地分布在各个节点上,无法使用mget一次性获取,简单的方式就是逐次执行n个get命令,时间上虽然不是最有,但实现简单。

2. 串行IO

使用CRC16算法计算出散列值,再对16383取余算出slot值,通过smart客户端保存的slot和节点对应关系,就可以得到每个节点的key子列表,从而对每个节点mget,操作时间=node次网络+node次命令时间。如果节点数太多,也会存在一定的性能问题。

3. 并行IO

将串行IO的最后一步改为多线程执行,可以将网络时间缩短为O(1),当然也会增加代码复杂度。

4. hash_tag实现

hash_tag将多个ke强制分配到一个节点上,我们就可以根据业务需要决定数据的节点分配策略,将所需数据集尽可能放在同一个节点上,这样就完全可以当做单节点使用。但是需要注意数据量均衡问题。

六、雪崩优化

如果缓存犹豫某些原因不能提供服务,那么多有请求都会到达存储层,存储层调用量保证,最终级联宕机,这种情况就叫做缓存雪崩。解决办法一般是预防和熔断。

1. 保证缓存层服务高可用性

无需多言,高可用保证即使个别节点、机器甚至机房宕机,依然可以提供服务,只要缓存层服务不宕机,自然不会发生雪崩。

2. 依赖隔离组件为后端限流并降级

降级机制在高并发系统中也是非常普遍的,基本原则就是保证系统不会因为个别资源出问题而整个停摆。当然这其中会涉及到很多问题,比如资源池的开启关闭,阈值管理等等,可以依赖现有的管理工具。

3. 提前演练

上线之前演练缓存层宕掉后,应用及后端负载情况及可能出现的问题,准备一些预案。

七、热点key重建优化

缓存+过期时间可以满足大部分情况,但如果当前key是一个热点key,并发量非常大,而且重建缓存不能在短时间内完成,可能是一个复杂计算,那么在缓存失效期间,也可能导致系统崩溃。

这个问题本身并不复杂,关键是不能在解决问题的同时给系统带来更多的麻烦,所以一般要求减少重建缓存次数,且数据尽可能一致,以减少潜在风险。

1. 互斥锁

一次只允许一个线程重建缓存,其余线程等待。

2. 永远不过期

缓存层面不为key设置过期时间,但是功能层面会为每个value设计一个逻辑过期时间,超过改时间,会使用单独线程去构建缓存。这也会导致在重构缓存时,会出现数据不一致。


总结

提示:这里对文章进行总结:

例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值