Redis锁与幂等性不得不说的故事

news2025/7/21 10:27:18

前言:

相信很多小伙伴对缓存锁都不陌生,但是简单的缓存锁想要用好还是需要一些功力。本文总结了笔者多年使用缓存所的一些心得,欢迎交流探讨~

幂等模型:

幂等场景一般由查重+写入两步操作组成,两步操作组成一个最小完整逻辑,再通过缓存锁保证原子性

实现:

实现redis分布式锁需要注意两个关键点:保证原子性、设置过期时间

保证原子性的目的:是为了保证同一时间只有一个请求能获取到锁

设置过期时间的目的:是为了防止解锁失败导致死锁

public class MethodLock {

    private static final Logger logger = LoggerFactory.getLogger(MethodLock.class);

    public static final String KEY_SEPARATOR = ":";
    public static final String PARAM_SEPARATOR = "_";
    public static final String KEY_PARAM_SEPARATOR = "#";
    public static final String SET_SUCCESS_RESULT = "OK";
    public static final String METHOD_LOCK = "doraemon:method:lock";


    private static Jedis jedis;

    private static Jedis getJedis() {
        if (jedis == null) {
            jedis = 自行实现;
        }
        return jedis;
    }


    /**
     * 获取锁
     *
     * @param methodName 方法名,类名加方法名(例:MethodLock.getLock)
     * @param timeout    锁过期时间(单位秒)
     * @param params     参数(通过参数控制锁的粒度)
     * @return
     */
    public static boolean getLock(String methodName, long timeout, String... params) {
        String method = "getLock|获取锁|";

        try {
            String key = getKey(methodName, params);
            String result = getJedis().set(key, methodName, "nx", "ex", timeout <= 0 ? 5 : timeout);
            if (Objects.equals(SET_SUCCESS_RESULT, result)) {
                return true;
            }
        } catch (Exception e) {
            logger.error(method + "执行失败,methodName={},timeout={},params={}", methodName, timeout, JSONObject.toJSONString(params), e);
        }

        return false;
    }

    /**
     * 释放锁
     *
     * @param methodName 方法名,类名加方法名(例:MethodLock.getLock)
     * @param params     参数(通过参数控制锁的粒度)
     * @return
     */
    public static boolean delLock(String methodName, String... params) {
        String method = "delLock|释放锁|";

        try {
            String key = getKey(methodName, params);
            long result = getJedis().del(key);
            if (result > 0) {
                return true;
            }
        } catch (Exception e) {
            logger.error(method + "执行失败,methodName={},params={}", methodName, JSONObject.toJSONString(params), e);
        }

        return false;
    }

