微服务架构之:Redis分布式锁

Redis分布式锁

    • 集群架构下的并发问题
    • 分布式锁的实现原理和不同方式的实现对比
    • 基于Redis实现的分布式锁
    • Redis分布式锁1.0

集群架构下的并发问题

    在单体架构上,乐观锁和悲观锁可以锁住并发情况下的同步代码块,我们多使用synchronized来对方法加锁。但是在配上负载均衡的集群模式下,普通的synchronized是无法锁住从两台服务器同时进入的请求
    这是在了解秒杀项目的难点之一:一人一单的并发安全问题在使用集群架构出现的难点。我们先从单体项目出发,单体项目很好理解,假如有俩线程:线程1查询订单,判断是否存在。然后第二个线程之后在去查询订单,判断是否存在,在synchronized的作用下两个线程是不会发生问题的。
微服务架构之:Redis分布式锁_第1张图片

    那现在,我们不再是一台服务器,而是多台。在当前这一个JVM内部,锁的原理是在JVM内部维护了一个锁监视器对象,监视器的对象用的是userId,它是在我们的常量池里面。那么在这个JVM内部是维护了这一个常量池子,当ID相同的情况下,他们永远都是同一个锁,也就是说锁的监视器是同一个。所以无论是线程1也好,线程2也好,他们俩要获取锁的时候,锁监视器就会记录线程ID,当另一个线程再来获取锁的时候肯定是不行的,因为锁监视器已经记录一个了。

    但是,当我们部署一个新的服务器的时候,也就是部署了一个新的JVM。两个JVM也拥有各自的常量池,JVM2用userId作为锁的时候,它的监视器对象就会拥有一个新的锁监视器,跟JVM1的监视器不是同一个。现在当我们线程3来获取锁的时候走的是自己的监视器,那这个监视器显示的是空的呀,所以也能获取锁成功,当然了线程4失败是没问题的。也就是说在JVM内部锁监视器能保证这些线程互斥,但是多个JVM就会有多个JVM监视器, 有多少个锁监视器就会有多少个线程成功进入同步代码块
微服务架构之:Redis分布式锁_第2张图片

    所以我们要解决的问题就是在多个JVM的情况下让这些锁监视器使用同一把锁。

分布式锁的实现原理和不同方式的实现对比

    synchronized就是利用JVM内部的锁监视器来控制线程的,在JVM内部,因为只有一个锁监视器,所以只会有一个线程获取到锁,可以实现线程阶段互斥。但是当有多个JVM的时候,就会有多个锁监视器,这时候synchronized就会显得苍白无力,JVM内部的锁监视器直接作废。所以锁的监视器一定要在JVM的外部,让所有JVM都去找独一无二的锁监视器来获取锁,这样也就只有一个线程获取锁,也就实现了多JVM的线程互斥。
微服务架构之:Redis分布式锁_第3张图片

    所以满足在分布式系统或集群模式下多线程可见并且互斥的锁就是分布式锁
微服务架构之:Redis分布式锁_第4张图片

    分布式锁核心是实现多进程之间的互斥,而满足这一点的方式有很多,常见的有三种:Mysql、Redis。Redis里有setnx互斥命令,王redis面set数据的时候,只有没数据的时候才会set成功,有数据就会set失败。
微服务架构之:Redis分布式锁_第5张图片

基于Redis实现的分布式锁

    实现分布式锁肯定要实现两个基本方法,获取锁释放锁

获取锁

  • 互斥条件:确保只能有一个线程获取到锁。
  • 非阻塞:尝试一次,成功返回true,失败返回false。
    这个我们可以用redis的setnx,这个可以确保只有一个可以返回1。
    微服务架构之:Redis分布式锁_第6张图片
    在这里插入图片描述
    确保原子性,利用EX。
    在这里插入图片描述

释放锁

  • 手动释放 del lock
    在这里插入图片描述
    思考问题:如果在获取锁后redis宕机了,那么这个释放锁动作就永远得不到执行,其他线程进不来,我这服务已经挂了,整个线程进入死锁状态。所以需要在获取锁时添加过期时间,避免服务器宕机引起的死锁。

Redis分布式锁1.0

微服务架构之:Redis分布式锁_第7张图片
锁的名称不能写死,不同的业务有不同的锁。
微服务架构之:Redis分布式锁_第8张图片
微服务架构之:Redis分布式锁_第9张图片

你可能感兴趣的:(微服务架构,架构,微服务,redis,分布式锁)