Redis在业内解决秒杀等业务场景有非常广的应用,如何设计实现一个分布式锁是解决超卖、一人一单问题非常重要…

分布式锁

分布式锁是控制分布式系统之间同步访问共享资源的一种方式。 在 分布式系统 中,常常需要协调他们的动作。 如果不同的系统或是同一个系统的不同主机之间共享了一个或一组资源,那么访问这些资源的时候,往往需要互斥来防止彼此干扰来保证 一致性 ,这个时候,便需要使用到分布式锁。

全局ID生成器

实现一个分布式锁,在分布式系统中用来生成全局唯一ID的工具,需要满足唯一性、高可用、高性能、递增性、安全性。

常见的一些解决方案:

  • 数据库自增AUTO_INCREMENT

如果使用数据库自增ID就存在id的规律性太过明显,而且也会受到单表数据量的限制。

  • UUID

  • Redis生成ID

Redis提供了incr和incrby这样的自增原子命令,能够保证生成的ID肯定是唯一有序的。

  • 雪花算法snowflake

算法算法的有点是高性能,低延迟,按时间有序,缺点主要是需要独立的开发和部署,依赖机器的时钟。

一人一单实现

超卖问题

在单线程的环境下,进行下单是没有问题的,但是在多线程的条件下,很容易会出现超卖的现象,也就是典型的多线程并发安全问题。

解决方案:

  • 悲观锁 :认为线程并发安全问题一定发生,因此在操作数据之前需要先获取锁,确保线程串行执行,常见的比如:synchronized、Lock都属于悲观锁。

  • 乐观锁:认为线程安全问题不一定发生,不对它进行加锁,只是在更新数据时判断是否有其他线程进行修改,只有在没有其他线程修改时才可以更新数据

乐观锁的实现:

id stock version
12 1 2

update stock set stock = stock - 1 where id = 12 and version = 2;

如果在更新过程中,version字段发生改变的话,就直接拒绝更新。

悲观锁的性能一般、乐观锁性能好但是存在成功率低的问题。

一人一单

当我们的项目部署到单机情况下,可以通过加锁来解决并发条件下线程安全问题,但是当我们的项目部署到nginx,或者使用集群进行部署实现负载均衡,这样单挑单机的锁不能解决这个问题

所以我们需要解决用户下单时重复下单的问题或者单张优惠卷只能使用到一次。

分布式锁

分布式锁:需要满足分布式系统或集群多进程下可见并且互斥的锁。

需要满足多进程可见、互斥、高可用、安全性、高性能

分布式锁需要实现多进程之间互斥,常见的三种方式有以下三种:

Redis setnx实现分布式锁

在Redis中setnx命令是具有原子性的,我们可以通过setnx获取一把锁,设置过期时间从而可以释放锁。

上面的一个设计流程会有什么问题呢?

当多线程情况下,如果Thread1出现业务堵塞、超时,分布式锁会自动释放,然后Thread2可以获取到分布式锁,Thread1超时会释放掉锁,Thread2还没有完成执行,下一线程又会获得到这把分布式锁,也有可能出现线程安全问题。

解决方案:采用线程标识来识别是否可以是否分布式锁

  • 在分布式锁超时释放前,需要判断当前这把锁是否是当前线程获取的,如果是已经超时释放掉,那就不允许释放当前这把锁。

这样就可以解决多线程下提前释放掉锁的问题,但是在Java代码中是很难保证释放锁操作的原子性的,所以我们需要引入lua脚本来编写释放分布式锁的代码。

-- 比较线程标示和锁的标识是否一致
if (redis.call('get', KEYS[1]) == ARGV[1]) then
-- 释放锁 del key
return redis.call('del', KEYS[1])
end
return 0

上述分布式锁存在不可重入、不可重试、超时释放、主从一致性,Redisson就实现了各种分布式锁,包括可重入锁、联锁、红锁、读写锁、信号量、闭锁等…

