Redis:17---常用功能之(事务)

  • 为了保证多条命令组合的原子性,Redis提供了简单的事务功能以及集成Lua脚本来解决这个问题,本文介绍Redis事务,Lua在下一篇文章介绍

一、事务概述

  • 简单地说,事务表示一组动作,要么全部执行,要么全部不执行。例如在社交网站上用户A关注了用户B,那么需要在用户A的关注表中加入用户B,并且在用户B的粉丝表中添加用户A,这两个行为要么全部执行,要么全部不执行,否则会出现数据不一致的情况

  • Redis只提供了四个命令管理事务:

    • MULTI:用来开启一个事务。开启一个事务之后,输入的命令不会被立即执行,而是进入事务队列中(入队),所以可以看见输入命令的结果显示为“QUEUED”

    • WATCH:是一个乐观锁。它可以在EXEC命令执行之前,监视任意数量的数据库键,并在EXEC命令执行时,检查被监视的键是否至少有一个已经被修改过了,如果是的话,服务器将拒绝执行事务,并向客户端返回代表事务执行失败的空回复

    • DISCARD:用于取消本次事务,放弃执行事务块内的所有命令。如果使用了WATCH,DISCARD将取消监视连接监视的所有键

    • EXEC:提交一个事务

  • 所以Redis的事务比较简单,主要是因为它不支持事务中的回滚特性,同时无法实现命令之间的逻辑关系计算,当然也体现了Redis的“keep it simple”的特性

二、事务演示案例

MULTI+EXEC

  • 下面使用MULTI开启一个事务,并且执行相关操作,最后使用EXEC提交执行事务内的操作

  • 备注:可以看到事务开启之后,每次执行的命令结果都会显示QUEUED,表示命令入队,但是没有被执行

MULTI+DISCARD

  • 下面使用MULTI开启一个事务,并且执行相关操作,最后使用DISCARD终止本次事务,并且事务内的操作全部放弃执行

  • 备注:因为discard已经结束事务了,所以再次输入exec会显示没有匹配的multi

MULTI+WATCH+EXEC

  • 客户端1:先设置一个字符串,键名为key,然后使用watch监听该键。然后开启事务

  • 客户端2:在客户端1事务还未结束的时候,修改key

  • 客户端1:操作key,并提交事务。因为key被其他客户端修改,所以EXEC返回nil,事务没有被执行。然后获取key,key没有被改变

三、事务错误的处理

  • 如果事务中出现错误,那么Reiis的处理机制也不尽相同

①命令错误

  • 如果一个事务在入队命令的过程中,出现了命令不存在,或者命令的格式不正确等情况,那么Redis将拒绝执行这个事务

  • 例如:下面操作错将set写成了sett,属于语法错误,会造成整个事务无法执行,key和counter的值未发生变化:

       根据文档记录,在Redis 2.6.5以前的版本,即使有命令在入队过程中发生了错误, 事务一样可以执行,不过被执行的命令只包括那些正确入队的命令,以下这段代码是 在Redis 2.6.4版本上测试的,可以看到事务可以正常执行,但只有成功入队的SET命令 和GET命令被执行了,而错误的YAH000O则被忽略了:

redis> MULTI
OK
redis> SET msg "hello"
QUEUED
redis> YAH000O
(error) ERR unknown command ' YAH000O'
redis> GET msg
QUEUED
redis> EXEC
11 OK
2) "hello"

②运行时错误(执行错误)

  • 有些事务输入的命令没有错误,但是语法或逻辑有错误,这类错误不会被立即检测出来,只有当事务提交时才会被检测出来

  • 即使在事务的执行过程中发生了错误,服务器也不会中断事务的执行,它会继续执行事务中余下的其他命令,并且已执行的命令(包括执行命令所产生的结果)不会被出错的命令影响

  • 因为在事务执行的过程中,出错的命令会被服务器识别出来,并进行相应的错误处理, 所以这些出错命令不会对数据库做任何修改,也不会对事务的一致性产生任何影响

