使用redis创建自己的分布式锁

R2M缓存介绍-业务使用方面.pptx R2M缓存介绍-业务使用方面 立即下载

作者 QQ 1135409377 欢迎加Q 交流

RedisLock 简介

1:支付公平锁,非公平锁(只是在单机器范围内)
2:不支持锁的重入(即 同一个线程,不能获取同一把锁两次及以上)
3:一个redis的key对应一个锁
4:参数可配置
5:可以像 使用 java.util.concurrent.locks.ReentrantLock 一样使用。

RedisLock 方法介绍

不可中断,直到获取锁为止
lock(String key, int keyExpireSecond)

如果当前线程未被中断,则直到获取锁为止
lockInterruptibly(String key, int keyExpireSecond) throws InterruptedException

如果锁可用,则获取锁,并立即返回值 true。如果锁不可用,则此方法将立即返回值 false。
tryLock(String key, int keyExpireSecond)

如果锁可用,则此方法将立即返回值 true。如果锁不可用,出于线程调度目的,将挂起当前线程,如果在线程挂起期间中断线程,则排除 InterruptedException
tryLock(String key, int keyExpireSecond, long timeout, TimeUnit unit)

RedisLock 使用演示

注意:演示的demo中使用的redisClient,是我们公司自己把redis给封装了。
需要使用者把 RedisLock 的 属性 redisClient 的对象类型修改为 自己的 redis 客户端的对象类型,列入 jedis,并且 spring xml 中,<constructor-arg name="redisClient" ref="r2mClusterClient"/>
把使用者自己的 redis 客户端的对象类型,注入到 redisClient 中。

spring xml 配置
<bean id="zkProvider" class="com.wangyin.rediscluster.provider.ZkProvider">
        <constructor-arg name="appName" value="QWE"/> <!--请修改为自己的appName-->
        <constructor-arg name="zkConnectionStr" value="178.28.48.208:2181,178.28.48.228:2181,178.28.48.248:2181"/>  <!--请修改为所需要使用环境的地址-->
        <constructor-arg name="zkTimeout" value="25000"/>
    </bean>

    <!--连接池配置, 这里连接配置指的是所有主节点得配置,指的是每一个主节点连接数,其他相关参数参看ApacheCommonPool-->
    <bean id="redisPoolConfig" class="com.wangyin.r2m.client.jedis.JedisPoolConfig">
        <property name="blockWhenExhausted" value="true"/> <!--连接池耗尽时是否阻塞-->
        <property name="maxWaitMillis" value="500" />
        <property name="maxTotal" value="15"/> <!---最大连接数,如果blockWhenExhausted为false会阻塞,为true会抛出异常-->
        <property name="maxIdle" value="10"/>  <!--最大可以保的空闲连接数量,实际空闲连接数会在 maxIdle与minIdle 之间-->
        <property name="minIdle" value="0"/> <!-- 最小空闲保持连接数,避免频繁创建-->
    </bean>

    <bean id="cacheClusterConfigProvider" class="com.wangyin.rediscluster.provider.CacheClusterConfigProvider">
        <property name="providers">
            <list>
                <ref bean="zkProvider"/>
            </list>
        </property>
    </bean>

    <bean id="r2mClusterClient" class="com.wangyin.rediscluster.client.R2mClusterClient">
        <property name="maxRedirections" value="3"/>
        <property name="redisTimeOut" value="500"/>
        <property name="redisPoolConfig" ref="redisPoolConfig"/>
        <property name="provider" ref="cacheClusterConfigProvider"/>
    </bean>
    <bean id="redisLock" class="com.lp.redis.lock.RedisLock">
        <!-- redis客户端 ,用户配置的时候,替换为自己的 redis客户端实例-->
        <constructor-arg name="redisClient" ref="r2mClusterClient"/>
        <!-- true 公平锁, false 非公平锁 ,默认值 false -->
        <constructor-arg name="fair" value="true"/>
        <!-- 尝试获取多少次锁后,如果还没有获取锁则挂起线程,默认值 2 -->
        <constructor-arg name="blockingAfterLockNum" value="5"/>
        <!-- 线程挂起时间,默认值 10毫秒 -->
        <constructor-arg name="parkThreadMilliscond" value="50"/>
     </bean>

