Redis 篇-深入了解分布式锁 Redisson 原理(可重入原理、可重试原理、主从一致性原理、解决超时锁失效)

Redisson分布式锁的可重入、重试、续约机制原理 Redisson分布式锁的可重入、重试和看门狗机制的原理 阅读详情
AI摘要

本文介绍了基于Redis实现的分布式锁存在的不可重入、不可重试、超时释放和主从一致性等问题,详细阐述了Redisson的功能、具体使用方法,深入分析了Redisson可重入锁、锁重试、WatchDog机制和MultiLock原理,展示了Redisson如何解决上述问题。

🔥博客主页: 【小扳_-优快云博客】
❤感谢大家点赞👍收藏⭐评论✍

本章目录

        1.0 基于 Redis 实现的分布式锁存在的问题

        2.0 Redisson 功能概述

        3.0 Redisson 具体使用

        4.0 Redisson 可重入锁原理

        5.0 Redisson 锁重试原理

        6.0 Redisson WatchDog 机制

        6.1 Redisson 是如何解决超时释放问题的呢?

        7.0 Redisson MultiLock 原理

        7.1 Redisson 分布式锁是如何解决主从一致性问题的呢?


        1.0 基于 Redis 实现的分布式锁存在的问题

        首先,在之前基于 setnx 实现的分布式锁存在以下问题:

        1)不可重入:同一个线程无法多次获取同一把锁。

        2)不可重试:获取锁只尝试一次就返回 false ,没有重试机制。

        当然这个机制是可以自己在判断完有无获取锁之后,再来根据业务的需求进行手动添加代码。比如说,当业务需求是:需要重复尝试获取锁。则可以在判断获取锁失败之后,等待一段时间,再去获取锁即可。

        3)超时释放:锁超时释放虽然可以避免死锁,但如果是业务执行耗时较长,也会导致锁释放,存在安全隐患。

        比如说,当业务阻塞时间较久,锁到了超时时间则会自动释放,那么其他线程就会有可能获取锁成功,这就出现了多个线程获取锁成功,从而导致线程安全问题。

        4)主从一致性:如果 Redis 提供了主从集群,主从同步延迟,当主机宕机时,如果未来得及同步到其他机器上,则就会出现多线程获取锁成功情况,从而导致线程安全问题。

        那么 Java 实现了解决以上问题的 Redisson 分布式服务类。

        2.0 Redisson 功能概述

        Redisson 是一个在 Redis 的基础上实现的 Java 驻内存数据网络。它不仅提供了一系列的分布式的 Java 常用对象,还提供了许多分布式服务,其中包含了各种分布式锁的实现。

        Redisson 解决了不可重入问题、不可重试问题、超时释放问题、主从一致性问题。

        比如说,分布式锁的可重入锁、公平锁、联锁、红锁等等。

        3.0 Redisson 具体使用

        1)引入依赖

        <dependency>
            <groupId>org.redisson</groupId>
            <artifactId>redisson</artifactId>
            <version>3.13.6</version>
        </dependency>

        2)配置 RedissonClient类

import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class RedissonConfig {

    @Bean
    public RedissonClient client(){
        //配置类
        Config config = new Config();
        //添加redis地址,这里添加了单点的地址,也可以使用config.useClusterServers()添加集群地址
        config.useSingleServer().setAddress("redis://8.152.162.159:6379").setPassword("****");
        //创建客户端
        return Redisson.create(config);
    }
}

        3)使用 RedissonClient类

    @Autowired
    RedissonClient redissonClient;

    @Test
    void contextLoads() throws InterruptedException {
        //先获取锁对象,根据业务来锁定资源
        RLock lock = redissonClient.getLock("lock");

        //尝试获取锁
        //tryLock() 进行了重写,有无参、只有两个参数、有三个参数
        boolean b = lock.tryLock(1, TimeUnit.SECONDS);
        
        if (b){
            System.out.println("成功获取锁!");
        }else {
            System.out.println("获取锁失败!");
        }
        
    }

        先注入 RedissonClient 对象,根据 getLock("锁") 方法获取 RLock lock 锁对象,根据业务需要对资源进行锁定。  

        调用 lock 对象中的 tryLock() 方法来尝试获取锁,该方法进行了重写:

        1)boolean tryLock():当获取锁失败时,默认不等待,就是不重试获取锁,默认锁的超时时间为 30 秒。

        2)boolean tryLock(long time, TimeUnit unit):在 time 时间内会进行重试尝试获取锁,unit 为时间单位。默认锁的超时时间为 30 秒。

        3)boolean tryLock(long waitTime, long leaseTime, TimeUnit unit):在获取锁失败时,在 waitTime 时间内进行重试尝试获取锁,锁的超时时间为 leaseTime 秒,unit 为时间单位。

        最后,调用 lock 对象中的方法 unlock() 来释放锁。

