《Redis设计与实现》学习笔记-发布与订阅、事务、慢查询日志

简介:

发布与订阅

Redis通过发布订阅提供一对多甚至是多对多的节点消息通信,发布订阅由PUBLISH、SUBSCRIBE、PSUBSCRIBE、PUBSUB等命令组成。

  • SUBSCRIBE命令:订阅某频道,在redisServer结构中通过pubsub_channels字典属性保存当前服务器所有频道的订阅关系,字典键时频道名称,字典值是一个链表,记录了所有订阅这个频道的客户端。
  • UNSUBSCRIBE命令:退订频道,调用该命令之后,会把订阅关系从pubsub_channels中删掉,如果键对应的链表为空了,则把键从字典中删除。
  • PSUBSCRIBE命令:订阅模式,服务器将所有的模式订阅关系保存在redisServer结构的pubsub_patterns属性中,该属性是一个链表,每个链表节点包含一个pubsubPattern结构,该结构记录了被订阅的模式和订阅该模式的客户端。
  • PUNSUBSCRIBE命令:退订模式,调用该命令之后,服务器会遍历pubsub_patterns链表,把客户端和模式都匹配的那个节点删除。
  • PUBLISH命令:发送订阅消息,服务器接收到该命令之后,先遍历pubsub_channels找出频道订阅者,把消息发送给所有频道订阅者,然后遍历pubsub_patterns找出与channel匹配的模式,并将消息发送给订阅了这些模式的客户端。
  • PUBSUB命令,查看订阅信息包含下面三个子命令:
  • PUBSUB CHANNLES [pattern]:返回当前服务器被订阅的频道,如指定pattern,则返回与模式匹配的频道
  • PUBSUB NUMSUB [channel-1 ... channel-n]:返回指定频道的订阅者数量
  • PUBSUB NUMPAT:返回服务器当前被订阅模式的数量

事务

Redis通过MULTI、EXEC、WATCH等命令来实现事务功能,实现将多个命令打包然后一次性顺序执行。事务以MULTI命令开始,EXEC命令结束。在执行MULTI命令之后执行的命令不立刻执行,而是向客户端返回一个QUEUED,等执行EXEC命令之后再执行。

事务的实现

事务开始

执行MULTI命令之后,服务器把客户端从非事务态切换到事务态,通过设置redisClient的flags标识,把REDIS_MULTI标识打开。

命令入队

客户端处于非事务态时,客户端发送的命令立刻执行,当处于事务态时:

如果客户端发送的命令为EXEC、DISCARD、WATCH、MULTI其中的一个时,服务器立即执行。
如果客户端发送的命令是其它的命令,服务器不会立刻执行这个命令,而是把命令放到事务队列中,然后向客户端返回QUEUED。
redisClient中有个multiState结构的属性mstate记录客户端的事务状态,在multiState结构中有个commands列表属性,它记录了调用MULTI之后该客户端入队的命令,count属性记录入队命令的数量。multiCmd结构记录命令实现函数指针,命令的参数,已经参数的数量。事务队列以FIFO的方式保存入队命令,先入队的命令先执行。
执行事务
执行EXEC命令提交事务,服务器接收该命令之后:

  1. 遍历client.mstate.commands,获取已入队的命令并且挨个执行,把命令的返回值添加到回复队列尾部。
  2. 清空客户端的事务状态,包括清零入队命令计数器,释放事务队列。
  3. 把执行结果返回给客户端。

WATCH命令实现

WATCH命令是一个乐观锁,在执行EXEC之前监视制定的数据库键,在执行EXEC命令执行时检查被监视的键是否至少有一个已经被修改过,如果是的话,服务器拒绝执行命令,并向客户端返回代表事务执行失败的空回复。
Redis数据库的redisDb结构保存了一个watched_keys字典,字典的键时某个被WATCH命令监视的键,值是一个链表,链表中记录了所有监视相应数据库键的客户端。
在执行对数据库修改的命令时,执行之后会调用multi.c/touchWatchKey函数对watched_keys字典进行检查,查看是否有客户端正在监视刚刚被命令修改过的数据库键,如果有的话,touchWatchKey函数将监视被修改键的客户端的REDIS_DIRTY_CAS标识打开,表示该客户端的事务安全性已经被破坏。当服务器接收到一个客户端发来的EXEC命令时,服务器根据这个客户端是否打开了REDIS_DIRTY_CAS标识来决定是否执行事务。

事务的ACID

原子性:对Redis事务来说,事务中的多个命令被当做一个整体,事务队列中的命令要么全部被执行,要么都不执行,Redis事务时具有原子性的,但是Redis事务部支持回滚,即使队列中某个命令执行出现了错误也不影响后面的命令,整个事务会继续执行。
一致性:在命令入队错误、执行错误、服务器停机时都不会影响数据库的一致性。ps:当入队错误时对2.6.5之前的版本事务会继续执行,2.6.5之后事务会被拒绝执行
隔离性:Redis事务执行期间不会被其它命令中断,以串行的方式运行,Redis事务是具有隔离性的
持久性:

  • 当服务器运行在无持久化的内存模式下时,事务不具有持久性:一旦服务器停机,所有数据都会丢失
  • 当服务器运行在RDB持久化模式下时,当服务器停机时会有一段时间的数据会丢失,事务不具有持久性
  • 当服务器运行在AOF持久化模式下,并且appendsync选项值为always时,数据会被及时保存到硬盘中,此时事务具有持久性(前提是没有打开no-appendfsync-on-rewrite选项,打开该选项之后,为了尽可能的减少IO操作,当服务器执行BGSAVE或BGREWRITEAOF时,会停止AOF文件同步,所以此时事务也不具有持久性)
  • 当服务器运行在AOF持久化模式下,并且appendsync选项值为everysec时,可能会丢失1秒的数据,此时事务不具有持久性
  • 当服务器运行在AOF持久化模式下,并且appendsync选项值为no,服务器停机时数据会丢失,此时事务不具有持久性