测试代码
package com.lp.demo;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import com.lp.redis.lock.RedisLock;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Demo {
    public static void main(String[] args) throws InterruptedException {
        final String redisKey = "keyrs";//redis key
        final int keyExpireSecond = 5;//redis key值的有效期 单位秒
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("spring.xml");
        final RedisLock redisLock = ctx.getBean("RedisLock", RedisLock.class);
        int size = 321;
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        for(int i=1; i<=size; i++) {
            executorService.submit(new Runnable() {
                @Override
                public void run() {
                    redisLock.lock(redisKey, keyExpireSecond);
                    //执行业务逻辑
                    System.out.println(MySource.getAndDecrement());
                    //
                    redisLock.unlock(redisKey);
                }
            });
        }

        while(true) {
            Thread.sleep(1000);
            //打印调试信息
            System.out.println(redisLock.getContentOfKeyLockMap(redisKey));
        }
    }
}

RedisLock 代码

package com.lp.redis.lock;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock;

import com.wangyin.rediscluster.client.R2mClusterClient;

public class RedisLock {

    private ReentrantLock globalLock;
    /**
     * redis的一个key,对应一个 RedisLockThread
     */
    private Map<String, RedisLockThread> keyLockMap = new HashMap<String, RedisLockThread>();

    private R2mClusterClient redisClient;

    /**
     * 默认值 false
     * true,公平锁; false,非公平锁
     */
    private boolean fair;

    /**
     * 尝试获取多少次锁后,如果还没有获取锁则挂起线程,默认值 2
     */
    private int blockingAfterLockNum = 2;

    /**
     * 参数只对方法 lock,lockInterruptibly 有效
     * 线程挂起时间,默认值 10毫秒
     */
    private long parkThreadMilliscond = 10;

    /**
     * 挂起线程的纳秒数
     */
    private long parkThreadNano = parkThreadMilliscond * 1000 * 1000;

    public RedisLock(R2mClusterClient redisClient) {
        this.redisClient = redisClient;
        this.globalLock = new ReentrantLock(fair);
    }

    public RedisLock(boolean fair, int blockingAfterLockNum, long parkThreadMilliscond, R2mClusterClient redisClient) {
        this.fair = fair;
        this.blockingAfterLockNum = blockingAfterLockNum;
        this.parkThreadMilliscond = parkThreadMilliscond;
        this.parkThreadNano = parkThreadMilliscond * 1000 * 1000;
        this.redisClient = redisClient;
        this.globalLock = new ReentrantLock(fair);
    }

    public boolean isFair() {
        return fair;
    }

    public R2mClusterClient getRedisClient() {
        return redisClient;
    }

    public int getBlockingAfterLockNum() {
        return blockingAfterLockNum;
    }

    public long getParkThreadMilliscond() {
        return parkThreadMilliscond;
    }

    /**
     * 不可中断,直到获取锁为止
     * @param key redis的key值
     * @param keyExpireSecond redis key的有效期
     */
    public void lock(String key, int keyExpireSecond) {
        if (isBlank(key) || keyExpireSecond < 0) {
            throw new IllegalArgumentException("param is illegal");
        }
        boolean isSaveLock = false;
        RedisLockThread lockThread = null;
        if(fair) {//公平锁
            lockThread = saveLock(key);//保证一个key对应一个lock
            lockThread.getLock().lock();//线程获取锁
            isSaveLock = true;
        }
        int doNum = 0;
        do {
            long setNx = redisClient.setnx(key, String.valueOf(System.currentTimeMillis()));
            if (setNx == 1) {
                redisClient.expire(key, keyExpireSecond);
                return;
            } else {
                if(!isSaveLock) {
                    lockThread = saveLock(key);//保证一个key对应一个lock
                    lockThread.getLock().lock();//线程获取锁
                    isSaveLock = true;
                }
                doNum ++;
                if(doNum == blockingAfterLockNum) {//获取锁几次后,让然获取不到锁,则挂起线程指定的时间。
                    doNum = 0;
                    LockSupport.parkNanos(Thread.currentThread(), parkThreadNano);
                }
            }
        } while (true);
    }

