redis分布式锁

redis分布式锁

≡放荡痞女 提交于 2020-01-17 03:54:27
package com.campuscard.core.utils; import java.util.Date; import java.util.concurrent.TimeUnit; import org.apache.commons.lang3.StringUtils; import org.springframework.dao.DataAccessException; import org.springframework.data.redis.connection.RedisConnection; import org.springframework.data.redis.core.RedisCallback; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.serializer.RedisSerializer; public class RedisLock { // 加锁超时时间,单位毫秒, 即:加锁时间内执行完操作,如果未完成会有并发现象 private static final long LOCK_TIMEOUT = 3 * 1000; private StringRedisTemplate

redis锁在事务提交之后再释放

爷,独闯天下 提交于 2020-01-16 13:34:25
发现 我们平时使用 分布式锁的方式有问题 如: try {} finnally{ 释放锁} , 如果方法有事务的话 , 进到finnally 的时候并不代表,数据已经持久化。 会导致锁提前释放,正确的做法应该是 事物完成后再释放锁。 /** * 事务结束后释放锁 */ private void unlockAfterTransaction(LockResult lockResult) { //事物完成后释放锁 TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() { @Override public void afterCompletion(int status) { super.afterCompletion(status); distLockSservice.unlock(lockResult); } }); } 来源: CSDN 作者: 矫首遐观 链接: https://blog.csdn.net/u010408502/article/details/104001087

redis 分布式锁

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

Springboot + redis + 注解 + 拦截器来实现接口幂等性校验

半世苍凉 提交于 2020-01-16 02:22:24
一、概念 幂等性, 通俗的说就是一个接口, 多次发起同一个请求, 必须保证操作只能执行一次 比如: 订单接口, 不能多次创建订单 支付接口, 重复支付同一笔订单只能扣一次钱 支付宝回调接口, 可能会多次回调, 必须处理重复回调 普通表单提交接口, 因为网络超时等原因多次点击提交, 只能成功一次 等等 二、常见解决方案 唯一索引 – 防止新增脏数据 token机制 – 防止页面重复提交 悲观锁 – 获取数据的时候加锁(锁表或锁行) 乐观锁 – 基于版本号version实现, 在更新数据那一刻校验数据 分布式锁 – redis(jedis、redisson)或zookeeper实现 状态机 – 状态变更, 更新数据时判断状态 三、本文实现 本文采用第2种方式实现, 即通过redis + token机制实现接口幂等性校验 四、实现思路 为需要保证幂等性的每一次请求创建一个唯一标识token, 先获取token, 并将此token存入redis, 请求接口时, 将此token放到header或者作为请求参数请求接口, 后端接口判断redis中是否存在此token: 如果存在, 正常处理业务逻辑, 并从redis中删除此token, 那么, 如果是重复请求, 由于token已被删除, 则不能通过校验, 返回请勿重复操作提示 如果不存在, 说明参数不合法或者是重复请求, 返回提示即可 五

分布式锁:Redis+注解

萝らか妹 提交于 2020-01-16 00:54:29
title: “分布式锁:Redis+注解” url: “https://wsk1103.github.io/” tags: 学习笔记 分布式锁 1. 起因 使用 redis 来设计分布式锁,经常需要在每个方法开始执行 setNx(key) ,然后在方法运行结束后 del(key) 。而且当系统需要改进使用分布式锁的时候,需要修改的地方偏多,这样造成了过程繁杂,而且有时候又忘记 del(key) ,导致间隔比较短请求被拦截。所以考虑设计一个结合 注解 和 AOP 来完成分布式锁。 2. 思路流程图 3. 代码设计 3.1 增加依赖 <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjrt --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.9.5</version> </dependency> <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver<

SpringBoot集成:1、SpringBoot -Redis-前期

☆樱花仙子☆ 提交于 2020-01-15 04:43:22
一、概要 随着Spring Boot2.x的到来,支持的组件越来越丰富,也越来越成熟,其中对Redis的支持不仅仅是丰富了它的API,更是替换掉底层Jedis的依赖,取而代之换成了Lettuce(生菜)Lettuce和Jedis的都是连接Redis Server的客户端程序。Jedis在实现上是直连redis server,多线程环境下非线程安全,除非使用连接池,为每个Jedis实例增加物理连接。Lettuce基于Netty的连接实例(StatefulRedisConnection),可以在多个线程间并发访问,且线程安全,满足多线程环境下的并发访问,同时它是可伸缩的设计,一个连接实例不够的情况也可以按需增加连接实例 二、常用的java连接框架 1、Jedis Github Jedis是Redis官方推荐的Java连接开发工具 2、redisson 官方网站 实现了分布式和可扩展的Java数据结构 3、lettuce 用于线程安全同步,异步和响应使用,支持集群,Sentinel,管道和编码器。* 官方网站 4、对比: **Jedis:**比较全面的提供了Redis的操作特性 **Redisson:**提供很多分布式相关操作服务,例如: 分布式锁 , 分布式集合 ,可通过Redis支持延迟队列 Lettuce: 主要在一些 分布式缓存 框架上使用比较多 三、spring-data

Redis五种常用数据类型

走远了吗. 提交于 2020-01-15 00:46:35
string 字符串常用操作 1.存入字符串键值对 SET key value 2.批量存储字符串键值对 MSET key value [key value ...] 3.获取一个字符串键值 GET key 4.批量获取字符串键值 MGET key [key ...] 5.删除一个键 DEL key [key ...] 6.设置一个键的过期时间(秒) EXPIRE key seconds 原子加减 1.将key中存储的数字值加一 INCR key 2.将key中存储的数字值减一 DECR key 3.将key所存储的值加上increment INCRBY key increment 4.将key所存储的值减去decrement DECRBY key decrement 单值缓存 SET key value GET key 对象缓存 1.SET user:1 value(json格式数据) 2.MSET user:1:name test user:1:balance 10086 MGET user:1:name user:1:balance 分布式锁 SETNX product:10001 true //返回1代表获取锁成功 SETNX product:10001 true //返回0代表获取锁失败 ....执行业务操作 DEL product:10001 //执行完业务释放锁

Redis入门

大城市里の小女人 提交于 2020-01-14 02:17:16
redis 是什么? 是完全开源免费的,用c语言编写的,是一个单线程,高性能的(key/value)内存数据库,基于内存运行并支持持久化的nosql数据库 能干嘛? 主要是用来做缓存,但不仅仅只能做缓存,比如:redis的计数器生成分布式唯一主键,redis实现分布式锁,队列,会话缓存。 去哪下? 官网,也可以通过Linux yum直接下载安装 怎么玩? 1.安装 2.redis数据类型(api操作) 3.redis配置文件解析 4.redis的持久化 5.redis的事务 6.redis的发布订阅 7.java客户端操作(jedis) redis的安装 1.解压 2.make 如果make报错的话 大家就可以看一下是不是报没有gcc的错 如果是报没有gcc的错,那就要先安装一个gcc yum install gcc-c++ 安装好gcc之后最好执行一下make distclean 因为前面make的时候它执行了一些东西 要先把他清掉 3.make install 查看redis默认安装位置 /usr/local/bin redis设置外网访问 1.注释bind并且把protected-mode no 2.使用bind 3.设置密码 protected-mode它启用的条件有两个,第一是没有使用bind,第二是没有设置访问密码。 redis数据类型及api操作(http:/

SpringBoot项目接入Redisson分布式锁

戏子无情 提交于 2020-01-14 02:05:05
概述 可参考以下网站 Redisson Github WIKI Redisson是一个在Redis的基础上实现的Java驻内存数据网格(In-Memory Data Grid)。提供了使用Redis的最简单和最便捷的方法。促进使用者对Redis的关注分离。并且底层采用的是Netty框架。 我的理解:基于Netty封装了一些利用了Redis特性的工具,让我们可以更高效、更简便的使用Redis。 本文主要介绍,如果在一个springboot项目中接入并使用Redisson网络提供的可重入锁(Reentrant Lock),特别注意:这只是Redisson整个框架中的一小部分。 如何使用 说明:该项目是Springboot(1.5.10.RELEASE),其中已经集成了Redis(如何集成这个就不多介绍这个了= =),以下仅演示接入并使用Redisson的一种方式,更多接入方式 引入maven依赖 <dependency> <groupId>org.redisson</groupId> <artifactId>redisson</artifactId> <version>3.5.0</version> </dependency> 配置文件 redisson: address: redis://${spring.redis.host}:${spring.redis.port} #

Redis分布式锁中的问题

假如想象 提交于 2020-01-13 08:11:59
使用 使用 set key value ex 5 nx 命令设置key value 5秒过期 不存在才能设置成功,成功代表获取了分布式锁 随机值 在set时,key为固定,但value对不同线程应不同,如使用线程名。 如果使用的value相同会有什么问题?我们假设固定为 key=lock_key,value=lock_value 假设线程1获取到了分布式锁,超时30秒,但线程1的实际执行实际达到了40秒,在第30秒的时候锁被自动释放,线程2拿到了锁,线程2在继续自己的任务,假设是30秒。十秒后线程1结束,释放了锁,但这时候释放的是线程2设置的锁,从而导致同步出错。 若每个线程对应的value是不同的,在释放锁时只有value相同才会释放。但这个判断删除操作不是原子性的,可以使用lua脚本方式实现 if redis . call ( 'get' , KEYS [ 1 ] ) == ARGV [ 1 ] then return redis . call ( 'del' , KEYS [ 1 ] ) else return 0 end 锁超时 如上面所说的,如果获取锁设置了30秒超时,但实际任务执行时间超过了30秒怎么办? 可以使用守护线程的方式,在第29秒时给key续命10秒,然后十秒后守护线程继续执行。 主线程执行结束守护线程也会跟随销毁 单机故障引发并发问题 对于主从同步的情况