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事务详解(五)总结提高 一.概念 ...
随机推荐
- Cocos2d-x 3.X手游开发实例详解
Cocos2d-x 3.X手游开发实例详解(最新最简Cocos2d-x手机游戏开发学习方法,以热门游戏2048.卡牌为例,完整再现手游的开发过程,实例丰富,代码完备,Cocos2d-x作者之一林顺和泰 ...
- ViewPager 的页面重置问题
当我们使用ViewPager控件时,假设我们的ViewPager有三页,当我们第一次启动ViewPager显示第一页的时候,ViewPager会预加载第二页,这样当我们向第二页滑动的时候就可以看见第二 ...
- Liferay7 BPM门户开发之37: Liferay7下的OSGi Hook集成开发
hook开发是Liferay客制扩展的一种方式,比插件灵活,即可以扩展liferay门户,也能对原有特性进行更改,Liferay有许多内置的服务,比如用hook甚至可以覆盖Liferay服务. 可作为 ...
- XML学习笔记6——XPath语言
在上一篇笔记的结尾,我们接触到了两个用于选择XML文档中特定范围的元素<selector>和<field>,这两个元素的取值都是XPath表达式,那么,什么是XPath呢?简单 ...
- 查看Wait type
Wait 能够指示系统存在的bottlenect 或 hot spot,再通过这些wait反馈的信息,对系统hardwar进行升级或对query 进行性能优化. 一,查看 Wait 统计信息 1,sy ...
- ValidationSummary控件不弹出错误提示框
采用VS2013 编写的前台,运用ValidationSummary控件时,不出现错误弹窗,网上找到了解决方法 发现是ASP.NET 4.5对验证控件的影响(兼容性),使用ASP.NET 4.5的解决 ...
- Android入门(十六)调用摄像头相册
原文链接:http://www.orlion.ga/665/ 一.调用摄像头 创建一个项目ChoosePicDemo,修改activity_main.xml: <LinearLayout xml ...
- python类定义与c#的一些区别
c#中可以定义一个空类,但是python中定义空类需要加pass class EmptyClass(object): pass python的lei是多继承 python子类继承了基类,如果子类也 ...
- redis session共享中的序列化问题
今天在做session对象存入redis(set方法)时,碰到一个空指针异常,代码如下: public class CheckAccount extends HttpServlet { public ...
- 轻松自动化---selenium-webdriver(python) (六)
本节知识点: 操作对象: · click 点击对象 · send_keys 在对象上模拟按键输入 · clear 清除对象的内容,如果可以的话 WebElement 另一些常用方法: · text ...