Redis 中的事務

Redis支持簡單的事務php

 

Redis與mysql事務的對比html

 

 

Mysqlmysql

Redis程序員

開啓redis

start transactionsql

muitlide

語句測試

普通sqlui

普通命令atom

失敗

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);
}
?>

 

 

 

 

 

 

 

沒有平白無故的榮耀 
相關文章
相關標籤/搜索