Redis分布式锁实现及使用
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分布式锁实现及使用的更多相关文章
- 利用redis分布式锁的功能来实现定时器的分布式
文章来源于我的 iteye blog http://ak478288.iteye.com/blog/1898190 以前为部门内部开发过一个定时器程序,这个定时器很简单,就是配置quartz,来实现定 ...
- Redis分布式锁
Redis分布式锁 分布式锁是许多环境中非常有用的原语,其中不同的进程必须以相互排斥的方式与共享资源一起运行. 有许多图书馆和博客文章描述了如何使用Redis实现DLM(分布式锁管理器),但是每个库都 ...
- redis分布式锁和消息队列
最近博主在看redis的时候发现了两种redis使用方式,与之前redis作为缓存不同,利用的是redis可设置key的有效时间和redis的BRPOP命令. 分布式锁 由于目前一些编程语言,如PHP ...
- redis咋么实现分布式锁,redis分布式锁的实现方式,redis做分布式锁 积极正义的少年
前言 分布式锁一般有三种实现方式:1. 数据库乐观锁:2. 基于Redis的分布式锁:3. 基于ZooKeeper的分布式锁.本篇博客将介绍第二种方式,基于Redis实现分布式锁.虽然网上已经有各种介 ...
- spring boot redis分布式锁
随着现在分布式架构越来越盛行,在很多场景下需要使用到分布式锁.分布式锁的实现有很多种,比如基于数据库. zookeeper 等,本文主要介绍使用 Redis 做分布式锁的方式,并封装成spring b ...
- Redis分布式锁的正确实现方式
前言 分布式锁一般有三种实现方式:1. 数据库乐观锁:2. 基于Redis的分布式锁:3. 基于ZooKeeper的分布式锁.本篇博客将介绍第二种方式,基于Redis实现分布式锁.虽然网上已经有各种介 ...
- Redis分布式锁---完美实现
这几天在做项目缓存时候,因为是分布式的所以需要加锁,就用到了Redis锁,正好从网上发现两篇非常棒的文章,来和大家分享一下. 第一篇是简单完美的实现,第二篇是用到的Redisson. Redis分布式 ...
- redis分布式锁实践
分布式锁在多实例部署,分布式系统中经常会使用到,这是因为基于jvm的锁无法满足多实例中锁的需求,本篇将讲下redis如何通过Lua脚本实现分布式锁,不同于网上的redission,完全是手动实现的 我 ...
- Redis分布式锁的try-with-resources实现
Redis分布式锁的try-with-resources实现 一.简介 在当今这个时代,单体应用(standalone)已经很少了,java提供的synchronized已经不能满足需求,大家自然 而 ...
- 关于分布式锁原理的一些学习与思考-redis分布式锁,zookeeper分布式锁
首先分布式锁和我们平常讲到的锁原理基本一样,目的就是确保,在多个线程并发时,只有一个线程在同一刻操作这个业务或者说方法.变量. 在一个进程中,也就是一个jvm 或者说应用中,我们很容易去处理控制,在j ...
随机推荐
- CBV源码分析及模板语法之传值 过滤器 标签 继承 导入
CBV的源码分析 # CBV的源码入口从哪里看呢? CBV的核心源码: return self.dispatch(request, *args, **kwargs) def dispatch(self ...
- CentOS查看已安装的服务与卸载服务。。
1:使用rpm查看, rmp -qa | grep servername rpm -qa 查看以安装的所有服务,grep过滤我们需要看的服务. 2:使用yum查看<此命令恕在下未能完全理解,可能 ...
- h5移动端开发经验积累篇
h5键盘控制 const el = document.documentElement || document.body const originHeight = el.clientHeight win ...
- MOBIUS: Towards the Next Generation of Query-Ad Matching in Baidu's Sponsored Search——百度下一代搜索广告系统
简介 传统的广告最终的呈现需要经过召回与排序两个阶段,百度的搜索架构则采用三层漏斗状,如图1所示.最上面的一层用于筛选出和用户查询最相关的一部分广告,将整个候选广告集从亿级降到千级:下面两层是排序阶段 ...
- spring-mvc.xml
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.spr ...
- Javaweb学习笔记第十弹
本章存在的意义,大概就是为了回顾一下被遗忘不久的html了 HTML:超文本标记语言(不区分大小写,语法较为松散,但建议书写时规范一些) HTML标签由浏览器来解析 标签展示图片 具体详情也可以去参考 ...
- 关于jsp页面中的小细节们
细节一:利用jsp判断文本框的输入格式是否正确 也就是主要利用script标签进行判断,主要用到的是正则表达式(判断是否为整数): 再加上if语句的配合,就能够在文本框的格式不正确时,发出错误警告啦! ...
- Axios的js文件的下载教程+相关应用
下载教程来啦! 1.进入GitHub网站,网址在这里:http://github.com 2.去搜索框搜索Axios,得到如下界面: 3.然后选择这里: 会出现如下界面: 4.点击右方的绿色按钮&qu ...
- Bitcask — 日志结构的快速 KV 存储引擎
Bitcask 介绍 Bitcask 是一种高性能的键值存储引擎,基于日志结构和哈希索引来提供高速的读写操作和数据持久性,适用于处理大量写入请求和快速查找键值对的应用场景. 核心概念 Bitcask ...
- java多线程--3 线程状态、线程方法、线程类型
java多线程--3 线程状态.线程方法.线程类型 线程状态 创建状态: **就绪状态: ** 进入状态: 创建状态:启动线程 阻塞状态:阻塞解除 运行状态:释放CPU资源 阻塞状态: 进入状态: 运 ...