redisson

分布式锁的实现分析

谁说胖子不能爱 提交于 2019-12-12 21:47:47
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> 1、设计目标 分布式部署的应用集群中保证数据更新的互斥性,且程序出现异常时,锁能够自动释放,避免死锁发生。 2、为什么要使用分布式锁 为了保证分布式部署的应用集群中同一时间只有一个客户端对共享资源进行操作。根据锁的用途再细分: 对共享资源的操作是幂等性的,使用分布式锁能够避免重复操作,从而提高效率。 对共享资源的操作是非幂等的,比如订单状态的修改,如果多个客户端同时操作,最后的结果可能很遭,使用分布式锁可以让各个客户端分散时间操作。 3、分布式锁应具备哪些条件 这也是分布式锁的关键技术。 互斥性 这个是分布式锁的基本要求,分布式锁需要保证不同客户端的不同线程之间互斥。 可重入性 支持锁的重入,减少资源消耗。 锁超时释放 获取锁的客户端因为某些原因而宕机,而未能释放锁,其他客户端无法获取此锁,锁超时释放是为了避免死锁。 安全性 锁只能被持有该锁的用户删除,而不能被其他用户删除。 高效与高可用 加锁与解锁需要高效,并保证高可用,当部分节点宕机,客户端仍能获取锁或者释放锁。 支持阻塞与非阻塞 阻塞就是线程获取不到锁一直阻塞,增加超时时间可以防止一直阻塞。非阻塞则获取不到锁不阻塞线程。 支持公平与非公平 公平锁就是按照加锁的顺序获取到锁,非公平锁即无序。 4、基于Redis 4.1、 从一个问题开始 问题

Redis中的Java分布式缓存

邮差的信 提交于 2019-12-12 16:58:35
为什么在分布式Java应用程序中使用缓存?今天学习了两节优锐课讲解分布式缓存的内容,收获颇多,分享给大家。 在提高应用程序的速度和性能时,每毫秒都是至关重要的。例如,根据Google的一项研究,如果网站在3秒或更短时间内无法加载,则有53%的移动用户会离开该网站。 缓存是使你的分布式应用程序更快的最重要的技术之一。你可以将信息存储到计算机的CPU中越近,访问信息的速度就越快。从CPU缓存中加载数据要比从RAM中加载数据快得多,这也比从硬盘或通过网络加载数据快得多。 为了存储经常访问的数据,分布式应用程序在多台计算机上维护高速缓存。分布式缓存通常是减少分布式应用程序的延迟并提高其并发性和可伸缩性的基本策略。 Redis是一种流行的开源内存中数据结构存储,可以用作数据库,缓存或消息代理。因为Redis从内存而不是从磁盘加载数据,所以Redis比许多传统的数据库解决方案要快。 但是,使分布式缓存在Redis中正常工作对于开发人员可能是一个挑战。例如,本地缓存失效是替换或删除缓存条目的过程,必须谨慎处理。每次更新或删除一台计算机上本地缓存中存储的信息时,都必须更新作为分布式缓存一部分的所有计算机上的内存中缓存。 好消息是,有Redis框架(例如Redisson)可以帮助你构建应用程序所需的分布式缓存。在下一部分中,我们将讨论Redisson中三种重要的分布式缓存实现:Maps,Spring

分布式锁