具体代码:

    @Autowired
    RedissonClient redissonClient;

    @Test
    void contextLoads() throws InterruptedException {
        //先获取锁对象,根据业务来锁定资源
        RLock lock = redissonClient.getLock("lock");

        //尝试获取锁
        //tryLock() 进行了重写,有无参、只有两个参数、有三个参数
        boolean b = lock.tryLock(1, TimeUnit.SECONDS);

        if (!b){
            System.out.println("获取锁失败!");
        }

        try {
            System.out.println("获取锁成功!");
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            //释放锁
            lock.unlock();
        }

    }

        4.0 Redisson 可重入锁原理

        在之前的基于 setnx 实现的分布式锁是不支持可重入锁,举个例子:线程一来获取锁,使用 setnx 来设置,当设置成功,则获取锁成功了,线程一在获取锁成功之后,再想来获取相同的锁时,则再次执行 setnx 命令,那一定是不可能成功获取,因为 setxn 已经存在了,这就是基于 setnx 来实现分布式锁不可重入锁的核心原因。

        而对于 Redisson 可以实现可重入锁,这是如何实现的呢?

        其核心原因是基于 Redis 中的哈希结构实现的分布式锁,利用 key 来锁定资源,对于 field 来标识唯一成功获取锁的对象,而对于 value 来累计同一个线程成功获取相同的锁的次数。

        具体实现思路:

        1)尝试获取锁:

        先判断缓存中是否存在 key 字段,如果存在,则说明锁已经被成功获取,这时候需要继续判断成功获取锁的对象是否为当前线程,如果根据 key field 来判断是当前线程,则 value += 1 且还需要重置锁的超时时间;如果根据 key field 判断不是当前线程,则直接返回 null。如果缓存中不存在 key 字段,则说明锁还没有被其他线程获取,则获取锁成功。

        2)释放锁:

        当业务完成之后,在释放锁之前,先判断获取锁的对象是不是当前线程,如果不是当前线程,则说明可能由于超时,锁已经被自动释放了,这时候直接返回 null;如果是当前线程,则进行 value -= 1 ,最后再来判断 value 是否大于 0 ,当大于 0 时,则不能直接释放锁,需要重置锁的超时时间;当 value = 0 时,则可以真正的释放锁。

如图:

 

        又因为使用 Java 实现不能保证原子性,所以需要借助 Lua 脚本实现多条 Redis 命令来保证原则性。

尝试获取锁的 Lua 脚本:

释放锁的 Lua 脚本:

        5.0 Redisson 锁重试原理

        在之前基于 setnx 实现的分布式锁,获取锁只尝试一次就返回 false ,没有重试机制。

        而 Redisson 是如何实现锁重试的呢?

实现锁重试

        追踪源代码:

得到该类:

        首先,将等待时间转换为毫秒,接着获取当前时间和获取当前线程 ID ,再接着第一个尝试去获取锁,将参数 waitTime 最大等待时间,leaseTime 锁的超时时间,unit 时间单位,threadId 当前线程 ID 传进去 tryAcquire 方法中。

        紧接着来查看 tryAcquire 方法:

         再查看调用的 tryAcquireAsync 方法:

        当指定了 leaseTime 锁的超时时间,则会调用 tryLockInnerAsync 方法;当没有指定 leaseTime 锁的超时时间,则会调用 getLockWatchdogTimeout 方法,默认超时时间为 30 秒。

        接着查看 tryLockInnerAsync 方法:

         可以看到,这就是尝试获取是的 Lua 脚本执行多条 Redis 命令。

        细心可以发现,如果正常获取锁,则返回 null ;如果获取锁失败,则返回当前锁的 TTL ,锁的剩余时间。

        因此最后将当前锁的 TTL 返回赋值给 Long ttl 变量。

        再接着往下:

        当 ttl == null ,则说明当前线程成功获取锁,因此就不需要接着往下再次尝试去获取锁了。相反,当 ttl != null ,则需要接着往下走,重新尝试去获取锁。

        判断 time 等于当前时间减去在第一次获取锁之前的时间,time 也就是最大的等待时间还剩多少。判断 time 是否小于 0 ,若小于 0 则已经到了最大等待时间了,所以不需要再继续等下去了,直接返回 false 即可。

        若 time 还是大于 0 ,则接着往下走:

        调用 subscribe 方法,该方法可以理解成订阅锁,一旦锁被释放之后,该方法就会收到通知,然后再去尝试获取锁。

