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事务详解(五)总结提高 一.概念 ...
随机推荐
- angularJS自定义那些事
angularJS在数据处理方面很优秀. 使用angularJ给我感觉就像在写模板,然后对模板填入内容,只是这些内容不在是 在html页面编写,而是以数据的方式添加进去,这个也大大提高了编写的效率. ...
- 编写Shader时的一些性能考虑
编写shader时的一些建议:1.只计算需要计算的东西:2.通常,需要渲染的像素比顶点数多,而顶点数又比物体数多很多.所以如果可以,尽量将运算从PS移到VS,或直接通过script来设置某些固定值:3 ...
- javascript类型系统——包装对象
× 目录 [1]定义 [2]生存期 [3]显式创建[4]转型函数[5]比较运算 前面的话 javascript对象是一种复合值,它是属性或已命名值的集合.通过'.'符号来引用属性值.当属性值是一个函数 ...
- java中多线程模拟(多生产,多消费,Lock实现同步锁,替代synchronized同步代码块)
import java.util.concurrent.locks.*; class DuckMsg{ int size;//烤鸭的大小 String id;//烤鸭的厂家和标号 DuckMsg(){ ...
- Android自动连接指定的wifi,免密码或指定密码
一.运行时的状态 遇到一个这样的要求:“不进行扫描操作,怎么对指定的免密码WIFI进行连接(之前没有连接过)”,于是动手写了一个Demo,如图所示未连接成功时的状态,第一个编辑框让用户输入SSID,第 ...
- Cordova webapp实战开发:(1)为什么选择 Cordova webapp?
很长时间没有专注写代码了,即使写点代码也主要是写写敏捷个人app,这个App主体内容是我用了一周的时间,使用PhoneGap+JQueryMobile搭建的,之所以会比较快的完成,是因为11年我在做建 ...
- 自制简单实用IoC
IoC是个好东西,但是为了这个功能而使用类似 Castle 这种大型框架的话,感觉还是不大好 代码是之前写的,一直没详细搞,今天整理了一下,感觉挺实用的. IoC定义接口: using System; ...
- 在SQL Server 2016里使用查询存储进行性能调优
作为一个DBA,排除SQL Server问题是我们的职责之一,每个月都有很多人给我们带来各种不能解释却要解决的性能问题. 我就多次听到,以前的SQL Server的性能问题都还好且在正常范围内,但现在 ...
- 基于HT for Web 3D技术快速搭建设备面板
以真实设备为模型,搭建出设备面板,并实时获取设备运行参数,显示在设备面板上,这相比于纯数值的设备监控系统显得更加生动直观.今天我们就在HT for Web的3D技术上完成设备面板的搭建. 我们今天模拟 ...
- 阅读《LEARNING HARD C#学习笔记》知识点总结与摘要四
又是一个周末,刚好有时间,又继续复习与总结了,希望能让大家受益,不足之处欢迎指正,谢谢! 十八. Lambda 1.Lambda表达式:匿名方法的另一种表现形式,它可以包含表达式和语句,且用于创建委托 ...