③服务器停机

  • 如果Redis服务器在执行事务的过程中停机,那么根据服务器所使用的持久化模式,可能有以下情况出现:

    • 如果服务器运行在无持久化的内存模式下,那么重启之后的数据库将是空白的,因此数据总是一致的

    • 如果服务器运行在RDB模式下,那么在事务中途停机不会导致不一致性,因为服务器可以根据现有的RDB文件来恢复数据,从而将数据库还原到一个一致的状态。如果找不到可供使用的RDB文件,那么重启之后的数据库将是空白的,而空白数据库总是一致的

    • 如果服务器运行在AOF模式下,那么在事务中途停机不会导致不一致性,因为服务器可以根据现有的AOF文件来恢复数据,从而将数据库还原到一个一致的状态。如果找不到可供使用的AOF文件,那么重启之后的数据库将是空白的,而空白数据库总是一致的

  • 综上所述,无论Redis服务器运行在哪种持久化模式下,事务执行中途发生的停机都不会影响数据库的一致性

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/444315.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Redis:12---有序集合对象

一、有序集合对象概述它保留了集合不能有重复成员的特性, 但不同的是,有序集合中的元素可以排序。但是它和列表使用索引下标作为排序依据不同的是,它给每个元素设置一个分数(score)作为排序的依据如下图所示&#xff0…

Redis:11---Set对象

集合类型 (Set) 是一个无序并唯一的键值集合。它的存储顺序不会按照插入的先后顺序进行存储。 集合类型和列表类型的区别如下: 列表可以存储重复元素,集合只能存储非重复元素;列表是按照元素的先后顺序存储元素的,而集合则是无序方式存储元素的。一、集合对象概述 特点:集…

Redis:13--常用功能之redis-cli redis-server等命令

Redis提供了redis-cli、redis-server、redis-benchmark等Shell工具。它们 虽然比较简单,但是麻雀虽小五脏俱全,有时可以很巧妙地解决一些问题一、redis-cli在前面数据库连接的时候已经redis-cli的-h、-p参数,除了这些参数,还有很多…

Redis:21---客户端相关配置篇

一、客户端相关配置①客户端的限制maxclientsRedis提供了maxclients参数来限制最大客户端连接数,一旦连接数超过 maxclients,新的连接将被拒绝maxclients默认值是10000可以通过info clients来查询当前Redis的连接数:可以通过config set maxcl…

Redis:23---info命令总结

info命令的格式有3种:info:部分Redis系统状态统计信息info all:全部Redis系统状态统计信息,一次性打印下面所有p的内容info p:某一块的系统状态统计信息。info命令所有的p如下所示模块名模块含义 Server服务器信息Clie…

Redis:22---客户端API:client、monitor)

一、client listclient list命令能列出与Redis服务端相连的所有客户端连接信息。例如下面代码是在一个Redis实例上执行client list的结果,其中每一行代表一个客户端信息:下面将选择几个重要的属性进行说明,其余通过表格的形式进行展示①标识&…

Redis:20---常用功能之(发布与订阅)

一、发布与订阅概述Redis提供了基于“发布/订阅”模式的消息机制,此种模式下,消息发布者和订阅者不进行直接通信,发布者客户端向指定的频道(channel)发布消息,订阅该频道的每个客户端都可以收到该消息。 下…

Redis:19---常用功能之(HyperLogLog)

一、HyperLogLog概述HyperLogLog并不是一种新的数据结构(实际类型为字符串类型),而是一种基数算法,通过HyperLogLog可以利用极小的内存空间完成独立总数的统计,数据集可以是IP、Email、ID等HyperLogLog提供了3个命令&a…

UNIX(多线程):13---condition_variable、wait、notify_one、notify_all

条件变量std::condition_variable、wait()、notify_one() 线程A: 等待一个条件满足线程B: 专门往消息队列中放入消息(数据),达到一定条件,通知处于等待中的线程A。std::condition_variable实际上是一个类,是一个和条件相关的一个类,说白了就是等待一个条件达成。这个类是…

UNIX(多线程):27---多线程并发之原子操作与无锁编程

原子操作:顾名思义就是不可分割的操作,该操作只存在未开始和已完成两种状态,不存在中间状态; 原子类型:原子库中定义的数据类型,对这些类型的所有操作都是原子的,包括通过原子类模板std::atomic< T >实例化的数据类型,也都是支持原子操作的。 二、如何使用原子类…

