网站收录怎么做,企业vi设计调研,重庆企业seo,域名注册免费目录 为什么要用Redis实现商户查询缓存#xff1f;用Redis实现商户查询缓存的基本思路#xff1f;使用Redis缓存的问题及解决方法#xff1f;一、如何保持数据库数据和Redis缓存数据的一致性#xff1f;1 内存淘汰机制2 超时剔除机制3 主动更新机制#xff08;胜#xff… 目录 为什么要用Redis实现商户查询缓存用Redis实现商户查询缓存的基本思路使用Redis缓存的问题及解决方法一、如何保持数据库数据和Redis缓存数据的一致性1 内存淘汰机制2 超时剔除机制3 主动更新机制胜如何实现主动更新机制操作缓存和数据库时应该更新缓存还是删除缓存如何保证缓存与数据库的操作的原子性先删除缓存还是先操作数据库 二、缓存穿透解决方案1 缓存空对象解决方案2 布隆过滤器 三、缓存雪崩解决方案1 随机TTL值解决方案2 redis集群解决方案3 服务熔断和降级解决方案4 多级缓存 四、缓存击穿热点key问题解决方案1 互斥锁解决方案2 逻辑过期 为什么要用Redis实现商户查询缓存
缓存是数据交换的缓冲区是存储频繁用的数据的临时区要求读写性能高redis基于内存读写的高性能特点恰恰满足这一要求用redis实现缓存可以降低后端负载提高读写效率增加缓存功能会增加成本如数据一致性成本代码维护成本运维成本等因此要根据业务场景选择合适的redis功能和机制
用Redis实现商户查询缓存的基本思路
实战视频
如果没有缓存客户端频繁发出请求查询一个数据时每次请求都会直接到达数据库数据库的压力会很大Redis缓存相当于在客户端和数据库之间增加了一个拦截当客户端发出请求查询数据时先到达Redis查询如果命中直接返回查询结果因此该请求就不会到达数据库降低了数据库的压力如果在Redis中请求没有命中该请求才会继续去数据库将数据库的查询结果返回客户端若该客户端多次重复请求这个在Redis中不存在的数据还是会多次请求数据库这并不是我们希望的结果因此数据库应该将查询结果返回客户端的同时将查询结果也写入redis缓存中
使用Redis缓存的问题及解决方法
一、如何保持数据库数据和Redis缓存数据的一致性
数据一致性要求较低数据变化频率较低用内存淘汰机制就行数据一致性要求较高数据变化频率较高用主动更新并用超时剔除当兜底
1 内存淘汰机制
redis为了解决内存不足的问题自带的一种功能会在内存不足时自动淘汰部分数据下次查询该数据时更新缓存在一定程度上可以保持数据的一致性优点维护成本几乎为0全程有Redis自己管缺点不知道会淘汰掉哪些数据什么时候淘汰所以数据一致性比较差
2 超时剔除机制
给缓存数据添加TTL时间到期后自动删除缓存下次查询时更新缓存优点维护成本较低只需要在原来数据的基础上增加一个过期时间缺点可以控制哪些数据什么时候淘汰数据一致性比内存淘汰机制好一些但也不强
3 主动更新机制胜
在修改数据库中数据的同时更新缓存优点数据一致性比较好缺点维护成本高需要自己编写大量的业务逻辑比较难
如何实现主动更新机制
实现的第一种方案自己写代码在更新数据库的同时更新缓存实际业务中用的最多。实现的第二种方案将缓存与数据库整合成一个服务只需调用该服务数据一致性由服务内部自己实现。但维护该服务比较难也较难找到现成的服务可用实现的第三种方案调用者不管数据库只在缓存中增删改查缓存一直保持最新的数据。由一个专门的线程通过异步的方式将缓存的数据更新到数据库中保证数据最终一致。异步机制可以大大提升效率主要体现的场景为假如缓存中的某个数据更新了n次此时异步线程来检查缓存中的数据有没有变化然后将最新的数据写入数据库相当于数据库只更新了1次而数据库的读写比缓存读写费劲多所以节省了更新n-1次数据库浪费的时间。缺点是维护异步线程的成本、Redis宕机丢失数据、在异步线程更新数据库之前数据完全不一致。
操作缓存和数据库时应该更新缓存还是删除缓存
更新缓存每次更新数据库时都需要更新缓存对于缓存来说无效的写操作比较多删除缓存更新数据库时删除缓存中的数据更新n次也只删一次只有客户端用到该数据时访问redis缓存redis中没有该数据才会从数据库中取最新的数据写到缓存中。
如何保证缓存与数据库的操作的原子性
意思就是更新数据库的时候必须保证删除缓存也成功执行二者要么都成功要么都失败对于单体系统将缓存与数据库操作放在一个事务中对于分布式系统利用TCC等分布式事务方案
先删除缓存还是先操作数据库
在多线程情景下二者的执行顺序不一样会造成不一样的后果先删除缓存假设线程1先删缓存后更新数据库线程2在线程1刚删完缓存还没更新数据库时突然请求此时缓存中的数据已经被删线程2会去数据库中查询但线程1还没更新数据库因此线程2查到的是旧数据还会把旧数据按照流程写入缓存此时线程1再更新数据库就会造成数据不一致先更新数据库假设线程1先更新数据库后删除缓存线程2在线程1更新数据库之前请求恰好缓存由于某些原因失效线程2便查询数据库返回客户端一个旧数据此时线程2正常更新数据库删除缓存线程1再继续将刚才从数据库中读到的旧数据写入缓存此时就会造成数据不一致先更新数据库造成的数据不一致的可能性更低且可以为缓存增加TTL在一定程度上避免该问题的发生因此应该先更新数据库后删除缓存
二、缓存穿透
客户端请求的数据在缓存和数据库中都没有无法建立缓存如果多次请求这个不存在的数据这些请求就会全部打到数据库给数据库造成压力
解决方案1 缓存空对象
简单暴力返回一个空值null下次请求再来时会在缓存命中null不会继续请求数据库优点实现简单好维护缺点1如果有很多不同的请求的数据不存在就会在缓存中存很多null造成额外的内存消耗。解决方法可以给null也增加一个TTL避免长期占用缓存空间。缺点2在null过期之前的请求得到的数据都是null如果此时数据库更新了数据就会造成短期的不一致。解决方法用主动更新机制在更新数据库的同时替换掉null
解决方案2 布隆过滤器
在客户端和Redis之间增加布隆过滤器当客户端发出一个请求时首先由布隆过滤器判断该数据是否存在若存在则放行请求会继续执行正常流程若不存在则拒绝禁止请求频繁访问缓存和数据库布隆过滤器是一个bit数组每一位非0即1可以快速判断一个元素是否存在存数据根据k个不同的hash函数将数据映射到bit数组的k个位置上将k个位置置1判断数据根据k个不同的hash函数将数据映射到bit数组的k个位置上若k个位置有0则该数据肯定不存在拦截若k个位置全为1则该数据可能存在hash可能冲突所以存在误判允许通过优点速度快占用空间小缺点实现复杂存在误判 三、缓存雪崩
大量redis缓存中的key同时失效或过期或者redis服务器宕机大量请求直接到达数据库给数据库造成巨大压力
解决方案1 随机TTL值
如果给大量key设置一样的TTL就会在同一时间大量key同时失效因此可以给不同的key添加分布较均匀的随机TTL
解决方案2 redis集群
宕机一个redis还有其他redis
解决方案3 服务熔断和降级
redis宕机时暂停redis缓存服务熔断预防出现雪崩若redis直接爆炸只能降级服务不理睬请求直接返回错误
解决方案4 多级缓存
在多个层面建立缓存比如浏览器、数据库等一级缓存和二级缓存失效时间不同一级缓存失效用二级缓存
四、缓存击穿热点key问题
部分热点key被高并发访问且缓存重建业务较复杂的key在缓存中失效或过期如果第一次请求未命中会去数据库查询并写入缓存但若在此期间有大量同样的请求涌入就会有大量请求涌到数据库要求查询给数据库造成巨大压力
解决方案1 互斥锁
当线程1查询缓存未命中时尝试获取锁获取成功才能去数据库查询写缓存后释放锁。在此期间其他同样的请求查询缓存未命中时同样尝试获取锁但获取失败就会等待一段时间重新尝试查询缓存并获取锁优点没有额外的内存消耗数据一致性更好实现简单缺点其他线程需要一直等待直到获取到锁的线程写入缓存或释放锁还有死锁风险
解决方案2 逻辑过期
不再设置TTL而是设置一个逻辑过期时间TTL相当于倒计时逻辑过期时间相当于一个具体的时间当线程1查询缓存时发现该缓存的逻辑时间已经过期便尝试获取互斥锁并开启一个新线程2来进行查询数据库重建缓存无需等待线程2执行完直接返回一个过期的数据线程3若紧跟线程1之后也来查询该缓存发现逻辑时间已过期也尝试获取互斥锁但此时锁被线程2占用获取失败则直接放弃返回过期数据只有在释放锁之后到来的线程4才能命中缓存中没有过期的数据优点线程无需等待性能较好缺点数据一致性较差有额外的内存消耗实现复杂