redis实战-添加商户缓存

为什么要使用缓存

  • 言简意赅:速度快,好用
  • 缓存数据存储于代码中,而代码运行在内存中,内存的读写性能远高于磁盘,缓存可以大大降低用户访问并发量带来的服务器读写压力
  • 实际开发中,企业的数据量,少则几十万,多则几千万,这么大的数据量,如果没有缓存来作为避震器系统是几乎撑不住的,所以企业会大量运用缓存技术
  • 但是缓存也会增加代码复杂度和运营成本
  • 缓存的作用
    1.降低后端负载
    2.提高读写效率,降低响应时间
  • 缓存的成本
    1.数据一致性成本
    2.代码维护成本
    3.运维成本(一般采用服务器集群,需要多加机器,机器就是钱)
    在这里护主要说redis缓存

图解

先从Redis中查询,如果没有查到,再去MySQL中查询,同时查询完毕之后,将查询到的数据也存入Redis,这样当下一个用户来进行查询的时候,就可以直接从Redis中获取到数据

商户缓存流程

  • 代码思路:如果Redis缓存里有数据,那么直接返回,如果缓存中没有,则去查询数据库,然后存入Redis

缓存更新策略

  • 缓存更新是Redis为了节约内存而设计出来的一个东西,主要是因为内存数据宝贵,当我们想Redis插入太多数据,此时就可能会导致缓存中数据过多,所以Redis会对部分数据进行更新,或者把它成为淘汰更合适
  1. 内存淘汰:Redis自动进行,当Redis内存大道我们设定的max-memery时,会自动触发淘汰机制,淘汰掉一些不重要的数据(可以自己设置策略方式)
  2. 超时剔除:当我们给Redis设置了过期时间TTL之后,Redis会将超时的数据进行删除,方便我们继续使用缓存
  3. 主动更新:我们可以手动调用方法把缓存删除掉,通常用于解决缓存和数据库不一致问题

数据库和缓存不一致解决方案

由于我们的缓存数据源来自数据库,而数据库的数据是会发生变化的,因此,如果当数据库中数据发生变化,而缓存却没有同步,此时就会有一致性问题存在,其后果是

  • 用户使用缓存中的过时数据,就会产生类似多线程数据安全问题,从而影响业务,产品口碑等

那么如何解决这个问题呢?有如下三种方式

  1. Cache Aside Pattern 人工编码方式 :缓存调用者在更新完数据库之后再去更新缓存,也称之为双写方案主要方案
  2. Read/Write Through Pattern:缓存与数据库整合为一个服务,由服务来维护一致性。调用者调用该服务,无需关心缓存一致性问题。但是维护这样一个服务很复杂,市面上也不容易找到这样的一个现成的服务,开发成本高
  3. Write Behind Caching Pattern:调用者只操作缓存,其他线程去异步处理数据库,最终实现一致性。但是维护这样的一个异步的任务很复杂,需要实时监控缓存中的数据更新,其他线程去异步更新数据库也可能不太及时,而且缓存服务器如果宕机,那么缓存的数据也就丢失了

综上所述,在企业的实际应用中,还是方案一最可靠,但是方案一的调用者该如何处理呢?


三个问题:
1. 删除缓存还是更新缓存?
2. 如何保证缓存与数据库的操作同时成功或者失败?
3. 先操作缓存还是先操作数据库?

  1. 删除缓存还是更新缓存?
  • 如果采用方案一,假设我们每次操作完数据库之后,都去更新一下缓存,但是如果中间并没有人查询数据,那么这个更新动作只有最后一次是有效的,中间的更新动作意义不大,所以我们可以把缓存直接删除,等到有人再次查询时,再将缓存中的数据加载出来
    对比删除缓存与更新缓存
    更新缓存:每次更新数据库都需要更新缓存,无效写操作较多
    删除缓存:更新数据库时让缓存失效,再次查询时更新缓存
  1. 如何保证缓存与数据库的操作同时成功/同时失败?
  • 单体系统:将缓存与数据库操作放在同一个事务
  • 分布式系统:利用TCC等分布式事务方案
  1. 先操作缓存还是先操作数据库?
  • 我们来仔细分析一下这两种方式的线程安全问题

  • 先删除缓存,再操作数据库

    删除缓存的操作很快,但是更新数据库的操作相对较慢,如果此时有一个线程2刚好进来查询缓存,由于我们刚刚才删除缓存,所以线程2需要查询数据库,并写入缓存,但是我们更新数据库的操作还未完成,所以线程2查询到的数据是脏数据,出现线程安全问题

  • 先操作数据库,再删除缓存

    线程1在查询缓存的时候,缓存TTL刚好失效,需要查询数据库并写入缓存,这个操作耗时相对较短(相比较于上图来说),但是就在这么短的时间内,线程2进来了,更新数据库,删除缓存,但是线程1虽然查询完了数据(更新前的旧数据),但是还没来得及写入缓存,所以线程2的更新数据库与删除缓存,并没有影响到线程1的查询旧数据,写入缓存,造成线程安全问题

    虽然这二者都存在线程安全问题,但是相对来说,后者出现线程安全问题的概率相对较低,所以我们最终采用后者先操作数据库,再删除缓存的方案

相关推荐
sam-1231 小时前
k8s上部署redis高可用集群
redis·docker·k8s
看山还是山,看水还是。1 小时前
Redis 配置
运维·数据库·redis·安全·缓存·测试覆盖率
谷新龙0011 小时前
Redis运行时的10大重要指标
数据库·redis·缓存
精进攻城狮@1 小时前
Redis缓存雪崩、缓存击穿、缓存穿透
数据库·redis·缓存
渗透测试老鸟-九青2 小时前
通过投毒Bingbot索引挖掘必应中的存储型XSS
服务器·前端·javascript·安全·web安全·缓存·xss
材料苦逼不会梦到计算机白富美5 小时前
golang分布式缓存项目 Day6 防止缓存击穿
分布式·缓存·golang
avenue轩6 小时前
gdb调试redis。sudo
c++·redis
不惑_6 小时前
Redis:发布(pub)与订阅(sub)实战
前端·redis·bootstrap
cui_win7 小时前
Redis高可用-Sentinel(哨兵)
redis·bootstrap·sentinel
cui_win10 小时前
Redis高可用-主从复制
redis·git·github·主从复制·哨兵