大家好,我是散步coding, 最近在整顿2022年Redis最新面试题, 大家也能够通过我上面的博客地址在线浏览, 明天讲讲第3篇 - Redis事务。 本文首发于公众号: 散步coding

2022年Redis最新面试题目录

  • Redis基础知识
  • Redis数据结构
  • Redis事务
  • Redis数据长久化
  • Redis集群
  • Redis淘汰策略
  • Redis分布式锁
  • Redis缓存问题
  • 运维和部署

事务

  • 怎么了解 Redis 事务?
  • Redis事务执行过程
  • Redis事务的一些应用场景
  • Redis事务与Redis pipeline的区别
  • 集群模式下Redis事务如何保障原子性

怎么了解 Redis 事务?

呈现概率: ★★★★

<font color=#FF000 >Redis事务的实质是一组命令的汇合</font>。事务反对一次执行多个命令,一个事务中所有命令都会被序列化。在事务执行过程,会依照程序串行的执行队列中的命令,其余客户端提交的命令申请不会插入到事务执行命令序列中。

总结说:Redis事务就是一次性、程序性、排他性的执行一个队列中的一系列命令。

1)、Redis事务相干命令和应用

MULTI 、 EXEC 、 DISCARD 和 WATCH 是 Redis 事务相干的命令。

  • MULTI: 开启事务,redis会将后续的命令一一放入队列中,而后应用EXEC命令来原子化执行这个命令系列。
  • EXEC: 执行事务中的所有操作命令。
  • DISCARD: 勾销事务,放弃执行事务块中的所有命令。
  • WATCH: 监督一个或多个key,如果事务在执行前,这个key(或多个key)被其余命令批改,则事务被中断,不会执行事务中的任何命令。
  • UNWATCH: 勾销WATCH对所有key的监督。

example:

127.0.0.1:6379> MULTIOK127.0.0.1:6379> SET name '散步coding'QUEUED127.0.0.1:6379> SET brief '一个专一于算法、数据库、职场的公众号'QUEUED127.0.0.1:6379> GET nameQUEUED127.0.0.1:6379> EXEC1) OK2) OK3) "散步coding"

画重点, <font color=#FF000 >Redis事务不反对Rollback</font>

事实上Redis命令在事务执行时可能会失败,但仍会继续执行残余命令而不是Rollback(事务回滚)。如果你应用过关系数据库,这种状况可能会让你感到很奇怪。然而针对这种状况Redis官网也给出了解释:

Redis命令可能会执行失败,仅仅是因为谬误的语法被调用(命令排队时检测不进去的谬误),或者应用谬误的数据类型操作某个Key: 这意味着,实际上失败的命令都是编程谬误造成的,都是开发中可能被检测进去的,生产环境中不应该存在。(这番话,彻底甩锅,“都是你们本人编程谬误,与咱们无关”。)

因为不用反对Rollback,Redis外部简洁并且更加高效。

Redis事务执行过程

呈现概率: ★★★

一个Redis事务从开始到执行会经验以下三个阶段:

  • 1)开始事务。
  • 2)命令放入Queue。
  • 3)执行事务。

1)开始事务

MULTI命令的执行标记着事务的开始:

127.0.0.1:6379> MULTIOK

这个命令惟一做的就是, 将客户端的 REDIS_MULTI 选项关上, 让客户端从非事务状态切换到事务状态。

2)命令放入Queue

当客户端处于非事务状态下时, 所有发送给服务器端的命令都会立刻被服务器执行:

127.0.0.1:6379> SET name '散步coding'OK127.0.0.1:6379> GET name"散步coding"

然而, 当客户端进入事务状态之后, 服务器在收到来自客户端的命令时, 不会立刻执行命令, 而是将这些命令全副放进一个事务队列里, 而后返回QUEUED, 表示命令已入队:

 127.0.0.1:6379> MULTIOK127.0.0.1:6379> SET name "散步coding"QUEUED127.0.0.1:6379> GET nameQUEUED

3)执行事务

当客户端进入事务状态之后, 客户端发送的命令就会被放进事务队列里。

EXEC 、 DISCARD 、 MULTI 和 WATCH 这四个命令 —— 当这四个命令从客户端发送到服务器时, 它们会像客户端处于非事务状态一样, 会被服务器立刻执行。

127.0.0.1:6379> EXEC1) OK2) OK3) "散步coding"

4)、对于WATCH命令

