zoukankan      html  css  js  c++  java
  • Redis 中的事务

    Redis支持简单的事务


    Redis与mysql事务的对比



    Mysql

    Redis

    开启

    start transaction

    muitl

    语句

    普通sql

    普通命令

    失败

    rollback 回滚

    discard 取消

    成功

    commit

    exec


    : rollback与discard 的区别

    • 如果已经成功执行了2条语句, 第3条语句出错.
    • Rollback后,前2条的语句影响消失.
    • Discard只是结束本次事务,前2条语句造成的影响仍然还在


    :

    mutil后面的语句中, 语句出错可能有2种情况

    1.  语法就有问题,

    这种,exec时,报错, 所有语句得不到执行

            2.   语法本身没错,但适用对象有问题. 比如zadd 操作list对象

    Exec之后,会执行正确的语句,并跳过有不适当的语句.

    (如果zadd操作list这种事怎么避免? 这一点,由程序员负责)    需要程序员手动控制操作



    思考:

    我正在买票

    Ticket -1 , money -100

    而票只有1张, 如果在我multi之后,和exec之前, 票被别人买了---即ticket变成0了.

    该如何观察这种情景,并不再提交


    悲观的想法:

    世界充满危险,肯定有人和我抢, 给ticket上锁, 只有我能操作. [悲观锁]


    乐观的想法:

    没有那么人和我抢,因此,我只需要注意,

    --有没有人更改ticket的值就可以了[乐观锁]


    Redis的事务中,启用的是乐观锁,只负责监测key没有被改动.


    具体的命令---- watch命令

    :

    redis 127.0.0.1:6379> watch ticket
    OK
    redis 127.0.0.1:6379> multi
    OK
    redis 127.0.0.1:6379> decr ticket
    QUEUED
    redis 127.0.0.1:6379> decrby money 100
    QUEUED
    redis 127.0.0.1:6379> exec
    (nil) // 返回nil,说明监视的ticket已经改变了,事务就取消了.
    redis 127.0.0.1:6379> get ticket
    "0"
    redis 127.0.0.1:6379> get money
    "200"


    watch key1 key2 ... keyN

    作用:监听key1 key2..keyN有没有变化,如果有变, 则事务取消


    unwatch

    作用: 取消所有watch监听

     

    下面的内容转载自http://haili.me/archives/439.html

     

     

    先介绍下与Redis的Transaction(事务)相关的几个命令:
    WATCH 监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断;
    UNWATCH 取消 WATCH 命令对所有 key 的监视;
    MULTI 标记一个事务块的开始,指事务块内的多条命令会按照先后顺序被放进一个队列当中,最后由EXEC命令原子性(atomic)地执行;
    DISCARD 取消事务,放弃执行事务块内的所有命令;
    EXEC 执行所有事务块内的命令;

     

     

    redis> MULTI
    OK
    redis> INCR user_id
    QUEUED
    redis> INCR user_id
    QUEUED
    redis> INCR user_id
    QUEUED
    redis> PING
    QUEUED
    redis> EXEC
    1) (integer) 1
    2) (integer) 2
    3) (integer) 3
    4) PONG

     

    phpredis也对该方法做了实现。

    事务的调用有两种模式

    Redis::MULTI

    Redis::PIPELINE

    默认是Redis::MULTI模式,Redis::PIPELINE管道模式速度更快,但没有任何保证原子性有可能造成数据的丢失。
    Redis管道PHP测试示例:

    <?php
    $redis = new Redis();
    $redis->connect('127.0.0.1', 6379);
    $startTime = microtimeFloat();
    
    $pipe = $redis->multi(Redis::PIPELINE);
    for($i = 0; $i < 100000; $i++){
        $pipe->set("key::$i", time());
        $pipe->get("key::$i");
    }
    $pipe->exec();
    
    //$redis->flushDB();
    $endTime = microtimeFloat();
    $runTime = $endTime - $startTime;
    echo "用时 $runTime 秒";
    
    function microtimeFloat(){
        list($usec, $sec) = explode(" ", microtime());
        return ((float)$usec + (float)$sec);
    }
    ?>

     

     

     

     

     

     

  • 相关阅读:
    梦断代码阅读笔记之一
    你的灯亮着吗阅读笔记之三
    第二次冲刺第八天
    第二次冲刺第七天
    价格计算
    第二次冲刺第六天
    构建之法阅读笔记06
    第二阶段冲刺第五天
    第二阶段冲刺第四天
    第二阶段冲刺第三天
  • 原文地址:https://www.cnblogs.com/timelesszhuang/p/4376141.html
Copyright © 2011-2022 走看看