    /**
     * 如果当前线程未被中断,则直到获取锁为止
     * @param key redis的key值
     * @param keyExpireSecond redis key的有效期
     * @throws InterruptedException
     */
    public void lockInterruptibly(String key, int keyExpireSecond) throws InterruptedException  {
        if (isBlank(key) || keyExpireSecond < 0) {
            throw new IllegalArgumentException("param is illegal");
        }
        boolean isSaveLock = false;
        RedisLockThread lockThread = null;
        if(fair) {//公平锁
            lockThread = saveLockInterruptibly(key);//保证一个key对应一个lock
            lockThread.getLock().lockInterruptibly();//线程获取锁
            isSaveLock = true;
        }
        int doNum = 0;
        do {
            long setNx = redisClient.setnx(key, String.valueOf(System.currentTimeMillis()));
            if (setNx == 1) {
                redisClient.expire(key, keyExpireSecond);
                return;
            } else {
                if(!isSaveLock) {
                    lockThread = saveLockInterruptibly(key);//保证一个key对应一个lock
                    lockThread.getLock().lockInterruptibly();//线程获取锁
                    isSaveLock = true;
                }
                doNum ++;
                if(doNum == blockingAfterLockNum) {//获取锁几次后,让然获取不到锁,则挂起线程指定的时间。
                    doNum = 0;
                    LockSupport.parkNanos(Thread.currentThread(), parkThreadNano);
                    if(Thread.interrupted()) {
                        throw new InterruptedException();
                    }
                }
            }
        } while (true);
    }

    /**
     * 如果锁可用,则获取锁,并立即返回值 true。如果锁不可用,则此方法将立即返回值 false。
     * @param key redis的key值
     * @param keyExpireSecond redis key的有效期
     * @return 如果获取了锁,则返回 true 否则返回 false。 
     */
    public boolean tryLock(String key, int keyExpireSecond) {
        if (isBlank(key) || keyExpireSecond < 0) {
            throw new IllegalArgumentException("param is illegal");
        }
        long setNx = redisClient.setnx(key, String.valueOf(System.currentTimeMillis()));
        if (setNx == 1) {
            redisClient.expire(key, keyExpireSecond);
            return true;
        }
        return false;
    }