<font color=#FF000 >WATCH指令,有点相似乐观锁</font>,事务提交时,如果 key 的值已被别的客户端扭转,比方某个 list 已被别的客户端push/pop 过了,整个事务队列都不会被执行。(当然也能够用 Redis 实现分布式锁来保障安全性,属于乐观锁)

WATCH机制的作用是,在事务执行前,监控一个或多个键的值变动状况,当事务调用EXEC命令执行时,WATCH机制会先查看监控的键是否被其它客户端批改了。如果批改了,就放弃事务执行,防止事务的隔离性被毁坏。而后,客户端能够再次执行事务,此时,如果没有并发批改事务数据的操作了,事务就能失常执行,隔离性也失去了保障。

WATCH机制的具体实现是由WATCH命令实现的,我给你举个例子,你能够看上面的图,进一步了解下WATCH命令的应用。

example:

127.0.0.1:6379>set k 1OK127.0.0.1:6379>WATCH kOK127.0.0.1:6379>set k 2OK127.0.0.1:6379>MULTIOK127.0.0.1:6379>set k 3QUEUED127.0.0.1:6379>EXEC(nil)127.0.0.1:6379>get k"2"

提交事务,<font color=#FF000 >但k值不会被批改为3,因为在事务开启之前k的值被批改了</font>。

Redis事务的一些应用场景

呈现概率: ★★★

可利用watch命令监听key,实现乐观锁,来保障不会呈现抵触,利用场景比方秒杀来避免超卖。

秒杀场景伪代码如下:

这块代码其实还没有想好, 如果有教训的敌人,欢送留言, 后续我钻研透彻会也专门写一篇秒杀场景的文章。

set total_quantity 100WATCH goods_quantityMULTIif goods_quantity < total_quantity && user_id not in 'user_list'   incr goods_quantity   set 'user_list' user_idendEXEC

Redis事务与Redis pipeline的区别

呈现概率: ★★★

<font color=#FF000 >Redis Pipeline次要用于批量发送命令,一次性发送多个申请,一次性读取所有返回后果</font>。能够节俭连贯->发送命令->返回后果这个过程所产生的工夫(RTT),缩小read()和write()的零碎调用(从用户态到内核态之间的切换)次数。

Redis事务、Redis Pipeline外表上它们能够作为批量执行命令的形式,但理论也有许多区别。

1)、命令缓冲队列形式不同
Redis事务蕴含的命令是缓冲在服务端内存队列,而Redis Pipeline则是缓冲在客户端本地内存中;

2)、申请次数不同
Redis事务中每个命令都须要发送到服务端,而<font color=#FF000 >Pipeline只须要发送一次,申请次数更少</font>;

3)、原子性保障
Redis事务能够保障命令原子化执行,而Pipeline不保障原子性。

Redis事务、Pipeline都只能作用于单个节点。集群环境下,执行Redis命令时,会依据key计算出一个槽位(slot),而后依据槽位重定向到特定的节点上执行操作。

4)、<font color=#FF000 >在应用事务时,倡议配合 Pipeline 应用</font>。

a) 如果不应用 Pipeline,客户端是先发一个 MULTI 命令到服务端,客户端收到 OK,而后客户端再发送一个个操作命令,客户端顺次收到 QUEUED,最初客户端发送 EXEC 执行整个事务(文章例子就是这样演示的),这样音讯每次都是一来一回,效率比拟低,而且在这屡次操作之间,别的客户端可能就把本来筹备批改的值给批改了,所以无奈保障隔离性。

b) 而应用 Pipeline 是一次性把所有命令打包好全副发送到服务端,服务端全副解决实现后返回。这么做好的益处,一是缩小了来回网络 IO 次数,进步操作性能。二是一次性发送所有命令到服务端,服务端在处理过程中,是不会被别的申请打断的(Redis单线程个性,此时别的申请进不来),这自身就保障了隔离性。咱们平时应用的 Redis SDK 在应用开启事务时,个别都会默认开启 Pipeline 的,能够注意察看一下。

集群模式下Redis事务如何保障原子性

呈现概率: ★★★

Redis事务中每个命令都须要发送到服务端, 不过Redis事务能够保障命令原子化执行

Redis事务只能作用于单个节点。集群环境下,执行Redis命令时,会依据key计算出一个槽位(slot),而后依据槽位重定向到特定的节点上执行操作。

也欢送关注我的公众号: 散步coding。一起交换, 在coding的世界里散步, 回复: redis, 收费获取最新Redis面试题(含答案)。