UNIX(进程间通信):01---Linux进程通信方式

Linux下的进程通信手段基本上是从Unix平台上的进程通信手段继承而来的。而对Unix发展做出重大贡献的两大主力AT&T的贝尔实验室及BSD(加州大学伯克利分校的伯克利软件发布中心)在进程间通信方面的侧重点有所不同。前者对Unix早期的进程间通信手段进行了系统的改进和扩充,…

UNIX(进程间通信):02---父子进程之间的数据共享分析

之前我们通过fork()函数,得知了父子进程之间的存在着代码的拷贝,且父子进程都相互独立执行,那么父子进程是否共享同一段数据,即是否存在着数据共享。接下来我们就来分析分析父子进程是否存在着数据共享。 我们都知道,在linux下,内存存储的位置是全局变量,栈区,堆区,以…

UNIX(进程间通信):04---孤儿进程

上一篇文章讲过僵尸进程,这里再分享给大家另外一种状态。 孤儿进程 什么是孤儿进程?当一个子进程还在执行时,它的父进程已经退出了,那么这个子进程的退出信息也没有被父进程接收到,如果子进程的退出信息没有被别的进程接收到,那么这个子进程就会变成一个僵尸进程,所…

UNIX(进程间通信):16深入理解Socket

socket又叫套接字或者插口,它也是进程间通信的一种方式,实际上就是网络上的通信节点,应用程序只需要链接到socket就可以和网络上任何一个通信端点连接、传送数据。socket封装了通信的细节,我们可以不必关心通信协议内容而专注于应用程序开发。根据数据传送方式,socket分为…

苹果支付:如何解决沙盒环境下获取可恢复购买项为空

在传统手游开发中免不了和苹果支付打交道,而且苹果也会有各种奇奇怪怪的问题和BUG 。 曾经有一次某一个游戏出现了调单问题,现象如下(我有点懒,不想画泳道图或者时序图): 客户端拉起支付付款成功,OC底层收到支付成功回调->发送支付成功的收据到服务器验…

游戏服务器架构:如何设计开发战斗系统的技能和buff系统

战斗系统中buff和skill如何配合 在网络游戏中的战斗形式多种多样,不同游戏的战斗逻辑也有很大的差异。但是一般都会涉及技能系统和buff系统,两种之间相互关联,技能可以产生buff作用在目标上,影响目标。同时buff也会影响技能的释放效果,两者都可以算得上游戏战斗系统最重要…

一文彻底搞懂静态库和动态库,显示链接和隐式链接

定义&#xff1a;运行时库 静态库 动态库运行时库&#xff1a;Unix中一个典型的运行时库例子就是libc&#xff0c;它包含标准的C函数&#xff0c;如&#xff0c;print()&#xff0c;exit()等等&#xff0c;用户能创建他们自己的运行库&#xff08;在Windows中是DLL&#xff09;…

mysql的cpu高定位

导致数据库CPU很高的原因有很多种,一般和慢SQL也有关(因为每条SQL要么占CPU高,要么占IO高,大体是这样)。 (1)、如果服务器有多个mysql实例,需要通过top命令看看是哪个mysql实例导致的cpu高(如果不是mysql导致的cpu高,需要优化其他导致cpu的程序): (2)、定位到占用…

游戏服务器架构-设计模式之发布订阅模式

发布订阅模式场景 熟悉消息中间件的同学应该对发布/订阅模式(Publish Subscribe Pattern)并不陌生。即使你不了解消息中间件,那么在平时生活中发布/订阅模式也是非常常见的场景。 比如你打开你的微信订阅号,你订阅的作者发布的文章,会广播给每个订阅者。在这个场景里,微信公…

聊一下CPU占用高的解决方案

前言: 在软件开发和性能测试中,CPU占用率是服务器开发一个很重要的指标,到底有哪些因素会导致CPU占 用率上升呢?又有哪些手段可以降低CPU的占用率呢? 如果你看了这篇文章后仍然没有解决项目问题的思路,请在下方留言或公众号后台留言。(后续我将更新一到两篇…