    /**
     * 如果锁可用,则此方法将立即返回值 true。
     * 如果锁不可用,出于线程调度目的,将挂起当前线程,如果在线程挂起期间中断线程,则排除 InterruptedException
     * @param key redis的key值
     * @param keyExpireSecond redis key的有效期
     * @param timeout
     * @param unit
     * @return
     * @throws InterruptedException
     */
    public boolean tryLock(String key, int keyExpireSecond, long timeout, TimeUnit unit) throws InterruptedException {
        long lastTime = System.nanoTime();
        long nanosTimeout = unit.toNanos(timeout);
        if (isBlank(key) || keyExpireSecond < 0) {
            throw new IllegalArgumentException("param is illegal");
        }
        //
        boolean isSaveLock = false;
        RedisLockThread lockThread = null;
        if(fair) {//公平锁
            lockThread = saveLockInterruptibly(key);
            boolean isLock = lockThread.getLock().tryLock(timeout, unit);
            if(!isLock) {//没有获取锁
                lockThread.removeThreadOfLock(Thread.currentThread());//删除lock对应的线程
                return isLock;
            } else {
                isSaveLock = true;
            }
        }
        //
        int doNum = 0;//do{}while 循环多少次挂起线程
        do {
            long setNx = redisClient.setnx(key, String.valueOf(System.currentTimeMillis()));
            if (setNx == 1) {
                redisClient.expire(key, keyExpireSecond);
                return true;
            } else {
                if(!isSaveLock) {//非公平锁
                    lockThread = saveLockInterruptibly(key);
                    boolean isLock = lockThread.getLock().tryLock(timeout, unit);
                    if(!isLock) {
                        lockThread.removeThreadOfLock(Thread.currentThread());//删除lock对应的线程
                        return isLock;
                    } else {
                        isSaveLock = true;
                    }
                }
                //超时
                if (nanosTimeout <= 0) {
                    lockThread.removeThreadOfLock(Thread.currentThread());//删除lock对应的线程
                    lockThread.getLock().unlock();//lock释放锁
                    //删除 key 对应的锁
                    globalLock.lock();
                    if(lockThread.getThreadsOfLock() == 0) {//lock对应的线程数为 0,从集合中删除 key对应的lock。
                        keyLockMap.remove(key);
                    }
                    globalLock.unlock();
                    return false;
                }
                //循环获取锁
                doNum ++;
                if(doNum == blockingAfterLockNum) {
                    doNum = 0;
                    long now = System.nanoTime();
                    nanosTimeout -= now - lastTime;
                    LockSupport.parkNanos(Thread.currentThread(), nanosTimeout);
                    if (Thread.interrupted()) {
                        throw new InterruptedException();
                    }
                }
            }
        } while (true);
    }

    /**
     * 释放锁
     * @param key redis的key值
     */
    public void unlock(String key) {
        globalLock.lock();
        redisClient.del(key);//必须先删除redis的key
        RedisLockThread lockThread = keyLockMap.get(key);//获取key对应的lock
        if(lockThread != null) {
            if ( Thread.currentThread() != lockThread.getThreadOfLock(Thread.currentThread()) ) {//当前线程是否在,lock对应的线程集合内
                throw new IllegalMonitorStateException();
            } else {
                lockThread.removeThreadOfLock(Thread.currentThread());//删除lock对应的线程
                lockThread.getLock().unlock();//lock释放锁
                if(lockThread.getThreadsOfLock() == 0) {//lock对应的线程数为 0,从集合中删除 key对应的lock。
                    keyLockMap.remove(key);
                }
            }
        }
        globalLock.unlock();
    }

    /**
     * 保证一个key对应一个lock
     * key与lock是一对一的关系,lock与线程是一对多的关系
     * @param key
     * @return
     * @throws InterruptedException 
     */
    private RedisLockThread saveLock(String key) {
        globalLock.lock();//保证 saveLock 方法是原子操作
        //保证一个 key 只创建一个 lock
        RedisLockThread lockThread = keyLockMap.get(key);
        if(lockThread == null) {
            lockThread = new RedisLockThread(fair);
            lockThread.saveThreadOfLock(Thread.currentThread());//保存 lock 与 线程的关系
            keyLockMap.put(key, lockThread);//保存 key 与  lock 的关系
        }
        lockThread.saveThreadOfLock(Thread.currentThread());//保存 lock 与 线程的关系
        globalLock.unlock();
        return lockThread;
    }


    /**
     * 保证一个key对应一个lock
     * key与lock是一对一的关系,lock与线程是一对多的关系
     * @param key
     * @return
     * @throws InterruptedException 
     */
    private RedisLockThread saveLockInterruptibly(String key) throws InterruptedException{
        globalLock.lockInterruptibly();//保证 saveLockInterruptibly 方法是原子操作
        //保证一个 key 只创建一个 lock
        RedisLockThread lockThread = keyLockMap.get(key);
        if(lockThread == null) {
            lockThread = new RedisLockThread(fair);
            lockThread.saveThreadOfLock(Thread.currentThread());//保存 lock 与 线程的关系
            keyLockMap.put(key, lockThread);//保存 key 与  lock 的关系
        }
        lockThread.saveThreadOfLock(Thread.currentThread());//保存 lock 与 线程的关系
        globalLock.unlock();
        return lockThread;
    }

