redis事务详解
mysql中也存在事务的概念。其实事务的定义是一样的。一组操作的集合,作为一个整体,要么全执行,要么全不执行。
redis设置事务三步骤:
- 开始事务 :multi
- 操作加入事务队列
- 执行事务 :exec
事务意味着 两个意思
- 事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断,这个很重要。
- 事务是一个原子操作:事务中的命令要么全部被执行,要么全部都不执行。
事务的好处就是可以保证 一组操有顺序执行,这个过程中不会插入其他操作。例如抽奖防止抽超过库存这一问题,当抽奖得到某一个奖品时,会先去取库存,看是不是大于0,如果大于0,我们再去把库存减一,然后返回。那么如何保证从取出库存到库存减一的这个过程中不插入其他操作呢。事务这个时候就能解决。(当然decr也能解决,而且更好)
用php模拟实现这个动作
$con->multi();
$a = $con->get('a');
$con->set('a',$a+1);
$con->get('a');
$res = $con->exec();
var_dump($res);
这个事务理论上能实现这个操作,但是实际上不会的。由于加入事务队列的操作不会立即执行,所以依赖于上一步的结果而进行的操作会有问题。
a 的值是3,返回如下:
$res = array(3) {
[0]=>
string(1) "3"
[1]=>
bool(true)
[2]=>
string(1) "2"
}
事务中的$a 并没有获得返回,得到了一个object,下次计算当成数字1计算,所以最后永远返回2
所以我们看到,当事务中的操作存在依赖关系时,完全使用事务并不合适。当然,在不存在依赖关系的用这个事务步骤十分可行。如关注和被关注两个操作。
关注发生时,follow(a,b),follow(b,a)这两个 放到一个事务中。
那么如果事务中出现依赖关系怎么办呢?就是上一个问题怎么解决呢?这个请出事务系列的另一个方法watch
watch 的作用是监控一个或者多个键,监控之后,到事务开始这段时间内,若有一个及以上的键值发生了改变或删除(改变可能发生了多次,可能是不同的客户端进行的修改),事务不会执行。
加入事务队列的操作无法立即获取返回结果,所以依赖上一步结果进行下一步操作这样的事务是无法进行的,因为上一步的结果无法在实务中立即获取。
解决方法是 在事务开始前获取结果,然后监控这个key,再开始事务。
如果要想实现整个操作,还是要重新执行整个过程。
对于高并发,这么做并不合适,在watch值之后到multi开始这段时间内,很容易发生变化,导致不执行。
$con->watch('a');
$a = $con->get('a');
$con->multi();
$con->set('a',$a+1);
$con->get('a');
$res = $con->exec();
var_dump($res)
这个能返回想要的结果,最开始服务器中a =>1
array(2) {
[0]=>
bool(true)
[1]=>
string(1) "2"
}
获得了 +1 之后的结果。
$a = $con->get('a');
$con->multi();
这两步之间,若其他的客户端对a进行了改动,那么后面的事务不会执行的。如果想我们的事务执行,上面的那段代码必须重复执行,直到exec动作执行
<?php
class RedisTest{
private $redis_host = '192.168.211.129';
private $redis_port = '6379';
private $redis_timeout = '5';
private $redis_auth = 'foobared'; private $con; public function __construct(){
$this->con = new Redis();
$this->con->connect($this->redis_host,$this->redis_port,$this->redis_port);
$this->con->auth($this->redis_auth);
} /*
* 模拟实现初始化某个值的动作。不存在是赋值,存在则不做改变
*/
public function setXX($key,$val){
$this->con->watch($key);
$res = $this->con->get($key);
if($res === false){
$this->con->multi();
$this->con->set($key,$val);
$this->con->get($key);
$restult = $this->con->exec();
}else{
$restult = $res;
$this->con->unwatch();//watch监控的key只有在exec执行完才释放,所以unwatch取消监控
}
return $restult;
} //模拟实现redis的incr操作
public function incr($key){
$this->con->watch($key);
$val = $this->con->get($key);
$this->con->multi();
$this->con->set($key,$val+1);
$this->con->get($key);
$res = $this->con->exec();
if(empty($res)){
$this->incr($key);//如果exec没有执行,则这个动作不停执行,知道执行为止。在并发高的系统中,这个并不合适
}
return $res;
}
public function __destruct(){
$this->con->close();
} } class Client{
public function main(){
$obj = new RedisTest();
$res = $obj->setXX('a', 10);
$res = $obj->incr('a');
var_dump($res);
} } $obj = new Client();
$obj->main();
redis事务详解的更多相关文章
- 【Redis】Redis事务详解,Redis事务支持回滚(不支持悲观锁)
1.redis事物参考:https://baijiahao.baidu.com/s?id=1613631210471699441&wfr=spider&for=pc (php操作red ...
- 5种Redis数据结构详解
本文主要和大家分享 5种Redis数据结构详解,希望文中的案例和代码,能帮助到大家. 转载链接:https://www.php.cn/php-weizijiaocheng-388126.html 2. ...
- redis配置详解
##redis配置详解 # Redis configuration file example. # # Note that in order to read the configuration fil ...
- PHP mysql与mysqli事务详解
官方对PHP连接到MySQL数据库服务器的三种主要的API简介如下: http://php.net/manual/zh/mysqli.overview.php PHP mysql与mysqli事务详解 ...
- CentOS7/RHEL7安装Redis步骤详解
CentOS7/RHEL7安装Redis步骤详解 CentOS7/RHEL7安装Redis还是头一次测试安装了,因为centos7升级之后与centos6有比较大的区别了,下面我们就一起来看看Cent ...
- Redis协议详解
smark Beetle可靠.高性能的.Net Socket Tcp通讯组件 支持flash amf3,protobuf,Silverlight,windows phone Redis协议详解 由于前 ...
- Java的JDBC事务详解
Java的JDBC事务详解 分类: Hibernate 2010-06-02 10:04 12298人阅读 评论(9) ...
- Redis学习——详解Redis配置文件(三)
一.Redis脚本简介 在我们介绍Redis的配置文件之前,我们先来说一下Redis安装完成后生成的几个可执行文件: redis-server .redis-cli .redis-benchmark ...
- spring事务详解(五)总结提高
系列目录 spring事务详解(一)初探事务 spring事务详解(二)简单样例 spring事务详解(三)源码详解 spring事务详解(四)测试验证 spring事务详解(五)总结提高 一.概念 ...
随机推荐
- Markdown快速入门
现在博文写作次数渐渐变多,经常看到很多园友的博文样式都非常的美观,个人虽然是个土鳖,但对美也是有很强需求的,同时由于最近将要上线一个博客项目,因此也很关心如何可以更高效的编辑和发布博文.之前一直使用w ...
- 再谈collections模块defaultdict()和namedtuple()
defaultdict()和namedtuple()是collections模块里面2个很实用的扩展类型.一个继承自dict系统内置类型,一个继承自tuple系统内置类型.在扩展的同时都添加了额外的很 ...
- Android_文件存储
因为项目的需求,想实现一个指导使用的欢迎页效果,通过在网上的询问,给的一种解决办法是通过SharedPreferences文件存储方式来实现,具体的实现类似于通过第一次取得SharedPreferen ...
- Uvaoj 10048 - Audiophobia(Floyd算法变形)
1 /* 题目大意: 从一个点到达另一个点有多条路径,求这多条路经中最大噪音值的最小值! . 思路:最多有100个点,然后又是多次查询,想都不用想,Floyd算法走起! */ #include< ...
- Shader 简明入门教程
Unity3D的所有渲染工作都离不开着色器(Shader),如果你和我一样最近开始对Shader编程比较感兴趣的话,可能你和我有着同样的困惑:如何开始?Unity3D提供了一些Shader的手册和文档 ...
- 如何在windows 10 x64安装佳能 CP900 驱动
佳能太无耻,为了销售CP910 , CP900 到win8 ,win8.1,win 10 都没有驱动程序,网上找的方法都不行,IT民工自有办法: 1.按住shift键,重启电脑 restart 2.在 ...
- 百度地图JavaScript API自定义覆盖物、自定义信息窗口增删时的显示问题
项目中,需求:在百度地图上实时画出车辆,并能点击车辆弹出信息框查看实时信息. 实现:通过不停的画覆盖物并删除掉.点击覆盖物时弹出信息窗口. 问题:删除掉覆盖物后信息窗也删除掉了.因为信息窗是建立在覆盖 ...
- TFS简介
Team Foundation Server(TFS)是一种为 Microsoft 产品提供 源代码管理.数据收集.报告和项目跟踪,而为协作软件开发的项目.可作为独立的软件,或 Visual Stud ...
- Spark入门实战系列--7.Spark Streaming(下)--实时流计算Spark Streaming实战
[注]该系列文章以及使用到安装包/测试数据 可以在<倾情大奉送--Spark入门实战系列>获取 .实例演示 1.1 流数据模拟器 1.1.1 流数据说明 在实例演示中模拟实际情况,需要源源 ...
- 如何删除回滚段状态为NEEDS RECOVERY的undo表空间
环境:RHEL 6.4 + Oracle 11.2.0.4 背景:备份恢复的测试库在一次不完全恢复后,没有来及做有效的全备,又一次数据库故障导致数据库无法正常open. 只能离线部分数据文件打开数据库 ...