Redis分布式锁实现及使用的更多相关文章

  1. 利用redis分布式锁的功能来实现定时器的分布式

    文章来源于我的 iteye blog http://ak478288.iteye.com/blog/1898190 以前为部门内部开发过一个定时器程序,这个定时器很简单,就是配置quartz,来实现定 ...

  2. Redis分布式锁

    Redis分布式锁 分布式锁是许多环境中非常有用的原语,其中不同的进程必须以相互排斥的方式与共享资源一起运行. 有许多图书馆和博客文章描述了如何使用Redis实现DLM(分布式锁管理器),但是每个库都 ...

  3. redis分布式锁和消息队列

    最近博主在看redis的时候发现了两种redis使用方式,与之前redis作为缓存不同,利用的是redis可设置key的有效时间和redis的BRPOP命令. 分布式锁 由于目前一些编程语言,如PHP ...

  4. redis咋么实现分布式锁,redis分布式锁的实现方式,redis做分布式锁 积极正义的少年

    前言 分布式锁一般有三种实现方式:1. 数据库乐观锁:2. 基于Redis的分布式锁:3. 基于ZooKeeper的分布式锁.本篇博客将介绍第二种方式,基于Redis实现分布式锁.虽然网上已经有各种介 ...

  5. spring boot redis分布式锁

    随着现在分布式架构越来越盛行,在很多场景下需要使用到分布式锁.分布式锁的实现有很多种,比如基于数据库. zookeeper 等,本文主要介绍使用 Redis 做分布式锁的方式,并封装成spring b ...

  6. Redis分布式锁的正确实现方式

    前言 分布式锁一般有三种实现方式:1. 数据库乐观锁:2. 基于Redis的分布式锁:3. 基于ZooKeeper的分布式锁.本篇博客将介绍第二种方式,基于Redis实现分布式锁.虽然网上已经有各种介 ...

  7. Redis分布式锁---完美实现

    这几天在做项目缓存时候,因为是分布式的所以需要加锁,就用到了Redis锁,正好从网上发现两篇非常棒的文章,来和大家分享一下. 第一篇是简单完美的实现,第二篇是用到的Redisson. Redis分布式 ...

  8. redis分布式锁实践

    分布式锁在多实例部署,分布式系统中经常会使用到,这是因为基于jvm的锁无法满足多实例中锁的需求,本篇将讲下redis如何通过Lua脚本实现分布式锁,不同于网上的redission,完全是手动实现的 我 ...

  9. Redis分布式锁的try-with-resources实现

    Redis分布式锁的try-with-resources实现 一.简介 在当今这个时代,单体应用(standalone)已经很少了,java提供的synchronized已经不能满足需求,大家自然 而 ...

  10. 关于分布式锁原理的一些学习与思考-redis分布式锁,zookeeper分布式锁

    首先分布式锁和我们平常讲到的锁原理基本一样,目的就是确保,在多个线程并发时,只有一个线程在同一刻操作这个业务或者说方法.变量. 在一个进程中,也就是一个jvm 或者说应用中,我们很容易去处理控制,在j ...

随机推荐

  1. 持续集成环境(2)-Jenkins插件管理

    Jenkins本身不提供很多功能,我们可以通过使用插件来满足我们的使用.例如从Gitlab拉取代码,使用 Maven构建项目等功能需要依靠插件完成.接下来演示如何下载插件. 修改Jenkins插件下载 ...

  2. 京东薅羊毛脚本-Docker

    一.安装好docker,然后创建容器: 注1:如果是旁路由,建议用--network host \代替-p 5678:5678 \这一行. 注2:如果想要看到lxk0301大佬的js脚本,并且重新部署 ...

  3. CentOS7-jdk1.8下载安装

    一.下载网址 jdk全版本:https://www.oracle.com/java/technologies/downloads/archive/ 本次安装版本(jdk1.8.0_151):https ...

  4. Codeforces Round #808 (Div. 2)

    Codeforces Round #808 (Div. 2) 传送门:https://codeforces.com/contest/1708 错过了,第二天vp的,只写出了AB就卡C了,竟然看不出是贪 ...

  5. Springboot 结合 Netty 实战聊天系统

    音视频技术为什么需要微服务 微服务,英文名:microservice,百度百科上将其定义为:SOA 架构的一种变体.微服务(或微服务架构)是一种将应用程序构造为一组低耦合的服务. 微服务有着一些鲜明的 ...

  6. C++ 用户输入验证

    在编写程序时,请考虑用户将如何滥用您的程序,尤其是在文本输入方面.对于每个文本输入点,请考虑: 会不会提取失败? 用户可以输入比预期更多的输入吗? 用户可以输入无意义的输入吗 用户可以溢出输入吗? 以 ...

  7. Go 语言:通过TDD测试驱动开发学习 Mocking (模拟)的思想

    正文: 现在需要你写一个程序,从 3 开始依次向下,当到 0 时打印 「GO!」 并退出,要求每次打印从新的一行开始且打印间隔一秒的停顿. 3   2   1   Go!   我们将通过编写一个 Co ...

  8. NLP 开源形近字算法之相似字列表(番外篇)

    创作目的 国内对于文本的相似度计算,开源的工具是比较丰富的. 但是对于两个汉字之间的相似度计算,国内基本一片空白.国内的参考的资料少的可怜,国外相关文档也是如此. 本项目旨在抛砖引玉,实现一个基本的相 ...

  9. 有关idea的使用部分

    出现相关异常,提示类似粗在idea找不到相关的包加载失败. 执行mvn命令 mvn -U idea:idea 含义更新重新加载idea工程的相关jar

  10. LeeCode 动态规划(二)

    01背包问题 题目描述 有 n 件物品和容量为 w 的背包,给你两个数组 weights 和 values ,分别表示第 i 件物品的重量和价值,每件物品只能使用一次,求解将哪些物品装入背包可使得物品 ...