Redis支持簡單的事務php
Redis與mysql事務的對比html
|
Mysqlmysql |
Redis程序員 |
開啓redis |
start transactionsql |
muitlide |
語句測試 |
普通sqlui |
普通命令atom |
失敗 |
rollback 回滾 |
discard 取消 |
成功 |
commit |
exec |
注: rollback與discard 的區別
注:
在mutil後面的語句中, 語句出錯可能有2種狀況
這種,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); } ?>