JedisCluster分布式锁

基于Redis Cluster的分布式锁实现以互斥方式操作共享资源 今天要说的技术方案也是有一定项目背景的。在上一个项目中,我们需要对一个redis集群中过期的key进行处理,这是一个分布式系统,考虑到高可用性,需要具备过期处理功能的服务有多个副本,这样我们就要求在同一时间内仅有一个副本可以对过期的key>进行处理,如果该副本挂掉,系统会在其他副本中再挑选出一个来处理过期的key。很显然,这里涉及到一个选主(leader election)的过程。每当涉及选主,很多人就会想到一些高大上的分布式一致性/共识算法,比如: raft 、 paxos 等。... 阅读详情

private volatile String unlockSha1 = “”;

private static final Long UNLOCK_SUCCESS_CODE = 1L;

private static final String LOCK_SUCCESS_CODE = "ok";
private static final String UNLOCK_LUA;
private static final String BIZ = "redislock:biz:";
private ThreadLocal<String> lockFlag = new ThreadLocal<>();
/*
 * 通过lua脚本释放锁,来达到释放锁的原子操作
 */
static {
    UNLOCK_LUA = "if redis.call(\"get\",KEYS[1]) == ARGV[1] " +
            "then " +
            "    return redis.call(\"del\",KEYS[1]) " +
            "else " +
            "    return 0 " +
            "end ";
}

/**
 * lua脚本:判断锁住值是否为当前线程持有,是的话解锁,不是的话解锁失败
 */
private static final String DISTRIBUTE_LOCK_SCRIPT_UNLOCK_VAL = "if" +
        " redis.call('get', KEYS[1]) == ARGV[1]" +
        " then" +
        " return redis.call('del', KEYS[1])" +
        " else" +
        " return 0" +
        " end";
@Autowired
private JedisCluster jedisCluster;

/**
 * 根据loopTryTime循环重试
 * @param lockKey 锁key
 * @param lockVal 锁值,用于解锁校验
 * @param expiryTime 锁过期时间
 * @param loopTryTime 获取失败时,循环重试获取锁的时长
 * @return 是否获得锁
 */
public boolean tryLock(String lockKey, String lockVal, long expiryTime, long loopTryTime){
    Long endTime = System.currentTimeMillis() + loopTryTime;
    while (System.currentTimeMillis() < endTime){
        if (tryLock(lockKey, lockVal, expiryTime)){
            return true;
        }
    }
    return false;
}
/**
 * 根据loopTryTime循环重试
 * @param lockKey 锁key
 * @param lockVal 锁值,用于解锁校验
 * @param expiryTime 锁过期时间
 * @param retryTimes 重试次数
 * @param setpTime 每次重试间隔 mills
 * @return 是否获得锁
 */
public boolean tryLock(String lockKey, String lockVal, long expiryTime, int retryTimes, long setpTime){
    while (retryTimes > 0){
        if (tryLock(lockKey, lockVal, expiryTime)){
            return true;
        }
        retryTimes--;
        try {
            Thread.sleep(setpTime);
        } catch (InterruptedException e) {
            log.error("get distribute lock error" +e.getLocalizedMessage());
        }
    }
    return false;
}
/**
 * 一次尝试,快速失败。不支持重入
 * @param lockKey 锁key
 * @param lockVal 锁值,用于解锁校验
 * @param expiryTime 锁过期时间 MILLS
 * @return 是否获得锁
 */
public boolean tryLock(String lockKey, String lockVal, long expiryTime){
    //相比一般的分布式锁,这里把setNx和setExpiry操作合并到一起,jedis保证原子性,避免连个命令之间出现宕机等问题
    //这里也可以我们使用lua脚本实现
    SetParams setParams =  SetParams.setParams();
    setParams.nx();
    setParams.ex((int)expiryTime);
    String result = jedisCluster.set(lockKey.getBytes(), lockVal.getBytes(),setParams);
    return LOCK_SUCCESS_CODE.equalsIgnoreCase(result);
}
/**
 * 释放分布式锁,释放失败最可能是业务执行时间长于lockKey过期时间,应当结合业务场景调整过期时间
 * @param lockKey 锁key
 * @param lockVal 锁值
 * @return 是否释放成功
 */