一世执手 提交于 2019-12-12 12:44:24
什么是分布式锁 线程锁 主要用来给方法、代码块加锁。当某个方法或代码使用锁,在同一时刻仅有一个线程执行该方法或该代码段。线程锁只在同一JVM中有效果,因为线程锁的实现在根本上是依靠线程之间共享内存实现的,比如synchronized是共享对象头,显示锁Lock是共享某个变量(state)。 进程锁 为了控制同一操作系统中多个进程访问某个共享资源,因为进程具有独立性,各个进程无法访问其他进程的资源,因此无法通过synchronized等线程锁实现进程锁。 分布式锁 当多个进程不在同一个系统中,用分布式锁控制多个进程对资源的访问。 使用场景 线程间并发问题和进程间并发问题都是可以通过分布式锁解决的,但是强烈不建议这样做!因为采用分布式锁解决这些小问题是非常消耗资源的!分布式锁应该用来解决分布式情况下的多进程并发问题才是最合适的。 有这样一个情境,线程A和线程B都共享某个变量X。 如果是单机情况下(单JVM),线程之间共享内存,只要使用线程锁就可以解决并发问题。 如果是分布式情况下(多JVM),线程A和线程B很可能不是在同一JVM中,这样线程锁就无法起到作用了,这时候就要用到分布式锁来解决。 分布式锁的实现(Redis) 分布式锁实现的关键是在分布式的应用服务器外,搭建一个存储服务器,存储锁信息,这时候我们很容易就想到了Redis。首先我们要搭建一个Redis服务器

Expired Redisson Keys still visible in Redis Cli

谁说我不能喝 提交于 2019-12-11 16:15:18
问题 I just learnt about Redis and Redisson as well. Basically I am trying to use Redis for storing AcessTokens/RefreshTokens used for authorization in my app. So I want to store the tokens with an expiration time. I used Spring Data Redis to store the token but there is no Api to expire each entry in a Map. I came across this post Spring Data Redis Expire Key and hence looked up Redisson. I tried a simple maven java project to test the expiration. Here is pom.xml: <project xmlns="http://maven

使用Redisson的RScoredSortedSet实现延时队列

大兔子大兔子 提交于 2019-12-09 23:44:17
1、实现思路 在存储对象时,使用时间戳作为对象的score,score最小的在set的最前面,最先取出 伪代码如下 RScoredSortedSet<String> set = redissonClient.getScoredSortedSet("simple"); set.add(System.currentTimeMillis() + 10000,"1"); set.add(System.currentTimeMillis() + 30000,"2"); set.add(System.currentTimeMillis() + 20000,"3"); 2、项目启动时,启动个线程循环获取set中的对象,伪代码如下 package com.ahies.stm.app.init; import com.ahies.stm.app.centerControl.control.queueHandler.CentralControlQueueHandler; import org.redisson.api.RedissonClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org

Redis分布式锁的原理以及如何续期

ε祈祈猫儿з 提交于 2019-12-07 02:50:30
面试问题 Redis锁的过期时间小于业务的执行时间该如何续期? 问题分析 首先如果你之前用Redis的分布式锁的姿势正确,并且看过相应的官方文档的话,这个问题 So easy .我们来看 很多同学在用分布式锁时,都是直接百度搜索找一个Redis分布式锁工具类就直接用了,其实Redis分布式锁比较正确的姿势是采用 redisson 这个客户端工具 如何回答 默认情况下,加锁的时间是30秒.如果加锁的业务没有执行完,那么到 30-10 = 20秒的时候,就会进行一次续期,把锁重置成30秒.那这个时候可能又有同学问了,那业务的机器万一宕机了呢?宕机了定时任务跑不了,就续不了期,那自然30秒之后锁就解开了呗. Redisson分布式锁的底层原理 redisson实现Redis分布式锁的底层原理 https://mp.weixin.qq.com/s/y_Uw3P2Ll7wvk_j5Fdlusw 1)加锁机制 咱们来看上面那张图,现在某个客户端要加锁。如果该客户端面对的是一个redis cluster集群,他首先会根据hash节点选择一台机器。 这里注意 ,仅仅只是选择一台机器!这点很关键! 紧接着,就会发送一段lua脚本到redis上,那段lua脚本如下所示: 为啥要用lua脚本呢? 因为一大坨复杂的业务逻辑,可以通过封装在lua脚本中发送给redis,保证这段复杂业务逻辑执行的 原子性 。

死磕 java同步系列之redis分布式锁进化史

ぃ、小莉子 提交于 2019-12-06 06:44:44
(手机横屏看源码更方便) 问题 (1)redis如何实现分布式锁? (2)redis分布式锁有哪些优点? (3)redis分布式锁有哪些缺点? (4)redis实现分布式锁有没有现成的轮子可以使用? 简介 Redis(全称:Remote Dictionary Server 远程字典服务)是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。 本章我们将介绍如何基于redis实现分布式锁,并把其实现的进化史从头到尾讲明白,以便大家在面试的时候能讲清楚redis分布式锁的来(忽)龙(悠)去(考)脉(官)。 实现锁的条件 基于前面关于锁(分布式锁)的学习,我们知道实现锁的条件有三个: (1)状态(共享)变量,它是有状态的,这个状态的值标识了是否已经被加锁,在ReentrantLock中是通过控制state的值实现的,在ZookeeperLock中是通过控制子节点来实现的; (2)队列,它是用来存放排队的线程,在ReentrantLock中是通过AQS的队列实现的,在ZookeeperLock中是通过子节点的有序性实现的; (3)唤醒,上一个线程释放锁之后唤醒下一个等待的线程,在ReentrantLock中结合AQS的队列释放时自动唤醒下一个线程,在ZookeeperLock中是通过其监听机制来实现的;

接口限流算法:漏桶算法和令牌桶算法

拥有回忆 提交于 2019-12-05 18:23:37
漏桶算法 漏桶可以看作是一个带有常量服务时间的单服务器队列,如果漏桶(包缓存)溢出,那么数据包会被丢弃。这一点和线程池原理是很相似的。 把请求比作是水,水来了都先放进桶里,并以限定的速度出水,当水来得过猛而出水不够快时就会导致水直接溢出,即拒绝服务。 需要注意的是,在某些情况下,漏桶算法不能够有效地使用网络资源,因为漏桶的漏出速率是固定的,所以即使网络中没有发生拥塞,漏桶算法也不能使某一个单独的数据流达到端口速率。因此,漏桶算法对于存在突发特性的流量来说缺乏效率。而令牌桶算法则能够满足这些具有突发特性的流量。 令牌桶算法 令牌桶算法是网络流量整形(Traffic Shaping)和速率限制(Rate Limiting)中最常使用的一种算法。典型情况下,令牌桶算法用来控制发送到网络上的数据的数目,并允许突发数据的发送。 令牌桶算法的原理是系统会以一个恒定的速度往桶里放入令牌,而如果请求需要被处理,则需要先从桶里获取一个令牌,当桶里没有令牌可取时,则拒绝服务。从原理上看,令牌桶算法和漏桶算法是相反的,一个“进水”,一个是“漏水”。 单机限流 Google的Guava包中的RateLimiter类就是令牌桶算法的解决方案。 首先说下单机限流 package yzy.guava.test; import com.google.common.base.Optional; import com

Springboot集成Redisson分布式锁

China☆狼群 提交于 2019-12-04 05:49:53
pom文件添加Redisson依赖 <dependency> <groupId>org.redisson</groupId> <artifactId>redisson</artifactId> <version>3.6.5</version> </dependency> application配置redis信息:我的redis没有设置密码,你们有的可以加一个password填上自己的密码 spring: redis: host: localhost port: 6379 timeout: 1000 写一个Redisson配置类生成bean: package com.hengtong.led.config; import org.redisson.Redisson; import org.redisson.api.RedissonClient; import org.redisson.config.Config; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration

redisson 分布式锁 waitTime 小坑

梦想的初衷 提交于 2019-12-04 05:48:57
maven 依赖 <dependency> <groupId>org.redisson</groupId> <artifactId>redisson</artifactId> <version>2.9.0</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.dataformat</groupId> <artifactId>jackson-dataformat-avro</artifactId> <version>2.9.0</version> </dependency> RedissonManager 分装初始化 @Component @Slf4j public class RedissonManager { private Config config = new Config(); private Redisson redisson = null; public Redisson getRedisson() { return redisson; } // 从配置文件里获取 redis 的 ip 和端口 private static String redis1Ip = PropertiesUtil.getProperty("redis1.ip"); private static Integer