1    Redis事务

1.1   Redis事务介绍

Redis的事务是通过MULTI,EXEC,DISCARD和WATCH这四个命令来完成的。

Redis的单个命令都是原子性的,所以这里确保事务性的对象是命令集合

Redis将命令集合序列化并确保处于同一事务的命令集合连续且不被打断的执行

Redis不支持回滚操作

1.2   相关命令

MULTI

用于标记事务块的开始

Redis会将后续的命令逐个放入队列中,然后使用EXEC命令原子化地执行这个命令序列。

语法:multi

EXEC

在一个事务中执行所有先前放入队列的命令,然后恢复正常的连接状态

语法:exec

DISCARD

清除所有先前在一个事务中放入队列的命令,然后恢复正常的连接状态。

语法:discard

WATCH

当某个事务需要按条件执行时,就要使用这个命令将给定的键设置为受监控的状态。

语法:watch key [key…]

       注意事项:使用该命令可以实现redis的乐观锁

UNWATCH

清除所有先前为一个事务监控的键。

语法:unwatch

1.3   事务失败处理

Redis语法错误(可以理解为编译期错误)

Redis类型错误(可以理解为运行期错误)

Redis不支持事务回滚

       为什么redis不支持事务回滚?

1、大多数事务失败是因为语法错误或者类型错误,这两种错误,在开发阶段都是可以预见的

2、redis为了性能方面就忽略了事务回滚

2    Redis实现分布式锁

2.1   锁的处理

单应用中使用锁:单进程多线程

synchronize、Lock

分布式应用中使用锁:多进程

2.2   分布式锁的实现方式

基于数据库的乐观锁实现分布式锁

基于zookeeper临时节点的分布式锁

基于redis的分布式锁

2.3   分布式锁的注意事项

互斥性在任意时刻,只有一个客户端能持有锁

同一性:加锁和解锁必须是同一个客户端,客户端自己不能把别人加的锁给解了。

可重入性:即使有一个客户端在持有锁的期间崩溃而没有主动解锁,也能保证后续其他客户端能加锁。

2.4   实现分布式锁

2.4.1获取锁

方式1(使用set命令实现) --推荐:

/**

* 使用redis的set命令实现获取分布式锁

* @param lockKey      可以就是锁

* @param requestId             请求ID,保证同一性

* @param expireTime  过期时间,避免死锁

* @return

*/

publicstaticboolean getLock(String lockKey,String requestId,intexpireTime) {

//NX:保证互斥性

String result = jedis.set(lockKey, requestId, "NX", "EX", expireTime);

if("OK".equals(result)) {

returntrue;

}

returnfalse;

}

方式2(使用setnx命令实现):

publicstaticboolean getLock(String lockKey,String requestId,intexpireTime) {

Long result = jedis.setnx(lockKey, requestId);

if(result == 1) {

jedis.expire(lockKey, expireTime);

returntrue;

}

returnfalse;

}

2.4.2释放锁

方式1(del命令实现):

/**

* 释放分布式锁

* @param lockKey

* @param requestId

*/

publicstaticvoid releaseLock(String lockKey,String requestId) {

if (requestId.equals(jedis.get(lockKey))) {

jedis.del(lockKey);

}

}

方式2(redis+lua脚本实现)--推荐:

publicstaticboolean releaseLock(String lockKey, String requestId) {

String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";

Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId));

if (result.equals(1L)) {

returntrue;

}

returnfalse;

}

1    Redis事务

1.1   Redis事务介绍

Redis的事务是通过MULTI,EXEC,DISCARD和WATCH这四个命令来完成的。

Redis的单个命令都是原子性的,所以这里确保事务性的对象是命令集合

Redis将命令集合序列化并确保处于同一事务的命令集合连续且不被打断的执行

Redis不支持回滚操作

1.2   相关命令

MULTI

用于标记事务块的开始

Redis会将后续的命令逐个放入队列中,然后使用EXEC命令原子化地执行这个命令序列。

语法:multi

EXEC

在一个事务中执行所有先前放入队列的命令,然后恢复正常的连接状态

语法:exec

DISCARD

清除所有先前在一个事务中放入队列的命令,然后恢复正常的连接状态。

语法:discard

WATCH

当某个事务需要按条件执行时,就要使用这个命令将给定的键设置为受监控的状态。

语法:watch key [key…]

       注意事项:使用该命令可以实现redis的乐观锁

UNWATCH

清除所有先前为一个事务监控的键。

语法:unwatch

1.3   事务失败处理

Redis语法错误(可以理解为编译期错误)

Redis类型错误(可以理解为运行期错误)

Redis不支持事务回滚

       为什么redis不支持事务回滚?

1、大多数事务失败是因为语法错误或者类型错误,这两种错误,在开发阶段都是可以预见的

2、redis为了性能方面就忽略了事务回滚

2    Redis实现分布式锁

2.1   锁的处理

单应用中使用锁:单进程多线程

synchronize、Lock

分布式应用中使用锁:多进程

2.2   分布式锁的实现方式

基于数据库的乐观锁实现分布式锁

基于zookeeper临时节点的分布式锁

基于redis的分布式锁

2.3   分布式锁的注意事项

互斥性在任意时刻,只有一个客户端能持有锁

同一性:加锁和解锁必须是同一个客户端,客户端自己不能把别人加的锁给解了。

可重入性:即使有一个客户端在持有锁的期间崩溃而没有主动解锁,也能保证后续其他客户端能加锁。

2.4   实现分布式锁

2.4.1获取锁

方式1(使用set命令实现) --推荐:

/**

* 使用redis的set命令实现获取分布式锁

* @param lockKey      可以就是锁

* @param requestId             请求ID,保证同一性

* @param expireTime  过期时间,避免死锁

* @return

*/

publicstaticboolean getLock(String lockKey,String requestId,intexpireTime) {

//NX:保证互斥性

String result = jedis.set(lockKey, requestId, "NX", "EX", expireTime);

if("OK".equals(result)) {

returntrue;

}

returnfalse;

}

方式2(使用setnx命令实现):

publicstaticboolean getLock(String lockKey,String requestId,intexpireTime) {

Long result = jedis.setnx(lockKey, requestId);

if(result == 1) {

jedis.expire(lockKey, expireTime);

returntrue;

}

returnfalse;

}

2.4.2释放锁

方式1(del命令实现):

/**

* 释放分布式锁

* @param lockKey

* @param requestId

*/

publicstaticvoid releaseLock(String lockKey,String requestId) {

if (requestId.equals(jedis.get(lockKey))) {

jedis.del(lockKey);

}

}

方式2(redis+lua脚本实现)--推荐:

publicstaticboolean releaseLock(String lockKey, String requestId) {

String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";

Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId));

if (result.equals(1L)) {

returntrue;

}

returnfalse;

}

Redis事务与可分布式锁的更多相关文章

  1. redis事务机制和分布式锁

    Redis事务机制 严格意义来讲,Redis的事务和我们理解的传统数据库(如mysql)的事务是不一样的:Redis的事务实质上是命令的集合,在一个事务中要么所有命令都被执行,要么所有事物都不执行.  ...

  2. 使用Redis SETNX 命令实现分布式锁

    基于setnx和getset http://blog.csdn.net/lihao21/article/details/49104695 使用Redis的 SETNX 命令可以实现分布式锁,下文介绍其 ...

  3. Redis 上实现的分布式锁

    转载Redis 上实现的分布式锁 由于近排很忙,忙各种事情,还有工作上的项目,已经超过一个月没写博客了,确实有点惭愧啊,没能每天或者至少每周坚持写一篇博客.这一个月里面接触到很多新知识,同时也遇到很多 ...

  4. 在 Redis 上实现的分布式锁

    由于近排很忙,忙各种事情,还有工作上的项目,已经超过一个月没写博客了,确实有点惭愧啊,没能每天或者至少每周坚持写一篇博客.这一个月里面接触到很多新知识,同时也遇到很多技术上的难点,在这我将对每一个有用 ...

  5. Redis整合Spring实现分布式锁

    spring把专门的数据操作独立封装在spring-data系列中,spring-data-redis是对Redis的封装 <dependencies> <!-- 添加spring- ...

  6. 使用Redis SETNX 命令实现分布式锁(转载)

    使用Redis的 SETNX 命令可以实现分布式锁,下文介绍其实现方法. SETNX命令简介 命令格式 SETNX key value 将 key 的值设为 value,当且仅当 key 不存在. 若 ...

  7. 【连载】redis库存操作,分布式锁的四种实现方式[一]--基于zookeeper实现分布式锁

    一.背景 在电商系统中,库存的概念一定是有的,例如配一些商品的库存,做商品秒杀活动等,而由于库存操作频繁且要求原子性操作,所以绝大多数电商系统都用Redis来实现库存的加减,最近公司项目做架构升级,以 ...

  8. 基于 Redis 实现简单的分布式锁

    摘要 分布式锁在很多应用场景下是非常有效的手段,比如当运行在多个机器上的不同进程需要访问同一个竞争资源的时候,那么就会涉及到进程对资源的加锁和释放,这样才能保证数据的安全访问.分布式锁实现的方案有很多 ...

  9. 基于Redis实现简单的分布式锁【理论】

    摘要 分布式锁在很多应用场景下是非常有效的手段,比如当运行在多个机器上的不同进程需要访问同一个竞争资源的时候,那么就会涉及到进程对资源的加锁和释放,这样才能保证数据的安全访问.分布式锁实现的方案有很多 ...

随机推荐

  1. 《Python学习手册 第五版》 -第7章 字符串基础

    本章内容是关于字符串的,字符串是编程中经常遇到的问题,本章的内容不是包含所有字符串的讲解,而是针对其最基本的内容进行说明,后续的相关章节会根据需要进行扩展和说明,例如后续的第37章内容会讲解Unico ...

  2. Linux命令行与Shell脚本编程大全

    快来参加<Linux命令行与Shell脚本编程大全>学习吧,提升技能,展示自我. 点击链接即可进入学习:https://s.imooc.com/WTmCO6H 课程亮点适合零基础读者,从零 ...

  3. JavaWeb前置知识 : 动态和静态的区别、两种架构、常见状态码

    JavaWeb程序设计(一) : 前置知识 1.动态网页与静态网页的区别: a.不要和是否有"动感"混为一谈. b.是否随着时间.地点.用户操作的改变而改变 (例如 : 在百度上搜 ...

  4. PYTHON 学习笔记1 PYTHON 入门 搭建环境与基本类型

    简介 Python,当然大家听到这个名词不再是有关于像JAVA 一样的关于后台,我们学习Python 的目的在于对于以后数据分析和机器学习AI 奠定基础,Python 在数据分析这一块,可谓是有较好的 ...

  5. JVM性能优化系列-(4) 编写高效Java程序

    4. 编写高效Java程序 4.1 面向对象 构造器参数太多怎么办? 正常情况下,如果构造器参数过多,可能会考虑重写多个不同参数的构造函数,如下面的例子所示: public class FoodNor ...

  6. javascript原生js轮播图

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  7. mongodb搭建带auth的主从

    1:下载mongodb包(mongodb3.4的方法一样,就是mongodb内用户设置到时候不同用户对应不同库,验证时得先创建某个库到用户参考http://ibruce.info/2015/03/03 ...

  8. VMware 克隆 CentOS 后网卡信息修改

    概述 在我们需要多台 CentOS 虚拟机的时候,对已有虚拟机的系统进行克隆或是复制.但是这样做又有一个问题,克隆出来的虚拟机启动的时候你输入命令:ifconfig,eth0 网卡信息没了,只有一个 ...

  9. sublime text3 安装详解+前端插件

    1,下载sublime 3,地址:http://www.sublimetext.com/ 2,注册码:(在网上找的,感谢前辈)打开sublime3, help----add license---复制下 ...

  10. Hadoop之HDFS扩容方法

    HDFS就是用来存取数据的,那么当数据太多的时候存不下,我们必需扩充硬盘容量,或者换个更大的硬盘. 由于它是分布式文件系统,有两种扩充HDFS集群容量的方法:横向扩容和纵向扩容 横向扩容 横向扩容就是 ...