回顾在释放锁的时候,使用 Redis 命令中的 redis.call('publish', KEYS[2], ARGV[1]) 来发布消息,通知锁已经被释放,一旦锁被释放,那么就可以成功订阅。

        因此,在订阅锁的过程中,并不是一直死等下去,而是在 time 剩余最大等待时间之内,如果可以订阅锁成功,才会去尝试获取锁。如果在 time 时间内,订阅锁失败,则会取消订阅,再返回 false 。

        接着往下走,当在 time 时间内订阅锁成功,会更新 time 时间,也就是更新最大的等待时间,判断 time 小于 0 ,则返回 false ,如果 time 还是大于 0 ,则到了真正尝试第二次获取锁,调用 tryAcquire(waitTime, leaseTime, unit, threadId) 方法,将返回值再次赋值给变量 ttl ,判断 ttl == null ,则说明成功获取锁了,直接返回 true ;判断 ttl != null ,则第二次获取锁还是失败,由需要更新 time 了,因为在调用尝试获取锁的过程中,消耗时间还是挺大的,同理,判断更新完之后的 time 是否大于 0,如果 time 小于 0,则超过了剩余最大锁的超时时间,返回 false ;

        如果判断 time 仍旧大于 0 :

        那么先判断锁的过期时间 ttl 与 剩余时间 time ,如果 ttl < time ,则类似订阅方法一样的思路,选择等待 ttl 锁的过期时间,当 ttl 过期之后,就会订阅该锁;如果 time < ttl ,则 ttl 还没有释放,就不需要等 ttl 了,等到 time 结束还没有订阅到锁,则 time 也就小于 0 了,如果在 time 时间内获取到锁,再次尝试去获取锁,同样的,当在 ttl 时间内,成功订阅了,而且 time > 0 ,则会第三次去尝试获取锁。之后的步骤都是如此,这里使用了 do whlie 循环,判断循环成立为 time > 0,当 time < 0 ,则会退出循环。

        总结,在解决可重试锁过程中,并不是循环不断的调用 tryAcquire(waitTime, leaseTime, unit, threadId) 方法来获取锁,这样容易造成 CPU 的浪费,而是通过等待锁释放,再去获取锁的方式来实现的可重试锁,利用信号量(Semaphore)和发布/订阅(PubSub)模式实现等待、唤醒、获取锁失败的重试机制。

        6.0 Redisson WatchDog 机制

        在之前基于 setnx 实现的分布式锁,锁超时释放虽然可以避免死锁,但是如果是业务执行耗时较长,也会导致锁释放,存在安全隐患。

        6.1 Redisson 是如何解决超时释放问题的呢?

        解决超时释放的核心是:当 leaseTime == -1 时,为了保证当前业务执行完毕才能释放锁,而不是业务还没有执行完毕,锁就被自动释放了。

