文档章节

Redis事务

秋风醉了
 秋风醉了
发布于 2016/04/14 13:43
字数 1025
阅读 95
收藏 1

钉钉、微博极速扩容黑科技,点击观看阿里云弹性计算年度发布会!>>>

Redis事务

redis事务简述

MULTI,EXEC,DISCARD,WATCH 四个命令是 redis 事务的四个基础命令。其中:

  • MULTI,告诉 redis 服务器开启一个事务。注意,只是开启,而不是执行

  • EXEC,告诉 redis 开始执行事务

  • DISCARD,告诉 redis 取消事务

  • WATCH,监视某一个键值对,它的作用是在事务执行之前如果监视的键值被修改,事务会被取消。

在介绍 redis 事务之前,先来展开 redis 命令队列的内部实现。


redis命令队列

redis 允许一个客户端不间断执行多条命令:发送 MULTI 后,用户键入多条命令;再发送 EXEC 即可不间断执行之前输入的多条命令。

➜  redis_7000 redis-cli -p 7000
127.0.0.1:7000> multi
OK
127.0.0.1:7000> set email helloworld
QUEUED
127.0.0.1:7000> set count 10
QUEUED
127.0.0.1:7000> incrby count 2
QUEUED
127.0.0.1:7000> exec
1) OK
2) OK
3) (integer) 12
127.0.0.1:7000>

由上面给出的 redis 客户端操作,来看看 redis 服务器的状态变化:



redis事务不可回滚

下面示例操作,

127.0.0.1:7000> multi
OK
127.0.0.1:7000> set counter 15
QUEUED
127.0.0.1:7000> incrby counter hello
QUEUED
127.0.0.1:7000> incrby counter 2
QUEUED
127.0.0.1:7000> exec
1) OK
2) (error) ERR value is not an integer or out of range
3) (integer) 17
127.0.0.1:7000> get counter
"17"

当执行exec时,会顺序的执行命令队列中的命令,其中一条命令incrby counter hello是错误的,但不会影响命令队列中其他命令的执行。从上面命令执行结果就可以看出,当incrby counter hello命令执行失败后,并没有影响下一条命令的执行,而是成功的自增了2,最后得到counter的结果是17,正确自增后的结果。


redis事务具有隔离性

开启两个redis客户端,当其中一个客户端进入事务状态后,不影响另一个客户端进入事务状态。


Redis WATCH命令

WATCH命令的实现

在每个代表数据库的 redis.h/redisDb 结构类型中, 都保存了一个 watched_keys 字典, 字典的键是这个数据库被监视的键, 而字典的值则是一个链表, 链表中保存了所有监视这个键的客户端。

比如说,以下字典就展示了一个 watched_keys 字典的例子:

其中, 键 key1 正在被 client2 、 client5 和 client1 三个客户端监视, 其他一些键也分别被其他别的客户端监视着。

WATCH 命令的作用, 就是将当前客户端和要监视的键在 watched_keys 中进行关联。

举个例子, 如果当前客户端为 client10086 , 那么当客户端执行 WATCH key1 key2 时, 前面展示的 watched_keys 将被修改成这个样子:

通过 watched_keys 字典, 如果程序想检查某个键是否被监视, 那么它只要检查字典中是否存在这个键即可; 如果程序要获取监视某个键的所有客户端, 那么只要取出键的值(一个链表), 然后对链表进行遍历即可。


WATCH命令的使用示例

客户端A如下操作,

127.0.0.1:7000> watch counter
OK
127.0.0.1:7000> multi
OK
127.0.0.1:7000> set counter 19
QUEUED
127.0.0.1:7000> incrby counter 2

接下来在客户端B修改counter的值,

127.0.0.1:7000> set counter 18
OK

最后客户端A执行exec命令,是命令队列执行,最后看结果,

127.0.0.1:7000> exec
(nil)
127.0.0.1:7000> get counter
"18"

最后返回结果为nil,说明该redis事务就没有执行,正是因为watch的作用,检测到counter的值发生了变化,导致整个事务被取消。


Jedis实现事务

如下示例代码,

package com.usoft.jedis.sample;

import org.junit.Before;
import org.junit.Test;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.Transaction;

import java.util.List;

/**
 * Created by xinxingegeya on 16/4/14.
 */
public class JedisTrxTest {

    /**
     * jedis连接池
     */
    public JedisPool jedisPool;

    @Before
    public void before() {
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxTotal(10);
        config.setMaxIdle(5);
        config.setMaxWaitMillis(5000);
        config.setTestOnBorrow(true);
        jedisPool = new JedisPool(config, "127.0.0.1", 7000);
    }

    @Test
    public void test() {
        Jedis jedis = jedisPool.getResource();
        /**
         * watch监视一个key
         * 当该key对应的值被其他客户端修改后,该事务被取消
         */
        jedis.watch("counter");
        long start = System.currentTimeMillis();
        Transaction tx = jedis.multi();
        tx.set("counter", "10");
        tx.incrBy("counter", 10);
        List<Object> results = tx.exec();
        long end = System.currentTimeMillis();
        for (Object result : results) {
            System.out.println(result);
        }
        System.out.println("Transaction SET: " + ((end - start) / 1000.0) + " seconds");
    }

}

============END============

秋风醉了
粉丝 253
博文 530
码字总数 404430
作品 0
朝阳
程序员
私信 提问
加载中
请先登录后再评论。

暂无文章

简单的 HTTP 调用,为什么时延这么大?

1. 背景 最近项目测试遇到个奇怪的现象,在测试环境通过 Apache HttpClient 调用后端的 HTTP 服务,平均耗时居然接近 39.2ms。可能你乍一看觉得这不是很正常吗,有什么好奇怪的?其实不然,我...

涤生-YQ
2019/07/14
0
0
SkyWalking 官方推荐教程 | 从源码剖析到实际应用

最近十年间,大数据的飞速发展,云计算、IoT 以及工业 4.0 的百花齐放,让互联网产品的竞争越演愈烈,业务架构更是变得更加复杂,对运维人员和开发人员来说,压力日渐剧增。 以前,我们用 AP...

Java公众号_Kirito的技术分享
03/13
7
0
文本挖掘的应用场景(上):管理类应用

以下文章来自知乎,作者Bill Tong。Bill Tong,上海交通大学管理科学与工程博士,曾出版《在线文本数据挖掘》一书。 基于文本挖掘的网络运营主要包括两类应用:第一种,是通过文本分析技术和...

三猫后端
02/16
7
0
TensorFlow 入门指南

介绍 让我们帮你从头开始安装并运行 TensorFlow 吧! 但在开始之前,先来看看一个最简单的使用 TensorFlow Python API 的示例代码,这样你就会对我们接下来要做的事情有所了解。 这是一个 Py...

yunwangjun
2017/02/12
11
0
快速了解UDP协议

互联网工程任务组(IETF)官员透露,HTTP-over-QUIC实验协议将重命名为HTTP/3,并有望成为HTTP协议的第三个正式版本。 Quic(QuickUDP Internet Connections)是一种新的传输方式,与TCP相比,...

全菜工程师小辉
2019/06/23
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部