zoukankan      html  css  js  c++  java
  • Redis(3)---Redis事务

    Redis事务

    Redis 通过 MULTIEXECDISCARD  和 WATCH 四个命令来实现事务功能。

            MULTI :标记一个事务块的开始。

             EXEC: 执行所有事务块内的命令。

     DISCARD :取消事务,放弃执行事务块内的所有命令。

    WATCH key [key ...] :监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断。

    一、事务

       1、是什么?

         可以一次执行多个命令,本质是一组命令的集合。一个事务中的所有命令都会序列化,不许加塞!

       2、能干什么?

         一个队列中,一次性的、顺序性的、排他性的执行一系列的命令。要么一起成功,要么一起失败。排好队,一次性的执行多个redis的命令!

       3、怎么玩?

       通过MULTI指令开启,之后输入多个命令!Redis将它们加入到队列当中,所有的命令通过EXEC来开启执行!通过DISCARD来放弃本次的批处理操作!

     (1)正常执行(好比购物先加入购物车,最后EXEC统一结账。)

    192.168.1.66:6379> MULTI    --开启事务
    OK
    192.168.1.66:6379> set k1 v1
    QUEUED
    192.168.1.66:6379> set k2 v2
    QUEUED
    192.168.1.66:6379> set k3 v3
    QUEUED
    192.168.1.66:6379> set k4 v4
    QUEUED
    192.168.1.66:6379> get k2
    QUEUED
    192.168.1.66:6379> EXEC  --结束事务
    1) OK
    2) OK
    3) OK
    4) OK
    5) "v2"

      (2)DISCARD 撤销所有操作!

    192.168.1.66:6379> MULTI
    OK
    192.168.1.66:6379> set k1 11
    QUEUED
    192.168.1.66:6379> set k2 22
    QUEUED
    192.168.1.66:6379> set k3 33
    QUEUED
    192.168.1.66:6379> DISCARD
    OK
    192.168.1.66:6379> get k1  --这里的k1的value值还是上面的值,而不是新设置的value值
    "v1"    

      (3)加入队列时不出错,下面的都将正常运行,执行时出错不影响其他语句!

    192.168.1.66:6379> set k1 v1
    OK
    192.168.1.66:6379> set k2 v2
    OK
    192.168.1.66:6379> MULTI
    OK
    192.168.1.66:6379> incr k1
    QUEUED
    192.168.1.66:6379> set k2 22
    QUEUED
    192.168.1.66:6379> EXEC
    1) (error) ERR value is not an integer or out of range --在运行是才发现k1不是数字,报错
    2) OK     --执行成功

    注意:
       (1)当遇到执行错误时,redis放过这种错误,保证事务执行完成。(所以说redis的事务并不是保证原子性
       (2)与mysql中事务不同,在redis事务遇到执行错误的时候,不会进行回滚,而是简单的放过了,并保证其他的命令正常执行。这个区别在实现业务的时候,需要自己保证逻辑符合预期。
       (3)当事务的执行过程中,如果redis意外的挂了。很遗憾只有部分命令执行了,后面的也就被丢弃了。当然如果我们使用的append-only file方式持久化,redis会用单个write操作写入整个事务内容。即是是这种方式还是有可能只部分写入了事务到磁盘。发生部分写入事务的情况 下,redis重启时会检测到这种情况,然后失败退出。可以使用redis-check-aof工具进行修复,修复会删除部分写入的事务内容。修复完后就 能够重新启动了。

    二、WATCH

           WATCH 命令可以为 Redis 事务提供 check-and-set (CAS)行为。

           被 WATCH 的键会被监视,并会发觉这些键是否被改动过了。 如果有至少一个被监视的键在 EXEC 执行之前被修改了, 那么整个事务都会被取消, EXEC 返回空多条批量回复(null multi-bulk reply)来表示事务已经失败。

    1、首先我们不加WATCH进行事务处理

    时间

    客户端 A

    客户端 B

    说明

    T1

    SET name aa

    SET age  10

    GET name

    aa

    GET age

    10

    数据库中两客户端登录,及键初始值。

    它们是同步的。

    T2

    MULTI

    SET name bb

    Incr age

     

    此时,客户端1开启事务,并提交队列命令:

    1.想要将当前age自增+1运算;

    2.将name值改为bb

    T3

     

    SET name cc

    Incr age

    此时,客户端2修改了age值

    同时修改name值为cc

    T4

    EXEC

     

     

    T5

    GET name

    bb

    GET age

    12

    此时,客户端1执行队列命令,发现运算之后age不是理想中的11,而是12原因是被其它客户插足抢先给修改了。name值确实是没有被其它所改变。这样可能导致数据不一致性。

     

     

     

     

    2、添加WARCH

    客户端1-引入“乐观锁”机制 客户端2 说明
     SET age
    "10"
     SET name
    "zhangsan"

     GET age
    "10"
     GET name
    "zhangsan"
    数据库中两客户端登录,及键初始值。
     WATCH    age name
    OK
     MUTLI
    OK
     incr age
    QUEUED
     set name lisi
    QUEUED
      此时,客户端1用watch命令监视age和name,然后开启事务,并提交队列命令
       incr age
    (integer) 11
    此时,客户端2修改了age值

     exec
    (nil)
     get age
    "11"
     get name
    "zhangsan"
      此时,客户端1执行队列命令,由watch监控发现此期间age的值已经被修改过,则让事整个务回滚,不做任何动作。

    watch可以同时监控多个键,在监控期间只要有一个键被其它客户端改变,则整个事务回滚。

    想太多,做太少,中间的落差就是烦恼。想没有烦恼,要么别想,要么多做。少校【1】

  • 相关阅读:
    最新屏蔽微信举报方法
    C# WIN 生成机器码
    Quartz.net的快速简单上手使用以及防止IIS回收停止Job的处理
    MVC、Web API 请求接口报错“自定义错误模块不能识别此错误。”解决
    获取微信短链接的官方接口
    Window 通过cmd查看端口占用、相应进程、杀死进程
    微信域名检测、防封,微信跳转技术揭秘(二) -- 微信跳转揭秘
    微信域名检测、防封,微信跳转技术揭秘(一) -- 域名检测原理及防封方案
    各种比较方便给力的小工具
    《Git学习指南》学习笔记(三)
  • 原文地址:https://www.cnblogs.com/qdhxhz/p/9135684.html
Copyright © 2011-2022 走看看