追踪源代码:

        当 leaseTime == -1 时,默认锁的最大超时时间为 30 秒,会执行以下代码。

        接着点进去:

        WatchDog 会在锁的过期时间到期之前,定期向 Redis 发送续约请求,更新锁的过期时间。这通常是通过设置一个较短的过期时间和一个续约间隔来实现的。

        如果持有锁的线程正常释放锁,WatchDog 会停止续约操作。如果持有锁的线程崩溃或失去响应,WatchDog 会在锁的过期时间到达后自动释放锁。

        简单概述一下 WatchDog 机制:在获取锁成功之后,就会调用 scheduleExpirationRenewal(threadId) 方法开启自动续约,具体是由在 map 中添加业务名称和任务定时器,这个定时器会在一定时间内执行,比如说 10 秒就会自动开启任务,而该定时器中的任务就是不断的重置锁的最大超时时间,使用递归,不断的调用重置锁的时间,这就保证了锁是永久被当前线程持有。 

        这样就可以保证执行业务之后,才会释放锁。释放锁之后,会取消定时任务。

        7.0 Redisson MultiLock 原理

        7.1 Redisson 分布式锁是如何解决主从一致性问题的呢?

        先搞清楚什么是主从一致性问题,在集群的 Redis 中会区分出主力机和一般机器,在写 Redis 命令会放到主力机中运行,而主力机和一般机器需要保证数据都是一样的,也就是主从同步数据,在主力机中执行写命令时,突然发生宕机,未来得及将数据同步到其他一般机器中,而且当主力机宕机之后,会选出一台一般机器充当主力机,这时候的主力机没有同步之前的数据,那么其他线程再来写命名的时候就会出现问题了,这出现了主从不一致性。

        那么 Redisson 是如何来解决该问题呢?

        在多主架构中,每台主机都可以接收写请求,这样即使某一台主机宕机,其他主机仍然可以继续处理写请求。

        当某一台主机宕机后,如果在它恢复之前有新的写操作发生,可能会导致数据不一致。通过比较不同主机的数据状态,可以很容易地发现这些不一致的问题。

        当宕机的主机恢复后,可以通过与其他主机的数据进行比较,找出差异并进行数据同步,确保所有主机的数据一致。

        简单来说,设置多台主力机,每一次写命令都是一式多份,当某一台主力机出现宕机了,主从未来得及同步时,再写命令,同样一式多份,这样充当主力机出现了跟其他主力机不同的结果时,就很容易的发现问题了。

        通过设置多台主力机并进行写操作的多份复制,可以有效提高系统的可靠性,并在出现问题时快速发现和解决数据不一致的问题。

具体使用:

Redisson看门狗机制你了解多少 这里也是对之前redisson锁的知识遗漏点的一个学习,结合实际的业务开发使用的案例,来分析锁的底层原理,从而来避免我在使用过程中遇到问题,能有更加清晰的解决思路,理解不对的地方也欢迎大家在评论区提出。 阅读详情

相关推荐

【Redis】【Redis分布式锁】Redis锁的超时时间问题

针对我们不同的实现方案,对应的redis锁有的一些问题,我们进行了梳理,希望给需要的同学能够带来点启发,对应也列举了几个解决方案。一般在简单的场景里,我会直接选择第一种解决方案:正在上传…重新上传取消。

BASK2311的博客 994

【Redis进阶】一文搞懂Redisson的看门狗机制底层实现

看门狗机制是Redission提供的一种自动延期机制,这个机制使得Redission提供的分布式锁是可以自动续期的。看门狗机制提供的默认超时时间是30*1000毫秒,也就是30秒如果一个线程获取锁后,运行程序到释放锁所花费的时间大于锁自动释放时间(也就是看门狗机制提供的超时时间30s),那么Redission会自动给redis中的目标锁延长超时时间。在Redission中想要启动看门狗机制,那么我们就不用获取锁的时候自己定义leaseTime(锁自动释放时间)。如果自己定义了锁自动释放时间的话,无论是通过。

沉迷写代码的程序猿的博客 3万+

Redis实现分布式锁

1. 为什么需要分布式锁?我们都知道,以上情况,,此时就2. 单机锁 & 分布式锁的定义:3. 分布式锁应该具备哪些条件?4. 分布式锁都有哪些主流的实现方案?分布式锁的核心是实现多线程之间互斥,而满足这一点的方式有很多,常见的有三种:补充:Zookeeper实现分布式锁的思路实现分布式锁的核心思路5. 如何用 Redis 实现分布式锁的?Redis本身可以被多个客户端访问,正好就是一个共享存储系统,可以用来保存分布式锁,而且Redis的读写性能高,可以应对高并发的锁操作场景。

weixin_53622554的博客 3284

分布式锁-Redission可重入锁原理

Redisson可重入锁是一种分布式锁,它基于Redis实现。可重入指的是同一个线程在持有锁的情况下,可以多次获取该锁而不会造成死锁。-----它可以在分布式系统中用于实现互斥锁。这种锁可以允许多个线程同时获取锁,但在任何给定时间只有一个线程可以执行受保护的代码块。-----Redission锁提供了一种简单的方法来保证在分布式系统中的互斥性,同时支持可重入性。这意味着一个线程可以在获取锁之后再次获取同一个锁,而不需要等待锁释放。