    private boolean isBlank(CharSequence cs) {
        int strLen;
        if (cs == null || (strLen = cs.length()) == 0)
            return true;
        for (int i = 0; i < strLen; i++)
            if (!Character.isWhitespace(cs.charAt(i)))
                return false;

        return true;
    }

    /**
     * 调试使用
     * @return
     */
    public String getContentOfKeyLockMap(String key){
        StringBuilder str = new StringBuilder();
        str.append("keyLock count:").append(keyLockMap.size());

        RedisLockThread lockThread = keyLockMap.get(key);
        if(lockThread != null) {
            str.append(",keyLockInfo:").append(lockThread.toString());
        } else {
            str.append(",keyLockInfo:").append("no lock");
        }

        return str.toString();
    }

    /**
     * redis的一个key,对应一个 RedisLockThread 实例对象
     */
    class RedisLockThread {

        private ReentrantLock lock;

        private volatile Map<Thread,Thread>  exclusiveOwnerThread = new HashMap<Thread,Thread>();

        public RedisLockThread(boolean fair) {
            this.lock = new ReentrantLock(fair);
        }

        protected ReentrantLock getLock() {
            return lock;
        }

        protected void saveThreadOfLock(Thread thread) {
            exclusiveOwnerThread.put(thread, thread);
        }

        protected Thread getThreadOfLock(Thread thread) {
            return exclusiveOwnerThread.get(thread);
        }

        protected void removeThreadOfLock(Thread thread) {
            exclusiveOwnerThread.remove(thread);
        }

        protected int getThreadsOfLock() {
            return exclusiveOwnerThread.size();
        }

        @Override
        public String toString() {
            StringBuffer str = new StringBuffer();
            str.append(" thread count of keyLock=").append(exclusiveOwnerThread.size());
            str.append(",keyLock=").append(lock.toString()).append(" ");
            return str.toString();
        }
    }
}

问与答

问:使用redis的什么指令实现的,分布式锁。
答:setnx

问:集群中有两台机器A、B,每台机器分别有10个线程需要获取redis lock。如果B机器的某个线程获取了redis lock,并且一直没有释放。这时 A 机器的10个线程会都挂起吗?
答:如果A机器的10个线程都挂起的话,那么将无法唤醒10个线程。所以 A 机器的10线程其中有9个会挂起,另外的一个线程会不断的尝试获取 redis lock,当获取blockingAfterLockNum参数配置次数后,仍然没有获取redis lock的时候,则挂起 parkThreadMilliscond 参数配置的时间。挂起结束后继续尝试获取 redis lock。

r2m-client jar包 R2M客户端 应用需要的jar包 网银开发 连接redis数据库 立即下载

相关推荐

R2M缓存系统.pdf

很好的学习资料。。值得学习的,介绍的很详细

Redis Cluster集群配置

Redis Cluster 提供了一种运行 Redis 安装的方法,其中数据 在多个 Redis 节点之间自动分片。

1856

详解ASP.Net Core 中如何借助CSRedis实现一个安全高效的分布式锁

主要介绍了ASP.Net Core 中如何借助CSRedis实现一个安全高效的分布式锁,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

新手Redis的分布式锁解析

在使用分布式锁进行互斥资源访问时候,我们很多方案是采用redis的实现。 固然,redis的单节点锁在极端情况也是有问题的,假设你的业务允许偶尔的失效,使用单节点的redis锁方案就足够了,简单而且效率高。 redis锁失效的情况: 客户端1从master节点获取了锁 master宕机了,存储锁的key还没来得及同步到slave节点上 slave升级为master 客户端2从新的master上获取到同一个资源的锁 于是,客户端1和客户端2同事持有了同一个资源的锁,锁的安全性被打破。 如果我们不考虑这种极

