Skip to content

Redis场景应用

缓存基础

Redis由于性能高效,通常可以做数据库存储的缓存,比如给MySQL当缓存就是常见的用法。具体而言,就是将MySQL中的热点数据存储在Redis中,通常业务都满足二八原则,即80%的流量集中在20%的数据上,所以缓存是可以有效提高系统的吞吐量。

缓存的四种模式

缓存一般有四种模式:

  • Cache-Aside Pattern:旁路缓存
    • 可能出现数据不一致问题
  • Read Through Pattern:读穿透缓存
    • 对业务透明,代码简洁
    • 缓存命中时性能较低,多一次服务间调用过程
  • Write Through Pattern:写穿透缓存
  • Write Behind Pattern:异步缓存写入模式
    • 数据不安全,有丢失风险

Cache-Aside Pattern

旁路缓存就是指业务方将缓存当做是数据库的旁路,业务直接和缓存打交道。

旁路缓存读流程:业务方先查看缓存中是否有目标数据,如果没有,则去数据库中查找指定数据。业务方在获取到数据的同时,将数据保存在缓存中,以备后续的查询。

image-20241030190038771

旁路缓存写流程:业务方首先向数据库写入数据,在写入成功之后将缓存中对于的数据删除。这是为了避免由于更新缓存的时序差异导致的数据不一致问题

image-20241030190309815

Read Through

读穿透缓存模式提供一个数据服务,业务方不再直接和缓存打交道,而是将查询请求发送给数据服务,让数据服务执行查询缓存、数据库的操作。一图蔽之:

image-20241030191116236

Write Through

写穿透缓存模式通常和读穿透模式一同使用。写穿透模式要求数据服务在接受到业务方的写请求时,先将数据写入数据库,接着写入缓存

image-20241030191922522

由于写穿透模式要求写完数据库后马上写缓存,对缓存的及时性要求高,在高并发的环境下就可能会出现数据不一致问题。另一方面,还需要合理设置缓存中数据的过期时间,因为每一次写入操作都会增加缓存中的数据,不合理的数据过期时间可能会导致缓存中的数据急剧膨胀,占用大量内存资源。

Write Behind

Write Behind和Write Through在执行写操作时都会对数据库和缓存操作。区别在于,Write Behind先写缓存,再异步将数据写入数据库

Write Behind缓存策略采用异步写数据的方式,可以选择在某个特定的时间点,例如数据库负载较低时,进行写入操作,也可以选择积累一定量的写命令后一次性将数据写入数据库中。

image-20241030192626673

异步写入操作极大降低了写请求的延迟以及数据库的负载,但代价是数据安全性不够高。倘若当部分存储在内存中的数据未写入数据库时,存储服务发生了崩溃,那么数据就丢失了。

分布式锁

分布式锁就是应用在分布式场景下的锁,保证各台机器上的各个进程并发安全的操作某一资源。一个合理的分布式锁应具备如下特点:

  • 互斥性:针对某一资源,同一时刻只能有一个竞争者持有锁,其他竞争者则阻塞
  • 抗死锁性(活性):当一个竞争者持有锁的期间,即使发生了异常导致程序退出,无法正常释放锁,也能有兜底策略将锁释放,避免发生死锁
  • 对称性:对同一资源上锁和解锁必须是同一个竞争者
  • 可靠性:具备一定的容灾能力

实现

从分布式锁的特点可以推测出,使用Redis实现分布式锁大致流程应该是:

  1. 对某一个资源尝试加锁
  2. 加锁并且标记owner
  3. 处理业务
  4. 检查锁的owner
  5. 删除锁

为什么要标记owner

如果不标记锁的owner,可能会出现竞争者A将竞争者B的锁释放,🌰:假设A率先拿到分布式锁,接着进行业务流程。倘若此时A由于网络延迟或CPU占用率高等因素导致在分布式锁的过期时,业务仍没有完成。那么B以为分布式锁没有被其他竞争者占用,顺理成章地拿到了分布式锁,执行业务逻辑。不幸的是,在B执行业务过程中,A终于完成了业务,然后执行delete删除分布式锁的动作。但此时A删除的并非是自己,而是B的分布式锁。那么该分布式锁就失去了保证资源并发安全的意义。

如何保证检查-删除的原子性?

4、5步骤是典型的check-do something场景,需要保证原子性,否则会出现并发问题。

要想实现Redis某些操作组合的原子性,Lua脚本是不二法门。Redis+Lua,可以说是专门为解决原子问题而生的。有了Lua的特性,Redis才真正在分布式锁、秒杀等场景有了用武之地,最终Redis实现分布式锁的流程如下:

image-20241027095707243

上次更新于: