分布式锁

什么是分布式锁及正确使用redis实现分布式锁

守給你的承諾、 提交于 2020-02-08 13:20:47
分布式锁   分布式锁其实可以理解为:控制分布式系统有序的去对共享资源进行操作,通过互斥来保持一致性。 举个不太恰当的例子:假设共享的资源就是一个房子,里面有各种书,分布式系统就是要进屋看书的人,分布式锁就是保证这个房子只有一个门并且一次只有一个人可以进,而且门只有一把钥匙。然后许多人要去看书,可以,排队,第一个人拿着钥匙把门打开进屋看书并且把门锁上,然后第二个人没有钥匙,那就等着,等第一个出来,然后你在拿着钥匙进去,然后就是以此类推 实现原理 互斥性 保证同一时间只有一个客户端可以拿到锁,也就是可以对共享资源进行操作 安全性 只有加锁的服务才能有解锁权限,也就是不能让a加的锁,bcd都可以解锁,如果都能解锁那分布式锁就没啥意义了 可能出现的情况就是a去查询发现持有锁,就在准备解锁,这时候忽然a持有的锁过期了,然后b去获得锁,因为a锁过期,b拿到锁,这时候a继续执行第二步进行解锁如果不加校验,就将b持有的锁就给删除了 避免死锁 出现死锁就会导致后续的任何服务都拿不到锁,不能再对共享资源进行任何操作了 保证加锁与解锁操作是原子性操作 例: 假设a用redis实现分布式锁, 1,设置key set(key,value) 2,给key设置过期时间 假设现在a刚实现set后,程序崩了就导致了没给key设置过期时间就导致key一直存在就发生了死锁 如何实现分布式锁  

Redis 面试题汇总

本小妞迷上赌 提交于 2020-02-07 15:18:32
Redis 面试题汇总 1.Redis 使用场景有哪些? 答:Redis 使用场景如下: 记录帖子点赞数、点击数、评论数 缓存近期热帖 缓存文章详情信息 记录用户会话信息 2.Redis 有哪些功能? 答:Redis 功能如下: 数据缓存功能 分布式锁的功能 支持数据持久化 支持事务 支持消息队列 3.Redis 支持哪些数据类型? 答:Redis 支持的数据类型如下: String 字符串 List 列表 Set 无序集合 ZSet 有序集合 Hash 哈希类型 4.Redis 相比 Memcached 有哪些优势? 答:Redis 相比 Memcached 优势如下: Memcached 所有的值均是简单的字符串,Redis 支持更为丰富的数据类型 Redis 的速度比 Memcached 要快 Redis 可以持久化 Redis 可以设置过期时间 Redis 支持主从同步 5.Redis 支持哪些淘汰策略? 答:Redis 淘汰策略如下: noeviction:禁止淘汰数据; allkeys-lru:尝试回收最少使用的键,使得新添加的数据有空间存放; volatile-lru:尝试回收最少使用的键,但仅限于在过期集合的键,使得新添加的数据有空间存放; allkeys-random:回收随机的键使得新添加的数据有空间存放; volatile-random

分布式锁是什么?为什么使用分布式锁?分布式锁实现方式?

一笑奈何 提交于 2020-02-06 20:25:07
分布式锁是多个jvm可以共享的锁。 传统java并发API只适用于单个jvm,多个jvm对临界区访问就无法使用,所以需要分布式锁。 实现方式1: 使用mysql数据库:创建一个表使用方法名字段(需要加锁的字段)作为唯一索引,获取锁的时候执行插入,释放锁的时候执行删除 缺点:1.不阻塞 2.单点可用性差 3.没有失效时间 4.不可重入 改进方式: 1.循环获取锁 2.集群方式 3.设置定时任务 5.加入一个字段统计入锁次数 实现方式2: 使用redis:获取锁set 释放锁 del 缺点:1.不阻塞 2.单点可用性差 3.没有失效时间 4.不可重入 改进方式: 1.循环获取锁 2.集群方式 3.设置过期时间 5.加入一个字段统计入锁次数 实现方式3: 使用zookeeper:获取锁的时候在持久化结点下创建临时时序结点。如果此临时时序结点是第一个结点就获取到锁。如果不是就监听前一个结点,当前一个结点消失变获取到锁。 释放锁的时候断开连接就可以删除结点 来源: CSDN 作者: 南阳木子 链接: https://blog.csdn.net/qq_36638446/article/details/104199359

解决 Redis 的并发竞争 Key 问题

偶尔善良 提交于 2020-02-05 19:30:18
1、Redis 的并发竞争 Key : 多个系统同时对一个 key 进行操作,但是最后执行的顺序和我们期望的顺序不同,这样也就导致了结果的不同! 2、解决方式:   分布式锁(zookeeper 和 redis 都可以实现分布式锁)。(如果不存在 Redis 的并发竞争 Key 问题,不要使用分布式锁,这样会影响性能)基于zookeeper临时有序节点可以实现的分布式锁。   大致思想为:每个客户端对某个方法加锁时,在zookeeper上的与该方法对应的指定节点的目录下,生成一个唯一的瞬时有序节点。 判断是否获取锁的方式很简单,只需要判断有序节点中序号最小的一个。 当释放锁的时候,只需将这个瞬时节点删除即可。同时,其可以避免服务宕机导致的锁无法释放,而产生的死锁问题。完成业务流程后,删除对应的子节点释放锁。 在实践中,当然是从以可靠性为主。所以首推Zookeeper。 来源: https://www.cnblogs.com/guoyu1/p/12266139.html

分布式缓存集群方案特性使用场景(Memcache/Redis(Twemproxy/Codis/Redis-cluster))优缺点对比及选型

蓝咒 提交于 2020-02-05 04:49:59
分布式缓存集群方案特性使用场景(Memcache/Redis(Twemproxy/Codis/Redis-cluster))优缺点对比及选型 分布式缓存特性: 1) 高性能:当传统数据库面临大规模数据访问时,磁盘I/O 往往成为性能瓶颈,从而导致过高的响应延迟.分布式缓存将高速内存作为数据对象的存储介质,数据以key/value 形式存储,理想情况下可以获得DRAM 级的读写性能; 2) 动态扩展性:支持弹性扩展,通过动态增加或减少节点应对变化的数据访问负载,提供可预测的性能与扩展性;同时,最大限度地提高资源利用率; 3) 高可用性:可用性包含数据可用性与服务可用性两方面.基于冗余机制实现高可用性,无单点失效(single point of failure),支持故障的自动发现,透明地实施故障切换,不会因服务器故障而导致缓存服务中断或数据丢失.动态扩展时自动均衡数据分区,同时保障缓存服务持续可用; 4) 易用性:提供单一的数据与管理视图;API 接口简单,且与拓扑结构无关;动态扩展或失效恢复时无需人工配置;自动选取备份节点;多数缓存系统提供了图形化的管理控制台,便于统一维护; 5) 分布式代码执行(distributed code execution):将任务代码转移到各数据节点并行执行,客户端聚合返回结果,从而有效避免了缓存数据的移动与传输.最新的Java 数据网格规范JSR

第一节 Redis常见业务场景

旧街凉风 提交于 2020-02-05 02:38:38
前言 以前在实习的时候,去Redis官网学了不少命令。不过现在看来,当初只是学到了一些简单的命令。等到实际工作中,在SpringBoot中也快速的集成了Redis。但是到底Redis应用在哪些实际场景中。我之前一直没有深入研究过。现在,我想好好研究一下Redis,因为在实际项目中,引入一个中间件是一件十分谨慎的事情。作为研发负责人,一旦吃不透某种技术,在生产库上出现问题,若无人能解决,将会出现严重的后果。 萌发深入学习Redis的另外一点动机是,上次同事问我,你知道哪些Redis的实际业务场景吗?我只简单了说了几个,同事说我还没有体会过Redis的牛逼之处。孤陋寡闻的我尴尬的笑了笑。 常见业务场景 Redis可以理解为一个数据库,一个缓存中间件,一个消息中间件。这玩意基于内容,跑得很快。主要业务场景: 缓存击穿、穿透、雪崩解决方案 消息通知与队列 排行榜 Session共享 分布式锁 秒杀系统 来源: CSDN 作者: 小大宇 链接: https://blog.csdn.net/yanluandai1985/article/details/104172009

Redis 分布式锁的正确实现方式( Java 版 )

狂风中的少年 提交于 2020-02-04 09:06:23
前言 分布式锁一般有三种实现方式: 1. 数据库乐观锁;2. 基于Redis的分布式锁;3. 基于ZooKeeper的分布式锁。本篇博客将介绍第二种方式,基于Redis实现分布式锁。虽然网上已经有各种介绍Redis分布式锁实现的博客,然而他们的实现却有着各种各样的问题,为了避免误人子弟,本篇博客将详细介绍如何正确地实现Redis分布式锁。 可靠性 首先,为了确保分布式锁可用,我们至少要确保锁的实现同时满足以下四个条件: 互斥性。在任意时刻,只有一个客户端能持有锁。 不会发生死锁。即使有一个客户端在持有锁的期间崩溃而没有主动解锁,也能保证后续其他客户端能加锁。 具有容错性。只要大部分的Redis节点正常运行,客户端就可以加锁和解锁。 解铃还须系铃人。加锁和解锁必须是同一个客户端,客户端自己不能把别人加的锁给解了。 代码实现 组件依赖 首先我们要通过Maven引入Jedis开源组件,在pom.xml文件加入下面的代码: <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.9.0</version> </dependency> 加锁代码 正确姿势 Talk is cheap, show me the code。先展示代码,再带大家慢慢解释为什么这样实现:

Redis系列--1.Redis概述

元气小坏坏 提交于 2020-02-03 14:23:30
什么是redis? Redis 是完全开源免费的,遵守BSD协议,是一个基于内存的高性能的key-value数据库。 Redis 与其他 key - value 缓存产品有以下三个特点: Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。 Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。 Redis支持数据的备份,即master-slave模式的数据备份。 为什么使用redis,有哪些优点? 性能极高 – Redis能读的速度是110000次/s,写的速度是81000次/s 。 丰富的数据类型 – Redis支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作。 原子 – Redis的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性,通过MULTI和EXEC指令包起来。 丰富的特性 – Redis还支持 publish/subscribe, 通知, key 过期等等特性。 redis的应用场景 1.缓存功能 缓存设计主要问题: 缓存穿透; 缓存击穿; 缓存与数据库不一致; 缓存热点数据; https://www.cnblogs.com

实现分布式锁的方式

不想你离开。 提交于 2020-02-03 00:28:04
一、为什么要使用分布式锁 我们在开发应用的时候,如果需要对某一个共享变量进行多线程同步访问的时候,可以使用我们学到的Java多线程的18般武艺进行处理,并且可以完美的运行,毫无Bug! 注意这是单机应用,也就是所有的请求都会分配到当前服务器的JVM内部,然后映射为操作系统的线程进行处理!而这个共享变量只是在这个JVM内部的一块内存空间! 后来业务发展,需要做集群,一个应用需要部署到几台机器上然后做负载均衡,大致如下图: 上图可以看到,变量A存在JVM1、JVM2、JVM3三个JVM内存中(这个变量A主要体现是在一个类中的一个成员变量,是一个有状态的对象,例如:UserController控制器中的一个整形类型的成员变量),如果不加任何控制的话,变量A同时都会在JVM分配一块内存,三个请求发过来同时对这个变量操作,显然结果是不对的!即使不是同时发过来,三个请求分别操作三个不同JVM内存区域的数据,变量A之间不存在共享,也不具有可见性,处理的结果也是不对的! 如果我们业务中确实存在这个场景的话,我们就需要一种方法解决这个问题! 为了保证一个方法或属性在高并发情况下的同一时间只能被同一个线程执行,在传统单体应用单机部署的情况下,可以使用Java并发处理相关的API(如ReentrantLock或Synchronized)进行互斥控制。在单机环境中,Java中提供了很多并发处理相关的API

Redis 分布式锁实现

谁说我不能喝 提交于 2020-02-02 22:39:16
在分布式集群环境下,对 Redis 数据的修改也会发生冲突,这时候需要利用锁的机制,防止数据在同一时间被多个系统修改。 实现分布式锁的思路就是利用 Redis 的两个命令:setnx 和 setex,修改数据前使用 setnx 命令对操作加锁,防止其他系统执行相同操作,使用 setex 命令设置锁超时时间(这一步的目的是防止系统突然挂掉,没有解锁),在操作结束后,进行解锁。 我们新建一个任务 Scheduled,每10秒执行一次,在不同的机器(虚拟机)上启动相同的项目,因为锁的原因,同一时间只有一个任务被执行,代码如下: @Service public class LockNxExJob { private static final Logger logger = LoggerFactory.getLogger(LockNxExJob.class); @Autowired private RedisService redisService; @Autowired private RedisTemplate redisTemplate; private static String LOCK_PREFIX = "prefix_"; @Scheduled(cron = "0/10 * * * * *") public void lockJob() { String lock = LOCK