weixin_45618869的博客 2879

大数据实时+离线项目架构----智慧物流大数据平台(超流行框架!)

智慧物流大数据平台 文章目录智慧物流大数据平台一、项目背景二、逻辑架构三、解决方案技术亮点:数据流转四、项目的技术选型4.1流式处理平台4.2 分布式计算平台4.3 海量数据存储框架软件版本总结 一、项目背景 本项目基于一家大型物流公司研发的智慧物流大数据平台。该物流公司是国内综合性快递、物流服务商,并在全国各地都有覆盖的网点。经过多年的积累、经营以及布局,拥有大规模的客户群,日订单达上千万。如此规模的业务数据量,传统的数据处理技术已经不能满足企业的经营分析需求。公司需要基于大数据技术构建数据中心,从而挖

weixin_48143996的博客 6430

TEC 高精度控温算法:实现精准升降温与恒温控制

本文深入解析了TEC高精度控温算法的核心原理与工程实践。针对TEC非线性、时变的特性,算法通过智能状态机实现精准升降温与恒温控制,并详细阐述了参数整定、硬件协同及调试优化的系统性方法,为半导体激光器、PCR仪等高精度温控应用提供了一套完整的解决方案。

weixin_29212867的博客 1012

Redisson分布式锁核心机制解析:锁重试与WatchDog看门狗实战

在分布式系统设计中,保证多节点对共享资源的互斥访问是刚需,分布式锁因此成为高并发架构中的基础组件。Redis凭借高性能和易用性常被用来实现锁,但单纯依赖SETNX容易遇到锁提前过期、误删、不可重入等隐患。Redisson作为Java生态成熟的分布式锁方案,通过信号量与发布订阅实现高效的锁重试,并利用WatchDog看门狗机制自动续期,避免业务未完成而锁失效。合理配置tryLock的等待时间、理解显式leaseTime与看门狗之间的关系,能显著提升系统的稳定性与并发安全性。结合线上事故与源码分析,可深入理解R

weixin_32075843的博客 296

DDR ECC错误注入与寄存器配置实战指南

本文详细介绍了DDR ECC错误注入的核心价值与实战操作指南,包括通过FI_Dx和FI_ECC寄存器注入数据与ECC错误的方法。文章提供了环境准备、寄存器配置、错误检测及系统可靠性测试策略,帮助开发者验证内存系统的纠错能力和可靠性,提升硬件开发的稳定性与效率。

nnn11的博客 1104

黑马点评面试精讲:Redis缓存、分布式锁与秒杀架构全解析

高并发场景下,缓存与分布式锁是保障系统稳定性的核心技术。Redis作为高性能存储组件,常被用于解决缓存穿透、击穿与雪崩问题,并通过分布式锁机制确保秒杀场景下的“一人一单”。同时,雪花算法保证了分布式环境下的全局唯一ID生成,RabbitMQ的引入则实现了异步下单与削峰填谷。这些技术点共同构成了电商系统的高并发解决方案,也是后端面试中的高频考点。本文以黑马点评项目为依托,深入剖析这些技术背后的底层原理、选型依据及常见坑点,帮助开发者从“会用”进阶到“懂原理”,在面试中展现真正的工程实践能力。

weixin_33831673的博客 432

Apple 网页 SRP 登录系列文章(二):网页参数提取与会话初始化

本文深入解析了Apple网页SRP登录的第一个关键环节。文章首先指出Apple登录页面采用多层安全架构,包括跨域跳转机制和动态参数生成。重点介绍了四种关键参数(ServiceKey、SCNT、FrameId、ServiceNum)的提取技术,通过正则表达式和JSON路径解析从HTML脚本和HTTP头中获取。最后详细说明了会话初始化流程,包括访问初始页面和构建认证URL。这些技术细节揭示了Apple如何通过复杂机制确保登录过程的安全性。

Sayid_Des的专栏 1129

【LPDDR4 - 学习二】LPDDR4 介绍 ——LPDDR4 芯片引脚说明解析