public boolean tryUnLock(String lockKey, String lockVal){
    List<String> keys = new ArrayList<>();
    keys.add(lockKey);
    List<String> argv = new ArrayList<>();
    argv.add(lockVal);
    try {
        Object result = jedisCluster.evalsha(unlockSha1, keys, argv);
        return UNLOCK_SUCCESS_CODE.equals(result);
    }catch (JedisNoScriptException e){
        //没有脚本缓存时,重新发送缓存
        log.info("try to store script......");
        storeScript(lockKey);
        Object result = jedisCluster.evalsha(unlockSha1, keys, argv);
        return UNLOCK_SUCCESS_CODE.equals(result);
    }catch (Exception e){
        e.printStackTrace();
        return false;
    }
}
/**
 * 由于使用redis集群,因此每个节点都需要各自缓存一份脚本数据
 * @param slotKey 用来定位对应的slot的slotKey
 */
public void storeScript(String slotKey){
    if (StringUtilsPlus.isEmpty(unlockSha1) || !jedisCluster.scriptExists(unlockSha1, slotKey)){
        //redis支持脚本缓存,返回哈希码,后续可以继续用来调用脚本
        unlockSha1 = jedisCluster.scriptLoad(DISTRIBUTE_LOCK_SCRIPT_UNLOCK_VAL, slotKey);
    }
}
信息安全与技术——(十一)恶意代码检测与防范技术 恶意代码(Malicious Code )或恶意软件(Malware )主要是指以危害信息的安全等不良意图为目的的程序,它们一般潜伏在受害计算机系统中实施破坏或窃取信息。 阅读详情

相关推荐

用Codex自动化挖掘电梯行业外贸客户:从关键词到22维深度分析

在B2B外贸客户开发中,精准定位垂直行业潜在客户是核心挑战。传统手动搜索效率低下,而数据驱动的工作流正成为解决方案。其原理在于将模糊的业务需求转化为机器可识别的结构化查询,通过组合行业核心关键词(如“Elevator Manufacturer”、“Elevator Maintenance”)与商业角色描述,系统性地从海量数据中筛选目标。这种自动化抓取技术的价值在于,它不仅生成客户名单,更通过多维数据分析(如公司规模、业务标签、数字足迹)构建初步的客户画像,为后续的优先级排序和个性化触达提供情报基础。在工业制

weixin_34054866的博客 453

Redis怎样实现分布式锁?

我们知道,在Java单进程中,多线程的环境下,如果我们要操作一个共享变量,需要使用synchronized或者是JUC同步工具类才能保证线程安全。那么,多进程环境下,我们要怎样保证线程安全?

BASK2312的博客 523

银河麒麟系统V10 Server SP1 安装Oracle 19c

•oracle-database-preinstall-19c 这个工具会自动配置系统参数,创建 oracle 用户和组。比较方便。•••••银河麒麟高级服务器操作系统V10 - 国产操作系统、银河麒麟、中标麒麟、开放麒麟、星光麒麟——麒麟软件官方网站。

fuguimashu的博客 4320

Redis分布式锁实战

什么是分布式锁 在单机部署的情况下,要想保证特定业务在顺序执行,通过JDK提供的synchronized关键字、Semaphore、ReentrantLock,或者我们也可以基于AQS定制化锁。单机部署的情况下,锁是在多线程之间共享的,但是分布式部署的情况下,锁是多进程之间共享的。那么分布式锁要保证锁资源的唯一性,可以在多进程之间共享。 分布式锁特性 保证同一个方法在某一时刻只能在一台机...

胡峻峥的博客 362

保姆级教程:在Ubuntu 22.04上搞定PX4 V1.14 + ROS2 Humble的HITL仿真(避坑实录)

本文提供在Ubuntu 22.04上配置PX4 V1.14与ROS2 Humble的HITL仿真环境的详细教程,涵盖环境准备、固件编译、QGroundControl配置、ROS2通信设置及联调测试。特别针对版本兼容性、Gazebo插件构建和MicroDDS配置等常见问题提供避坑指南,帮助开发者高效搭建无人机仿真系统。

weixin_30836759的博客 999

黏菌算法(Slime Mould Algorithm,SMA)

这是一篇关于黏菌算法的总结博客,包含算法思想,算法步骤,求函数最值(Python实现),算法改进等,持续更新ing

weixin_46838605的博客 1万+

redis实现分布锁

目录 前言 实现 注意 加解锁 jedis集群,哨兵模式在spring的配置 前言 参考:https://redis.io/commands/set 针对实现分布式锁,redis为方便用户实现,出现了set key value EX NX的系统命令进行实现。 注意:由于SET命令选项可以替换SETNX、SETEX、PSETEX、GETSET,因此在未来的 Redis 版本中,这些命令可能会被弃用并最终被删除。 所以以后可能SETNX这样的命令估计不存在了。 NX-- 仅在不存在..