    /**
     * 【私有方法】获取redis key
     *
     * @param methodName
     * @param params
     * @return
     */
    protected static String getKey(String methodName, String... params) {
        if (StringUtils.isBlank(methodName)) {
            return null;
        }
        String key = METHOD_LOCK + KEY_SEPARATOR + methodName;
        if (params != null && params.length > 0) {
            key += KEY_PARAM_SEPARATOR + Joiner.on(PARAM_SEPARATOR).useForNull("null").join(params);
        }
        return key;
    }

注意事项:

1、锁范围内的逻辑需要 完整+精简

锁范围内指的是:获取锁和释放锁中间的逻辑,只有必须保证原子性的关键的逻辑才能放入到锁范围内,其他的一些不相关逻辑完全可以放在锁范围外处理

完整:加锁的目的是为了解决并发问题,所以锁里面的逻辑要求完整,不完整的逻辑=没加锁

比如幂等场景下:一般是 查重+写入 两个操作需要保证原子性,这两个操作加起来就是一个完整逻辑

精简:精简的意思是在保证完整的前提下,不要有多余的逻辑,以免锁占用时间过长,进而影响性能

2、锁粒度选择要恰当

锁粒度指的是:锁对请求条件筛选的粗细程度,例如用户购买商品下单时可以 1、根据用户id加锁,2、也可以根据用户id + 商品id加锁,1和2就是两种粒度

锁的粒度太大会导致锁的范围过大,可能会影响当前逻辑之外的业务

锁的粒度太小会导致锁的范围过小,可能会导致锁失效

3、锁过期时间设置要合理

一般建议过期时间 = 逻辑执行时间 * 150%

过期时间太小可能导致在逻辑执行完成前,锁过期失效

过期时间太大+解锁失败,可能导致在锁过期失效之前重试的请求被拒之门外

4、加锁在try之前,锁中的逻辑使用try catch包围,解锁在finally里处理

若加锁操作在try catch中,并发场景下未获取锁的操作会执行到finally里将锁解除,影响正常逻辑

防止逻辑中出现异常,阻断流畅,导致解锁操作执行不到

5、基于redis的分布式锁并不100%可靠

在一些特殊情况下,比如redis宕机,数据丢失,可能会导致锁失效

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/395218.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringSecurity支持WebAuthn认证

WebAuthn是无密码身份验证技术&#xff0c;解决了密码泄露的风险&#xff0c;主流的浏览器都支持。有很多开源的类库实现了WebAuthn规范&#xff0c;Java下流行的类库有&#xff1a;webauthn4jjava-webauthn-serververtx-authSpring Security官方暂时未支持WebAuthn&#xff0c…

怎样编写java程序

搭建好了Java开发环境之后&#xff0c;下面就来学习一下如何开发Java程序。为了让初学者更好地完成第一个Java程序&#xff0c;接下来通过几个步骤进行逐一讲解。 1&#xff0e;编写Java源文件 在D盘根目录下新建一个test文件夹&#xff0c;并在该文件夹中新建文本文档&#…

运维自动化之Ansible

一&#xff1a;Ansible的概述ansible的简介Ansible是一款为类Unix系统开发的自由开源的配置和自动化工具。它用Python写成&#xff0c;类似于saltstack和Puppet&#xff0c;但是有一个不同和优点是我们不需要在节点中安装任何客户端。它使用SSH来和节点进行通信。Ansible基于 P…

【C++】Clang-Format:代码自动格式化(看这一篇就够了)

文章目录Clang-format格式化C代码1.引言&安装1.1引言1.2 安装2. 配置字解释2.1 language 编程语言2.2 BaseOnStyle 基础风格2.3 AccessModifierOffset 访问性修饰符偏移2.4 AlignAfterOpenBracket 开括号后的对齐2.5 AlignArrayOfStructures 对齐结构体数组2.6 AlignConsec…

中电金信Gien享汇・大数据专题|金融行业数据架构及模型演进

本期嘉宾 陈子刚 中电金信商业分析事业部华南区总经理 毕业于复旦大学&#xff0c;硕士研究生&#xff1b;拥有16年以上金融行业商业智能领域从业经验&#xff1b;曾就职于中国工商银行、Teradata、东亚银行&#xff0c;服务于平安银行、广发银行、招商银行、广东农信、招商…

IT项目经理的自我修养手册(续)

上一节从工作职责和如何提升IT项目经理的个人能力讲述了作为一个职业项目经理的自我修养&#xff0c; 入口地址&#xff1a; IT项目经理的自我修养手册 本节将会从计划、组织、领导、控制这四个方面&#xff0c;系统的介绍作为职业项目经理的工作职责和工作范围。 一、计划 …

Springboot怎么实现WebSocket通信(一)

文章示例环境配置信息jdk版本:1.8开发工具&#xff1a;Intellij iDEA 2020.1springboot:2.3.9.RELEASE什么是WebSocket?WebSocket&#xff0c;是HTML5下一种新的协议&#xff0c;支持web浏览器和服务器端之间双向全双工通信 &#xff0c;基于TCP协议实现。WebSocket主要特性1、…

console使用方法介绍

console是在写前端Javascript时经常会使用到&#xff0c;我平时使用最多的是console.log&#xff0c;相比大多数人也是如此吧&#xff01; 下面一起来看一下强大的console吧&#xff01; 01函数&#xff08;属性&#xff09; 包含如下函数 / 属性&#xff1a;memory、assert、c…

2023年最新最全 VSCode 插件推荐

Visual Studio Code 是由微软开发的一款免费的、针对于编写现代Web和云应用的跨平台源代码编辑器。它包含了一个丰富的插件市场&#xff0c;提供了很多实用的插件。下面就来分享 2023 年前端必备的 VS Code 插件&#xff01; 前端框架 ES7 React/Redux/React-Native snippets …

洗地机哪个牌子比较好?家用洗地机推荐

洗地机是可以做到扫地的同时把地也拖了&#xff0c;可以做到高效清洁&#xff0c;减轻家务负担。还具有杀菌功能&#xff0c;不用担心拖完地之后地面还有细菌滋生啦&#xff0c;洗地机可以做到即洗即干&#xff0c;无需等待拖完地之后还潮湿不能走路&#xff0c;尤其对于木地板…

简述下 React 的事件代理机制?

React 并不会把所有的处理函数直接绑定在真实的节点上。而是把所有的事件绑定到结构的最外层&#xff0c;使用一个统一的事件监听器&#xff0c;这个事件监听器上维持了一个映射来保存所有组件内部的事件监听和处理函数。 当组件挂载或卸载时&#xff0c;只是在这个统一的事件…

LIN资料整理(一):LIN入门简介

目录 一、LIN是什么 1、LIN简介 2、LIN的适用场景 3、LIN协议版本 4、LIN的主从机节点、主从机任务与LIN总线特点 一、LIN是什么 1、LIN简介 LIN 是Local Interconnect Network 的缩写&#xff0c;是基于UART/SCI(Universal Asynchronous Receiver-Transmitter / Serial…

2023级社科院与杜兰大学金融管理硕士还有少量名额,期待与你共谱人生新篇章

我们都是平凡人&#xff0c;过着平凡的生活&#xff0c;但若能有所热爱有所坚持&#xff0c;便会发出自己的光芒。就像我们在社科院与杜兰大学金融管理硕士项目读研&#xff0c;通过更加系统的学习&#xff0c;不仅丰富了我们的知识&#xff0c;还提升了我们的思维&#xff0c;…

NB-IOT宣传这么多年,这次总算用好了吧

一、方案概述随着实体经济快速发展&#xff0c;石化、港口、货场、工地等区域规模日益扩大&#xff0c;厂区面积广阔、环境复杂、作业人员和车辆众多&#xff0c;如无法实时掌握工作人员状态及外来人员位置、外来车辆情况等问题&#xff0c;将存在非常大的安全隐患。今天小编介…

ChatGPT在工业领域的用法

在工业数字化时代&#xff0c;我们需要怎么样的ChatGPT&#xff1f; 近日&#xff0c;ChatGPT热度高居不下&#xff0c;强大的人机交互能力令人咋舌&#xff0c;在国内更是掀起一股讨论热潮。一时间&#xff0c;这场由ChatGPT引起的科技飓风&#xff0c;使得全球最顶尖科技力量…

notepad++学习小技巧

不要小瞧了notepadd 这个可是我们的cv好帮手。。。 实战1背景&#xff0c;我找一个同事要表结构 结果他给我了一个xml。顿时一懵&#xff0c;我也不知道为啥好像是从前端扣下来的。 建表我只需要 columnName, displayName当作是comment&#xff0c; dataTypeNamecolumnType借鉴…

【计算机视觉】Visual grounding系列

文章目录一、任务简介二、Visual grounding常用数据集与评估指标2.1 常用数据集2.2 评估指标三、Visual grounding主流做法一、任务简介 Visual grounding涉及计算机视觉和自然语言处理两个模态。 简要来说&#xff0c;输入是图片&#xff08;image&#xff09;和对应的物体描…

市场营销书籍推荐:《经理人参阅:市场营销》

要学好市场营销有什么好方法&#xff1f;答案是看书&#xff01;比起碎片化地去阅读一些文章或看一些相关视频&#xff0c;读书来得更实在些。倘若能静下心来好好读上一本系统性的市场营销书籍&#xff0c;学好营销管理将不会再是一件难事。然而&#xff0c;问题的关键是&#…

大模型分布式系统

背景&#xff1a;模型越来越大&#xff0c;训练复杂度越来越高&#xff0c;需要训练的时间也是越来越长。那么我们该如何在现有的硬件基础上对模型做训练呢。模型规模的扩大&#xff0c;对硬件&#xff08;算力、内存&#xff09;的发展提出要求。然而&#xff0c;因为 内存墙 …

2023年襄阳中级工程师职称评审通知出来了哟

襄阳市职称改革工作领导小组办公室关于做好2022年度襄阳市非公企业工程系列中级任职资格评审工作的通知 各县&#xff08;市、区&#xff09;人力资源和社会保障局&#xff08;职改办&#xff09;&#xff1a; 根据市职改办《关于做好2022年度全市职称评审工作的通知》&#x…