本文系统解析了LPDDR4内存芯片的引脚定义与特性,重点介绍了272球POPFBGA封装的双通道架构。内容涵盖电源管理(三级供电架构与上电时序)、控制信号(差分时钟与复用命令总线)、数据接口(16位双向数据总线与选通信号)以及校准复位等核心模块。通过表格详细列明了各引脚电压范围、功能定义及工程注意事项,并附有典型封装球位分布图。全文基于JEDEC标准,为移动设备内存设计提供全面的硬件参考,特别强调电源时序控制、信号完整性及抗干扰设计等关键点。

zap15622077817的博客 2637

分布式锁的底层原理与生产实战:Redis、ZooKeeper、数据库对比

在微服务架构下,多个实例共享同一资源时,传统的单机锁因锁状态隔离而失效,需要一种跨进程的互斥机制,这就是分布式锁。它的核心原理是通过外部存储组件(如Redis的SETNX命令)注册唯一标识,并配合过期时间与续期机制防止死锁,从而在多节点间实现临界区保护。分布式锁的价值在于解决秒杀超卖、库存扣减、定时任务重复执行等典型并发问题,同时要警惕锁过期、误删他人锁、主从切换等陷阱。围绕Redis、ZooKeeper与数据库三种主流实现,系统解析选型思路、生产落地与故障排查:Redisson的Watchdog自动续期怎

weixin_34072296的博客 321

Python 静态导入与动态导入

python中模块的静态导入 与 动态导入(运行时指定模块),以及具体对应示例。

慢也好,步子小也好,往前走就好~ 717

1.4 java面试题 ,Redis 必问三大块,哨兵,集群

从 Java 面试之王的角度,Redis 必问三大块:数据结构与使用场景、缓存三大问题及解决方案、分布式锁与高可用。我会把这些拆成能直接背的干货,配上代码和血泪教训。面试官最爱问“你用 Redis 做过什么”,你必须把数据结构和业务场景对应起来。血泪教训:别用 HGETALL 扫描大 Hash,拆成小 Hash 或改用 String + JSON 分页。现象:恶意请求 直接打到 DB。 方案: 缓存空值:null 也缓存,过期时间设短(如 60s)。 2. 缓存击穿(热点 key 过期) 现象:某热门

你是人间四月天 237

基于深度学习的心律失常的自动分类

基于深度学习的心律失常的自动分类 作者:禅与计算机程序设计艺术 1. 背景介绍 1.1 心律失常的危害与检测的重要性 心律失常是一种常见的心血管疾病,严重威胁着人们的健康和生命。据统计,全球每年有数百万人因心律失

AI架构师小马 1139

SY6982C 7.4V锂电池1A充电模块原理图设计,已量产

在手持设备、便携工具与小型无人机等场景中,7.4V(2S)锂聚合物电池的应用愈发广泛。这类电池对充电系统的安全性、效率与兼容性提出了明确要求:需支持 USB 5V 输入、1A 安全充电,同时具备多重保护机制。本文将结合一款基于 SY6982C 的充电原理图,深入解析其电路设计与技术亮点。

不脱发的程序猿 360

语义缓存穿透与击穿防线:基于分布式锁的多实例向量重建保护

做 AI 落地架构设计的人,迟早要面临 Token 账单的现实毒打。去年年中我们上线了智能知识库与导购客服系统,起初为了省钱并把端到端 P99 响应时间从 1.8 秒压到 200 毫秒以内,架构团队在应用层引入了语义缓存(Semantic Cache)。原理大家都不陌生:用户输入一段话,先转成向量,去向量数据库(如 Milvus 或 Redis Vector Search)里算余弦相似度。只要距离大于阈值(比如 0.92),直接复用上一次大模型的推理答案,跳过后续高昂的 LLM 推理链路。

alex_goden的博客 4133

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

Redis 知识体系(文档型 NoSQL)

