基于单机redis的分布式锁实现
最近我们有个服务经常出现存储的数据出现重复,首先上一个系统流程图:
用户通过http请求可以通知任务中心结束掉自己发送的任务,这时候任务中心会通过MQ通知结束服务去结束任务保存数据,由于任务结束数据计算保存有一定延时,所以存在用户短时间内多次结束同一个任务,这时候就会导致我们结束服务对同一个任务保存多次数据。恰好我们也是用了redis,所以对于这个问题我当时想到使用分布式锁来解决,那么如何用redis实现分布式锁呢?
首先要明确一个分布式锁应具备的原则:
- 互斥性。在任意时刻,只有一个客户端能持有锁;
- 不会发生死锁。即使一个客户端持有锁的期间崩溃而没有主动释放锁,也需要保证后续其他客户端能够加锁成功;
- 加锁和解锁必须是同一个客户端;
- 有高可用的获取锁和释放锁功能。
由于我们只使用了单机的redis,所以本文的实现不具备第四点原则。
我们这个锁的实现就包括两点:加锁、解锁。首先看加锁。先上代码:
- public boolean tryGetDistributedLock(String lockKey, String requestId, int expireTime) throws Exception{
- Jedis jedis = null;
- try {
- jedis = getJedisClient();
- String result = jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime);
- if (LOCK_SUCCESS.equals(result)) {
- return true;
- }
- return false;
- } finally {
- returnResource(jedis);
- }
- }
我们的加锁就是设置一个键值对,并且满足以下条件:
- 确保只有当键不存在时才设置有效;
- 设置的值必须是当前客户端生成的uuid;
- 键必须要有过期时间。
这三点条件就可以满足上述的原则1、原则2。
接下来看下解锁,代码如下:
- public boolean releaseDistributedLock(String lockKey, String requestId) throws Exception{
- Jedis jedis = null;
- try {
- jedis = getJedisClient();
- String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
- Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId));
- if (RELEASE_SUCCESS.equals(result)) {
- return true;
- }
- return false;
- }finally {
- returnResource(jedis);
- }
- }
解锁是通过一段lua脚本实现,逻辑如下:
1、获取锁键值看是否与当初设置的值一致;
2、如果一致则删除键。
由于解锁过程分为两步,为了确保原子性所以通过让redis执行lua脚本来实现,校验键值可以确保加锁解锁都是同一个客户端。
这样一个简易的分布式锁就实现完毕了,当然在本文开头就说了,这个实现只能满足单机redis的情况,对于redis集群其实是不严谨的,对于redis集群有一个redlock方案,我也在研究中,后面也会总结一下。
基于单机redis的分布式锁实现的更多相关文章
- springboot 中单机 redis 实现分布式锁
在微服务中经常需要使用分布式锁,来执行一些任务.例如定期删除过期数据,在多个服务中只需要一个去执行即可. 以下说明非严格意义的分布式锁,因为 redis 实现严格意义的分布式锁还是比较复杂的,对于日常 ...
- 基于redis的分布式锁(转)
基于redis的分布式锁 1 介绍 这篇博文讲介绍如何一步步构建一个基于Redis的分布式锁.会从最原始的版本开始,然后根据问题进行调整,最后完成一个较为合理的分布式锁. 本篇文章会将分布式锁的实现分 ...
- 基于redis的分布式锁(不适合用于生产环境)
基于redis的分布式锁 1 介绍 这篇博文讲介绍如何一步步构建一个基于Redis的分布式锁.会从最原始的版本开始,然后根据问题进行调整,最后完成一个较为合理的分布式锁. 本篇文章会将分布式锁的实现分 ...
- redis系列:基于redis的分布式锁
一.介绍 这篇博文讲介绍如何一步步构建一个基于Redis的分布式锁.会从最原始的版本开始,然后根据问题进行调整,最后完成一个较为合理的分布式锁. 本篇文章会将分布式锁的实现分为两部分,一个是单机环境, ...
- 基于Redis的分布式锁和Redlock算法
1 前言 前面写了4篇Redis底层实现和工程架构相关文章,感兴趣的读者可以回顾一下: Redis面试热点之底层实现篇-1 Redis面试热点之底层实现篇-2 Redis面试热点之工程架构篇-1 Re ...
- 身为一枚优秀的程序员必备的基于Redis的分布式锁和Redlock算法
1 前言 今天开始来和大家一起学习一下Redis实际应用篇,会写几个Redis的常见应用. 在我看来Redis最为典型的应用就是作为分布式缓存系统,其他的一些应用本质上并不是杀手锏功能,是基于Redi ...
- 基于 Redis 的分布式锁
前言 分布式锁在分布式应用中应用广泛,想要搞懂一个新事物首先得了解它的由来,这样才能更加的理解甚至可以举一反三. 首先谈到分布式锁自然也就联想到分布式应用. 在我们将应用拆分为分布式应用之前的单机系统 ...
- 基于redis的分布式锁实现
1.分布式锁介绍 在计算机系统中,锁作为一种控制并发的机制无处不在. 单机环境下,操作系统能够在进程或线程之间通过本地的锁来控制并发程序的行为.而在如今的大型复杂系统中,通常采用的是分布式架构提供服务 ...
- 基于 redis 的分布式锁实现 Distributed locks with Redis debug 排查错误
小结: 1. 锁的实现方式,按照应用的实现架构,可能会有以下几种类型: 如果处理程序是单进程多线程的,在 python下,就可以使用 threading 模块的 Lock 对象来限制对共享变量的同步访 ...
随机推荐
- nvm安装管理nodejs
安装nodejs运行环境 相关连接 步骤 下载nvm-window并安装: https://github.com/coreybutler/nvm-windows/releases 下载完成后直接解压安 ...
- 从 Nginx 优秀的核心架构设计,揭秘其为何能支持高并发?
目录: 1. Nginx的整体架构 2. Nginx的模块化设计 3. Nginx的请求方式处理 4. Nginx事件驱动模型 5. Nginx进程处理模型 写在前面 Nginx 是一个 免费的,开源 ...
- Redundant Paths 分离的路径
Redundant Paths 分离的路径 题目描述 为了从F(1≤F≤5000)个草场中的一个走到另一个,贝茜和她的同伴们有时不得不路过一些她们讨厌的可怕的树.奶牛们已经厌倦了被迫走某一条路,所以她 ...
- 小程序动态修改页面标题setNavigationBarTitle
可以使用setNavigationBarTitle方法动态设置页面标题 wx.setNavigationBarTitle({ title: options.name, })
- 『无为则无心』Python序列 — 17、Python字符串操作常用API
目录 1.字符串的查找 @1.find()方法 @2.index()方法 @3.rfind()和rindex()方法 @4.count()方法 2.字符串的修改 @1.replace()方法 @2.s ...
- 什么是OSI的第7层
1.什么是Internet的第7层? 第7层是指Internet的7层OSI模型的顶层,也称为"应用程序层".这是数据处理的顶层,位于用户与之交互的软件应用程序的表面之下或幕后.例 ...
- 不藏了,这些Java反射用法总结都告诉你们
摘要:Java反射是一种非常强大的机制,它可以在同一个系统中去检测内部的类的字段.方法和构造函数.它非常多的Java框架中,都大量应用了反射技术,如Hibernate和Spring.可以说,反射机制的 ...
- 【Azure 应用程序见解】Application Insights Java Agent 3.1.0的使用实验,通过修改单个URL的采样率来减少请求及依赖项的数据采集
问题描述 近日好消息,如果是一个Java Spring Cloud的项目,想使用Azure Applicaiton Insights来收集日志及一些应用程序见解.但是有不愿意集成SDK来修改代码或者配 ...
- Linux指令手册 (一)
指令格式 指令主体 [选项] [操作对象] 一个完整的指令是由"指令主体"."选项"和"操作对象"组成的,其中指令主体只能有一个,选项有零个 ...
- 1.3.4、通过Host匹配
server: port: 8080 spring: application: name: gateway cloud: gateway: routes: - id: guo-system4 uri: ...