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