wliang578的博客 443

手把手教你用STM32F030实现功率MOS双脉冲测试(附完整电路图)

本文详细介绍了如何使用STM32F030微控制器搭建功率MOSFET双脉冲测试平台。通过分析双脉冲测试原理,提供了完整的硬件电路设计、驱动电路选型、软件时序生成方法,并指导如何利用示波器捕获和分析开关波形,从而评估功率器件的动态特性与开关损耗。

juice的博客 711

SpringBoot集成Redis - Redis分布式锁的实现之Jedis(setNXPX+Lua)

分布式锁相关的内容请参考分布式系统 - 分布式锁及实现方案(具体看分布式系统 - 分布式锁及实现方案中Redis实现分布式锁的部分)加锁: set NX PX + 重试 + 重试间隔向Redis发起如下命令:其中,"productId"由自己定义,可以是与本次业务有关的id,"0xx9p03001"是一串随机值,必须保证全局唯一(原因在后文中会提到),“NX"指的是当且仅当key(也就是案例中的"productId:lock”)在Redis中不存在时,返回执行成功,否则执行失败。

明平姚的博客 932

声音源定位:利用YOLO与麦克风阵列定位声音来源YOLOv5、YOLOv8、YOLOv10

YOLO(You Only Look Once)是一个用于目标检测的深度学习模型。YOLO的最大特点是其通过一次前向传播即可完成多个目标的检测,速度和精度相对其他目标检测算法具有显著优势。YOLO模型的版本不断更新,从YOLOv1到YOLOv10,算法精度和速度都有了显著的提升。声音源定位是利用多个麦克风阵列收集的声音信号,通过算法计算声音源的位置。声音源定位的关键在于准确估计每个麦克风的声音到达时间,从而确定声音源的空间坐标。基于时延估计(TDOA)

YOLO 672

大厂校招:星宸科技嵌入式面试及参考答案(5万字长文)

当一个新的硬件设备被插入系统时,内核会发送一个设备事件通知 udev,udev 会根据设备的属性和规则,为该设备创建一个合适的设备文件。通过去除不必要的驱动程序、禁用不需要的功能、选择合适的内核配置选项、优化内核编译选项和定制内核模块等方法,可以减小内核的大小和复杂性,提高系统的性能和稳定性。上半部通常是在中断关闭的情况下执行的,以确保中断处理的原子性。处理碎片化内存是内存管理中的一个重要问题,可以采用内存压缩、内存池管理、伙伴系统、首次适应算法和最佳适应算法等方法来减少内存碎片的产生,提高内存的利用率。

大模型大数据攻城狮的专栏 2926

Redis分布式锁之 JedisCluster 分布式Lock