pipujopijhpo的博客 314

小白学电路之cadance搭建buffer电路

Buffer(缓冲器)是一种放大器或驱动电路,主要用于隔离输入和输出,以防止负载对前级电路造成干扰或影响。本文作者在电路方面是小白水平,目前正在学习,有不足之处欢迎指正。3.创建新的cellview,对此buffer进行仿真验证。2.创建buffer的symbol。电路中的V2的详细参数。

weixin_58051657的博客 1992

CMMI AIM 人工智能成熟度框架:31个过程域的157项AI实践集成

CMMI AIM人工智能成熟度框架为企业提供了系统化管理AI项目全生命周期的解决方案,包含31个过程域的157项AI实践。该框架通过四个演进阶段(混沌与风险、结构与凝聚、验证与信任、价值与增长),帮助组织建立可持续的AI能力成长路径,降低项目失败率并提升商业价值。

weixin_42613501的博客 355

R2M在项目中的使用

本次主要是记录R2M在项目中的使用以及降级处理 public static void setOrderRid(String cacheKey,R2MCacheService redisUtils,OrderConfimVO confirmVo,HttpServletResponse response,int cacheTime) { try { redisUtils.setex(cach

钟渊博客 4074

Maltab GUI课程设计——网络爬虫程序(基金连涨连跌提醒)

Maltab GUI课程设计——网络爬虫程序(基金连涨连跌提醒)

果果爱腰果的博客 851

在 .NET Core中如何使用 Redis 创建分布式锁

锁的键: 使用订单 ID 作为锁的键(如 PaymentLock:202501061410455506968463210),确保同一订单的支付请求串行化。return Conflict(new { Message = "正在处理此订单的另一个付款请求..." });ReleaseLockAsync: 使用 Lua 脚本确保只有锁的持有者才能释放锁,避免误删其他请求的锁。如果锁的粒度过大(如全局锁),可能导致性能问题;锁的过期时间: 设置合理的过期时间(如 10 秒),防止锁被长时间占用。

weixin_55010563的博客 1141

浅谈专项测试之弱网络测试

浅谈专项测试之弱网络测试 一.弱网络测试背景 移动端产品的使用并非完全都是在流畅的wifi环境,大部分用户主要使用4G,3G,2G等网络,另外因为移动端产品使用的场景多变,如进公交,上地铁,坐电梯,使得弱网测试显得尤为重要。考虑到各种场景的客户端展示及容错,提升产品的印象和用户体验,提高产品的健壮性,弱网测试必不可少。 二.弱网络测试建议 网下需要进行功能点测试,无网络测试,网络切换测试等,测试过程除了关注功能点的实现,还应关注用户体验等各个方面 三.弱网络测试通用功能点总结 四.弱网络测试用例实例

ITstudy001的博客 1011

win2012 r2 + IIS8.5 伪静态设置脚本映射

win2012 r2 + IIS8.5 伪静态设置脚本映射,网站用的.net fromwork 2.0 ,应用程序池设置了32位支持

xueking87的专栏 3241

使用Redis创建分布式锁

点击上方蓝色字关注我们~在本文中,我们将讨论如何在.NET Core中使用Redis创建分布式锁。当我们构建分布式系统时,我们将面临多个进程一起处理共享资源,由于其中只有...

dotNET跨平台 574

告别手动维护!教你用SAP BAPI批量更新生产订单BOM组件(CO02工单)

本文详细介绍了如何利用SAP BAPI实现生产订单BOM组件的批量更新,解决传统手工操作(如CO02工单)效率低下的问题。通过核心函数解析和批量处理框架设计,帮助用户大幅提升工作效率,降低错误率,适用于物料主数据变更、季节性配方调整等场景。

weixin_30844577的博客 561

【Redis从入门到进阶】第 7 讲:基于 Redis 实现分布式锁

【Redis从入门到进阶】第 7 讲:基于 Redis 实现分布式锁

执梗的博客 4309

公文流转系统

公文录入区 | QLineEdit(文号/标题)、QComboBox(公文类型/紧急程度)、QTextEdit(正文)、QListWidget(附件列表)、QPushButton(上传附件/保存草稿/提交审批) |// 按时间范围获取。QStringList userNames = {"张三", "李四", "王五", "赵六", "钱七", "孙八", "周九", "吴十", "郑十一", "王十二"};

寒寒豆豆软件公司的博客 551

【网络协议】【TSN】精讲TSN工作原理!图解超赞超详细!!!

TSN有一个服务等级(class of service,CoS)的概念。对TSN网络而言,不同优先级的服务对应图3中的PCP码。3位PCP码定义了0(最低)~7(最高)这8个优先级,传输类型分别对应基础、最大努力、卓越努力、严苛应用、延时和抖动小于100 ms的视频、延时和抖动小于10 ms的音频、内部网络控制、网络控制。其会对网络场景进行不同的匹配,是后续调度、配置设计中会考虑到的数据流调度因素。

风云说通信 2633

使用Redis如何实现分布式锁?(超卖)

在多线程环境下,为了保证数据的线程安全,锁保证同一时刻,只有一个可以访问和更新共享数据。在单机系统我们可以使用锁、锁保证线程安全。锁是 Java 提供的一种内置锁,在单个 JVM 进程中提供线程之间的锁定机制,控制多线程并发。只适用于单机环境下的并发控制。想要在多个节点中提供锁定,在分布式系统并发控制共享资源,确保同一时刻只有一个访问可以调用,避免多个调用者竞争调用和数据不一致问题,保证数据的一致性,就需要分布式锁。:控制分布式系统不同进程访问共享资源的一种锁的机制。

2301_78703470的博客 906

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

分布式锁的作用及实现(Redis)

分布式锁:当多个进程不在同一个系统中,用分布式锁控制多个进程对资源的访问。 一、分布式锁的使用场景 如果是单机情况下(单JVM),线程之间共享内存,只要使用线程锁就可以解决并发问题。 如果是分布式情况下(多JVM),线程A和线程B很可能不是在同一JVM中,这样线程锁就无法起到作用了,这时候就要用到分布式锁来解决。 二、分布式锁的实现(Redis) 分布式锁实现的关键是在分布式的应用服务器...

a2210294的博客 4437

精雕软件(JDpaint) 5.5 绿色版

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

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

Java实现分布式锁(基于Redis)

Java实现分布式锁(基于Redis)

安 1325

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

golang使用redis分布式锁 [2020年更新]

我还记得上一篇文章golang使用redis分布式锁还是18年写的,但是对于现在来说已经不适用,所以今天我更新了go使用redis分布式锁,对想用redis分布式锁的人一个简单的讲解,并快速用于实践。 首先,最需要的还是redis的go客户端github.com/gomodule/redigo 已经不是之前的那个路径了。 然后下载github.com/go-redsync/redsync这个库,他就是实现分布式锁的核心。 当然你也可以自己实现,但是我今天只说这个库的用法。 // A Mute...

万彬学习的博客 4528

Java使用Redis来实现分布式锁

在单节点服务中,我们可以使用来保证同一时间内只允许一个线程执行限定的代码块。但是如果我们是多节点服务呢,因为是针对服务内部的,其他服务是无法受到他的干预的。那么如何保证多个节点在同一时间内只允许一个节点中的一个线程去访问这个代码块呢?使用分布式锁!!!本文使用Redisson来操作Redis并实现分布式锁。

假女吖的博客 717

redis分布式锁

使用Redis实现分布式锁是一种常见的做法,因为Redis提供了原子操作,可以确保锁的正确性和高效性。下面是一个使用Spring Boot和Redis实现分布式锁的完整示例。

qq_37398465的博客 530
上一篇: java自定义线程阻塞
下一篇: 自定义 Java ClassLoader
三易的博客
博客等级 码龄15年 42粉丝 89原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值