当前位置:   article > 正文

【Redis】分布式锁及其他常见问题

【Redis】分布式锁及其他常见问题

分布式锁及其他常见问题

1. 我看你的项目都用到了 Redis,你在最近的项目的哪些场景下用到了 Redis 呢?

一定要结合业务场景来回答问题!要是没有不要硬讲,除非面试官问;

在这里插入图片描述

接下来面试官将深入发问。

  • 你没用到的也可能会试探着去问;

Redis 分布式锁使用的场景?

分布式情况下的,或者集群情况下的,多个微服务操作同一对象,可能是相同操作(同时改),也可能是不同操作(一个删,一个改…)

  1. 定时任务
  2. 抢单/秒杀
  3. 密等性场景

2. 抢卷场景

2.1 分布式问题

在这里插入图片描述

执行流程:

在这里插入图片描述

而如果是分布式的项目,就可能对服务进行集群部署:

在这里插入图片描述

2.2 synchronized 锁解决问题

在这里插入图片描述

显然这解决不了分布式问题;

只能解决同个 Java 进程的多线程的问题,也就是处理同一个 Java 服务的多个请求的问题;

在这里插入图片描述

2.3 分布式锁解决问题

在这里插入图片描述

3. 分布式锁的实现原理

Redis 分布式锁其实就是“争夺一个 key 的定义”,主要利用 Redis 的 setnx 命令(SET if **not ex**ists 如果不存在,则设置)

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

小插曲:锁提前过期,但是业务未结束,锁岂不是可以被其他服务获取了?

其实这个问题可以通过给锁续期来解决,举个例子:

一个分布式锁有效时长是 5 秒,但是业务时长 7 秒,我们可以每隔一段时间,如每个 3 秒 就判断业务是否结束,如果结束了那就释放锁,如果没结束,就重置锁的有效时长,如重置为 5 秒;

4. 程序中怎么使用分布式锁?

分布式锁真的很灵活和精准!

可以使用 redission 框架(加锁、设置过期时间等操作都是基于 lua 脚本,Redis可以识别的可保证原子性的脚本完成),执行流程如下:

在这里插入图片描述

示例代码:

  • R 在 redisson 中值得就是 Redis 的 R;

在这里插入图片描述

RLock 锁是可以重入的锁

在这里插入图片描述

5. 分布式锁主从一致性的问题

在这里插入图片描述

正常情况下,Redis 集群的主从会进行同步,所以不同的 Java 应用访问 Redis 集群的时候,是只有一个应用能获取一把锁;

但是,如果主节点在从节点同步之前挂了,从节点就变成了新的主节点,另一个 Java 应用尝试获取这把锁,发现可以获取成功,就出现了两个线程同时持有一把锁的情况了;

之后,两个线程就没有阻塞的同时进行了。

主从就不一致了,因为从节点只显示正常一个线程获得锁,但实际上是两个线程用了一把锁;

在这里插入图片描述

可以使用分布式锁的另一种实现:RedLock(**Red**is)

RedLock(红锁),在多个 Redis 实例上创建锁 (n / 2 + 1),避免在一个 Redis 实例上加锁:

在这里插入图片描述

缺点:

  1. 实现复杂
  2. 性能差
  3. 运维繁琐

如果非要解决这个问题,可以用 zookeeper(CP 思想)去解决,而 Redis (AP 思想)更适合根据具体业务实现最终一致性;

Redis 分布式锁,是如何实现的?

  • 根据自己简历的项目进行描述分布式锁使用后的场景,如抢票、维持幂等性…
  • 我们当时使用的是 redisson 实现的分布式锁,底层是 setnx 和 lua 脚本(保证原子性)

Redisson 实现的分布式锁是如何合理的控制锁的有效时长的?

  • 在 redisson 的分布式锁中,提供了一个 ==WatchDog(看门狗)==一个线程获得锁成功以后 WatchDog 会给持有锁的线程**续期(默认是每个 10 秒续期一次)**

Redisson 的这个锁,是可重入锁么?

  • 可以重入,多个锁重入需要判断是否是当前线程,在 Redis 中进行存储的时候使用 hash 结构,来存储==线程信息和重入的次数==;

Redisson 的这个锁,能处理主从数据一致的问题吗?

  • 主从数据一致的问题:主节点在从节点同步之前宕机,从节点就被升级为主节点的数据不一致的问题;

  • 处理不了,但是可以用 Redisson 提供的的==红锁来解决,但是这样的话,性能太低了==,如果是 AP,则为我们保证数据的最终一致性即可,如果业务要求 CP,建议采用 zookeeper 实现的分布式锁;

6. Redis 集群有哪些方案?

在 Redis 中提供了三种集群方案:

  1. 主从复制
  2. 哨兵模式
  3. 分片集群

有一些常见的问题:

  1. Redis 主从数据同步的流程是什么?
  2. 怎么保证 Redis 的高并发高可用?
  3. 你们是用 Redis 的单点还是集群,哪种集群?
  4. Redis 分片集群中数据是怎么存储和读取的?
  5. Redis 集群脑裂,该怎么解决呢?

6.1 主从复制

主从同步原理:

由于单点 Redis 的并发能力是有上限的,要进一步提高 Redis 的并发能力,就需要搭建主从集群,实现读写分离;

在这里插入图片描述

主从全量同步:

在这里插入图片描述

主从增量同步(slave 重启或后期数据变化)

在这里插入图片描述

主从同步数据的流程:

  1. 从节点请求主节点同步数据(replication id、offset)
    • replication id 用于判断是否是对应的主节点;
  2. 主节点判断是否是第一次请求(第一次就是全量同步),发送给从节点同步版本需要的信息(replication id、offset)
  3. 执行 bgsave,生成 rdb 文件后,发送给从节点去执行;
  4. 从节点清空数据,加载 rdb 文件(全量同步加载时间可能较长),期间主节点的新增数据以命令的方式记录在缓冲区(一个日志文件)
  5. 把生成之后的命令日志文件发送给从节点进行同步;
  • 之后从节点重启或者日常的同步数据:
  1. 请求主节点同步数据(replication id、offset)
  2. 主节点判断是否是第一次请求(不是第一次就是增量同步),根据 offset 获取 offset 之后的命令文件,发送给从节点;
  3. 从节点执行命令进行数据同步;

6.2 哨兵模式

在这里插入图片描述

Redis 提供了哨兵(Sentinel)机制来实现主从集群的自动故障恢复。哨兵的结构和作用如下:

  1. 监控:Sentinel 会不断检查您的主从系欸但是否按预取工作;
  2. 自动故障恢复:如果主节点故障,Sentinel 会选取一个从节点为新的主节点,故障实例恢复后作为从节点以新的主节点为主;
  3. 通知:Sentinel 充当 Redis 客户端的服务发现来源,当集群发生故障转移的时候,会将最新的信息推送给 Redis 客户端,也就是说之后的客户端能正确拉取 Redis 服务;

状态监控的相关细节:

  • Sentinel 基于心跳机制检测服务状态,每隔一秒向集群的每个实例发送 ping 命令;
  • 主观下线:如果某个 Sentinel 节点发现某实例未在规定时间响应,则认为该实例主观下线;
    • Sentinel 有集群,但是没有主从之分,没有“Sentinel 监控 Sentinel 的套娃”
      声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/395940
推荐阅读
相关标签