慢查询日志

Redis 的慢查询日志功能用于记录执行时间超过给定时长的命令请求, 用户可以通过这个功能产生的日志来监视和优化查询速度。

服务器配置有两个和慢查询日志相关的选项:

  • slowlog-log-slower-than 选项指定执行时间超过多少微秒(1 秒等于 1,000,000 微秒)的命令请求会被记录到日志上。

    举个例子, 如果这个选项的值为 100 , 那么执行时间超过 100 微秒的命令就会被记录到慢查询日志; 如果这个选项的值为 500 , 那么执行时间超过 500 微秒的命令就会被记录到慢查询日志; 诸如此类。

  • slowlog-max-len 选项指定服务器最多保存多少条慢查询日志。

    服务器使用先进先出的方式保存多条慢查询日志: 当服务器储存的慢查询日志数量等于 slowlog-max-len 选项的值时, 服务器在添加一条新的慢查询日志之前, 会先将最旧的一条慢查询日志删除。

    举个例子, 如果服务器 slowlog-max-len 的值为 100 , 并且假设服务器已经储存了 100 条慢查询日志, 那么如果服务器打算添加一条新日志的话, 它就必须先删除目前保存的最旧的那条日志, 然后再添加新日志。

原文链接:[http://wely.iteye.com/blog/2361639 ]
相关文章
|
7月前
|
监控 NoSQL 关系型数据库
Redis:事务(Transactions)
Redis事务支持将多个命令打包执行,但与MySQL不同,它不保证原子性、一致性、持久性和隔离性。Redis事务的核心在于“打包”命令,避免其他客户端插队,通过MULTI、EXEC、DISCARD等命令实现。此外,Redis提供WATCH和UNWATCH机制,用于监控键变化,实现类似“乐观锁”的功能,提升并发操作的安全性。
|
SQL 数据库
【YashanDB知识库】应用绑定参数的慢查询,慢日志抓取不到
【YashanDB知识库】应用绑定参数的慢查询,慢日志抓取不到
|
存储 运维 NoSQL
【赵渝强老师】Redis的慢查询日志
Redis慢查询日志用于记录执行时间超过预设阈值的命令,帮助开发和运维人员定位性能问题。每条慢查询日志包含标识ID、发生时间戳、命令耗时及详细信息。配置参数包括`slowlog-max-len`(默认128)和`slowlog-log-slower-than`(默认10000微秒)。实战中可通过`slowlog get`获取日志、`slowlog len`查看长度、`slowlog reset`重置日志。建议线上环境将`slowlog-max-len`设为1000以上,并根据并发量调整`slowlog-log-slower-than`。需要注意的是,慢查询只记录命令执行时间。
679 5
|
SQL 关系型数据库 MySQL
【赵渝强老师】MySQL的慢查询日志
MySQL的慢查询日志用于记录执行时间超过设定阈值的SQL语句,帮助数据库管理员识别并优化性能问题。通过`mysqldumpslow`工具可查看日志。本文介绍了如何检查、启用及配置慢查询日志,并通过实例演示了慢查询的记录与分析过程。
739 3
|
监控 关系型数据库 MySQL
分析慢查询日志
【10月更文挑战第29天】分析慢查询日志
344 3
|
监控 关系型数据库 数据库
怎样分析慢查询日志?
【10月更文挑战第29天】怎样分析慢查询日志?
434 2
|
NoSQL Redis
Redis事务长什么样?一文带你全面了解
Redis事务是一组命令的有序队列,通过MULTI、EXEC、WATCH和DISCARD等命令实现原子性操作。事务中的命令在EXEC执行前不会实际运行,而是先进入队列,确保所有命令要么全部成功,要么全部失败。此外,Redis还支持Lua脚本实现类似事务的操作,通常更简单高效。事务适用于购物车结算、秒杀活动、排行榜更新等需要保证数据一致性的场景。
198 0
|
消息中间件 NoSQL Redis
【赵渝强老师】Redis的消息发布与订阅
本文介绍了Redis实现消息队列的两种场景:发布者订阅者模式和生产者消费者模式。其中,发布者订阅者模式通过channel频道进行解耦,订阅者监听特定channel的消息,当发布者向该channel发送消息时,所有订阅者都能接收到消息。文章还提供了相关操作命令及示例代码,展示了如何使用Redis实现消息的发布与订阅。
455 0
|
缓存 NoSQL 安全
Redis 7.0 Multi Part AOF的设计和实现
本文将详解Redis中现有AOF机制的一些不足以及Redis 7.0中引入的Multi Part AOF的设计和实现细节
2422 0
|
缓存 NoSQL 安全
Redis 7.0 Multi Part AOF的设计和实现
Redis 作为一种非常流行的内存数据库,通过将数据保存在内存中,Redis 得以拥有极高的读写性能。但是一旦进程退出,Redis 的数据就会全部丢失。 为了解决这个问题,Redis 提供了 RDB 和 AOF 两种持久化方案,将内存中的数据保存到磁盘中,避免数据丢失。本文将重点讨论AOF持久化方案,以及其存在的一些问题,并探讨在Redis 7.0 (已发布RC1) 中Multi Part AOF(下文简称为MP-AOF,本特性由阿里云数据库Tair团队贡献)设计和实现细节。
Redis 7.0 Multi Part AOF的设计和实现
下一篇
开通oss服务