本文深入解析Redis八大基础数据结构及其底层编码实现,涵盖String、List、Set、ZSet、Hash、Geo、Bitmap、HyperLogLog和Stream等核心结构。通过源码级分析,揭示了SDS、Ziplist、Dict等底层组件的设计原理,并详细探讨了Redis的高性能IO模型、持久化机制(RDB/AOF/混合模式)、内存管理策略及高可用架构(主从/哨兵/Cluster)。 重点剖析了Redis在工程实践中的典型问题与优化方案,包括缓存穿透/击穿/雪崩的解决方案、分布式锁的完整实现(含Re

专注 Java 后端开发,分享基础语法、JVM、并发、Spring 全家桶、微服务、分布式、性能优化等实战干货。坚持输出高质量技术笔记,用简单语言讲清复杂原理,助力每一位 Java 开发者稳步进阶。 794

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

【高频面试题】分布式锁在项目中的应用

方案并发现象是否阻塞超卖多线程抢 Redis 锁,抢到才执行等待期间自旋不会超卖MySQL 悲观锁 for update线程卡在 select for update 排队等待行锁✅阻塞不会超卖MySQL 乐观锁 version全部同时读取,更新阶段判断版本冲突❌不阻塞不会超卖,但是大量失败重试。

后端胖头鱼的博客 203

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

02-06-X-锁机制全景详解

本文按四大模块(Java 单机锁 → MySQL 数据库锁 → 分布式锁 → 消息队列锁)逐一展开:每类锁是什么、什么场景出现、会出什么问题、如何预防、出了问题如何解决。

hhkrye的博客 516

大厂后台开发面试真题解析:HashMap、Redis与volatile深度实战

Java后台开发中,HashMap的并发扩容机制、Redis在高并发限流与分布式锁中的工程选型、volatile关键字对JVM内存模型的影响,是支撑云服务SLA稳定性的三大底层基石。理解其原理不仅关乎面试通过,更决定生产环境的健壮性——比如HashMap扩容死链可致CPU 100%,Redis序列化方式错误引发跨语言兼容断层,volatile缺失导致DCL单例NPE。这些知识点广泛应用于API网关、用户画像、订单系统等典型场景,也是腾讯云智等一线云厂商校招技术筛选的核心维度。

weixin_34218579的博客 373

Java高并发系统 + 安全监控 完整知识体系

本文系统梳理了Java高并发开发的全方位知识体系,涵盖单机并发基础、分布式架构、系统安全、监控体系和故障治理等核心模块。主要内容包括: 单机并发基础 CPU多级缓存与内存模型 JMM内存模型与happens-before原则 锁机制与CAS原子操作 并发容器与线程池原理 JVM调优与性能优化 分布式高并发架构 分布式锁与一致性算法 缓存体系与典型问题解决方案 消息队列的削峰填谷 负载均衡与分库分表 微服务通信与流量控制 生产级解决方案 高并发业务安全防护 全链路监控体系搭建 典型故障排查与治理 应急预案与性

专注 Java 后端开发,分享基础语法、JVM、并发、Spring 全家桶、微服务、分布式、性能优化等实战干货。坚持输出高质量技术笔记,用简单语言讲清复杂原理,助力每一位 Java 开发者稳步进阶。 575

redission的看门狗机制及应用

Redisson提供的分布式锁是支持锁自动续期的,也就是说,如果线程仍旧没有执行完,那么redisson会自动给redis中的目标key延长超时时间,这在Redisson中称之为 Watch Dog 机制。默认情况下,看门狗的检查锁的超时时间是30秒钟,也可以通过修改来另行指定。// 拿锁失败时会不停的重试// 具有Watch Dog 自动延期机制 默认续30s 每隔30/3=10 秒续到30s// 尝试拿锁10s后,没有Watch Dog。

a3337779的博客 9407

聊聊分布式锁——Redis和Redisson的方式

分布式~~锁,要这么念,首先得是『分布式』,然后才是『锁』分布式:这里的分布式指的是分布式系统,涉及到好多技术和理论,包括CAP 理论、分布式存储、分布式事务、分布式锁...分布式系统是由一组通过网络进行通信、为了完成共同的任务而协调工作的计算机节点组成的系统。分布式系统的出现是为了用廉价的、普通的机器完成单个计算机无法完成的计算、存储任务。其目的是利用更多的机器,处理更多的数据。锁:对对,就是你想的那个,Javer 学的第一个锁应该就是Java 初级面试问题,来拼写下赛克瑞纳挨日的线程锁。

20年码农 4289
上一篇: Redis 篇-深入了解基于 Redis 实现分布式锁(解决多线程安全问题、锁误删问题和确保锁的原子性问题)
下一篇: Redis 篇-深入了解基于 Redis 实现消息队列(比较基于 List 实现消息队列、基于 PubSub 发布订阅模型之间的区别)
小扳
小扳 优质创作者: Java技术领域 优质创作者: Java技术领域
博客等级 码龄4年 1万+粉丝 167原创
评论 54
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小扳

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值