Redis分布式锁重要的原则就是,加锁、解锁要原子性。Redis官方网站提供了RedLock锁。但是我感觉那个锁比较臃肿,完全没有必要。如果集群中有故障。锁获取失败就可以了,Redis锁的机制就决定了他不能像数据库事物一样。所以集群中挡掉节点的情况,我不予考虑。 代码示例: /** * 获取redis锁,有重试机制 * @param lockKey 锁的key * @param redisLockRequestId new 一个RedisLockRequestId 对象即可 -

-韧-的博客 1695

39-高级优化技术:指令调度与乱序执行 - 手把手教你手写CPU

本文介绍了现代处理器设计中提高指令级并行性(ILP)的两种关键技术:指令调度和乱序执行。指令调度分为静态调度(由编译器完成)和动态调度(由硬件完成),后者能更好适应运行时情况但复杂度更高。乱序执行通过动态重排指令顺序提高硬件利用率,其核心组件包括重排序缓冲区、保留站和寄存器重命名。文章提供了保留站的Verilog实现示例,并分析了不同优化技术在性能、硬件开销和功耗方面的权衡。最终指出,CPU设计需根据性能、功耗等需求选择合适的优化技术。

2301_79143213的博客 85

redis集群+JedisCluster+lua脚本实现分布式锁

这个过程可能存在问题就是,lock1在获取值之后,刚好到了有效期了,那么锁可能会在此时被锁竞争者2获得,并且设置锁lock2,然而这时锁竞争者1删除锁的指令刚好重新发送到redis-server,就会误删lock2,导致后续会被其他锁竞争者3获取,发送不可知业务错误。我们知道,分布式锁在解锁时一定需要验证是不是锁的持有者,这种情况下,我们需要进行的操作就有获取key的对应value,然后验证value的值,这个过程,存在一种情况,导致误删别的持有者的锁。获取到锁的线程,sleep2秒,然后释放锁。

我的博客 557

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

redis集群+JedisCluster+lua脚本实现分布式锁(转)

https://blog.youkuaiyun.com/qq_20597727/article/details/85235602 在这片文章中,使用Jedis clien进行lua脚本的相关操作,同时也使用一部分jedis提供的具有原子性set操作来完成值和过期时间的同时设置。使用lua脚本根本原因也是为了保证我们两个redis操作之间的原子性,使分布式锁更加可靠。 JedisCluster相关代码...

weixin_30847865的博客 304

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

jedisCluster中分布式锁遇到的坑总结篇

不知道大家有没有遇到过jedisCluster.set()方法上锁时出现上锁成功但返回结果并不是OK, 具体需求如下: 1.跑批量订单,需要对每个订单进行操作。 2.其他地方可能操作这些订单。 3.为了只有一个地方操作,将所有的订单逐一上锁出现问题, 之后我对jedisCluster进行测试 代码如下我们做三次测试以确保实验的准确性: 测试1: 结果如下 redis中查看 ...

it小小弟的博客 6272

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

springboot 集成redis集群配置JedisCluster,并用redis实现分布式锁

一、redis在工作是一个常见的工具,这里对redis和springboot形成集群做一个简单示例。 (1)引入对应redis集群所需要maven文件 <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifac...

fajing_feiyue的博客 5012

JedisCluster锁

一、前置配置 需要已经集成成功JedisCluster 本人已实践的参考:https://blog.youkuaiyun.com/NullToSay/article/details/109813194 二、定义RedisLock类 import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import redis.clients.jedis.JedisClust.

NullToSay的踩坑日常 1175

redis与分布式锁浅谈

背景:最近遇到一个生产问题,分布式部署了十几条服务器,有个业务过期的定时任务会每天发邮件提醒用户,然而用户最近反馈,每天收到好几封提醒邮件,于是排查多发的原因。指查询一个一定不存在的数据,由于缓存是不命中,将去查询数据库,但是数据库也无此记录,我们没有将这次查询的null写入缓存,这将导致这个不存在的数据每次请求都要到存储层去查询,失去了缓存的意义。加锁大量并发只让一个去查,其他人等待,查到以后释放锁,其他人获取到锁,先查缓存,就会有数据,不用去db。设置锁的自动过期,即使没有删除,会自动删除。

m0_37635053的博客 2129

Redis(3):Spring集成redis及实现分布式锁

1、pom文件 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/m

qq_30155803的博客 876

JedisCluster实践

1. Spring中运用JedisCluster http://blog.youkuaiyun.com/u010739551/article/details/52438101[spring集成 JedisCluster 联接 redis3.0 集群] 引用Maven依赖 增加Spring配置,包括Redis连接(classpath:connect-redis.properties) 实现Facto...

weixin_30338461的博客 117

Redis实现分布式锁

private static final String LOCK_SUCCESS = "OK"; private static final String SET_IF_NOT_EXIST = "NX"; private static final String SET_WITH_EXPIRE_TIME = "PX"; private static final Long RE...

神秘的博客 182

java redis getset_Java JedisCluster.getSet方法代码示例

import redis.clients.jedis.JedisCluster; //导入方法依赖的package包/类public synchronized boolean acquire(JedisCluster jedis) throws InterruptedException {int timeout = timeoutMsecs;while (timeout >= 0) {lon...

weixin_36044301的博客 780

Redis学习笔记(五)jedis(JedisCluster)操作Redis集群 redis-cluster

版本说明 jedis2.9.0 redis3.2.5 这里只是几个简单的demo,直接上代码吧,没啥好说的import org.apache.commons.pool2.impl.GenericObjectPoolConfig; import org.junit.After; import org.junit.Before; import org.junit.Test; import r

刘本龙的专栏 12万+

Redis分布式锁实现

Redis锁主要用到了Redis中的以下几个API,这里引用官方的API文档介绍说明一下: SETNX Set key to hold string value if key does not exist. In that case, it is equal to SET. When ke...

chouhui0263的博客 168
上一篇: prometheus+grafana+全方位立体监控redis
下一篇: 文件预览服务器kkfileview安装部署(linux 版)
狂野弘仁
博客等级 码龄8年 34粉丝 81原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值