`
IXHONG
  • 浏览: 450198 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

《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 条慢查询日志, 那么如果服务器打算添加一条新日志的话, 它就必须先删除目前保存的最旧的那条日志, 然后再添加新日志。

分享到:
评论

相关推荐

    redis设计与实现学习笔记,转自github:https://github.com/JiangRRRen/Redis-stud

    本学习笔记基于GitHub上的项目“Redis-stud”,由JiangRRRen分享,旨在深入理解Redis的设计与实现原理。 一、Redis概述 Redis是Remote Dictionary Server的缩写,它是一个开源的、支持网络的、可持久化的键值存储...

    redis学习笔记+练习springboot-redisdemo

    本资源包包含了关于Redis的学习笔记以及一个基于SpringBoot整合Redis的实战项目——"springboot-redisdemo",旨在帮助你深入理解和应用Redis。 首先,让我们详细探讨Redis的核心知识点: 1. **Redis的数据类型**:...

    Redis学习笔记,基于《Redis设计与实现》的内容,对Redis的基础知识进行总结.zip

    【Redis学习笔记】基于《Redis设计与实现》的深度解析 Redis是一款高性能的键值存储系统,被广泛应用于缓存、消息队列、分布式锁等场景。本笔记将结合《Redis设计与实现》这本书的内容,深入探讨Redis的基础知识,...

    redis心得笔记--180202

    - 发布订阅:提供发布/订阅模式,用于实现消息传递和事件驱动。 - Lua脚本:支持在服务器端执行Lua脚本,进行复杂逻辑处理。 3. 使用场景 - 缓存:Redis常用于减轻数据库压力,提高网站性能。 - 排行榜:利用...

    redis学习笔记。

    - 不支持复杂查询:与关系型数据库相比,查询能力较弱。 - 数据一致性:虽然支持持久化,但可能会丢失部分数据。 #### 1.4 术语 - **PUB/SUB**:发布/订阅模式,用于消息广播。 - **AOF(Append Only File)**:...

    Redis读书笔记(设计实现PDF)

    本文将基于“Redis读书笔记(设计实现PDF)”的标题和描述,结合黄建宏的《Redis设计与实现原理第二版》及老钱在掘金小册中的《Redis深度探险》资源,为你解析Redis的核心概念、设计思想和实际应用。 1. **Redis的...

    狂神说Redis笔记.pdf

    此外,还有 incr/decr 命令进行原子计数,EXPIRE命令实现数据过期机制,以及PUB/SUB命令支持发布订阅模式。 三、持久化 为了防止数据丢失,Redis提供了两种持久化方式:RDB快照和AOF日志。RDB是在指定时间间隔内...

    Java Redis 学习笔记 Markdown+PDF 格式分享

    - 消息订阅与发布:`subscribe()`和`publish()`实现消息通信。 - 分布式锁:使用`setnx()`和`expire()`实现基于Redis的分布式锁。 - 缓存淘汰策略:如LRU(最近最少使用)、TTL(过期时间)等。 6. **Redis持久...

    redis笔记.rar

    这份"redis笔记.rar"包含的"redis笔记.pdf"应该是一份详细的学习指南,非常适合初学者了解和掌握Redis的基本概念、操作命令以及实战技巧。 1. Redis基本概念: - Redis是一个开源的、基于内存的数据存储系统,支持...

    Redis笔记以及资料

    - 发布订阅模式用于实现消息传递,客户端可以订阅一个或多个频道,当有消息发布到这些频道时,订阅者会收到消息。 **6. Redis的过期策略** - Redis允许为键设置过期时间,过期后键会被自动删除。 - 过期策略包括...

    redis基本命令paper-mas开发笔记

    - **发布订阅(Pub/Sub)**:实现消息广播,支持频道订阅和发布。 - ** GEO(地理空间索引)**:存储地理位置信息,支持范围查询。 - **Lua脚本**:通过`EVAL`命令执行Lua代码,实现原子操作和复杂逻辑。 6. **...

    Redis学习笔记整理

    ### Redis学习笔记整理 #### 一、Redis环境搭建 ##### 1.1 简介 Redis是一款开源的键值(Key-Value)型数据库系统,因其高性能和丰富的数据结构而广受欢迎。它不仅可以作为数据库使用,还可以作为一种数据结构服务器...

    redis学习心得与笔记

    3. 消息队列:通过Redis的List数据类型,可以实现简单的消息队列功能,例如发布/订阅模式和阻塞列表操作。 四、优化与注意事项 1. 内存管理:合理设置Redis的最大内存大小,避免过度消耗系统资源。同时,监控内存...

    redis详细学习笔记

    Redis是一款高性能的键值对数据库,常用于数据缓存、消息队列以及主从复制等场景。本笔记将深入探讨Redis的关键特性和使用方法,帮助读者全面了解这一...阅读"Redis学习笔记.pdf"将为你提供更详尽的实例和实战经验。

    根据黑马程序员的 redis 课程自学做的 redis 笔记,备份一下

    Redis 是一个高性能的键值数据库,它以内存存储为...在使用 Redis 时,要充分考虑数据量、内存占用、持久化策略等因素,以实现最佳的系统设计。同时,不断关注 Redis 的更新和社区动态,以便掌握最新的功能和最佳实践。

    2022年redis学习笔记

    这份2022年的Redis学习笔记涵盖了Redis的基础概念、核心特性、使用场景以及最佳实践。 一、Redis简介 Redis是一个开源(BSD许可)的,非关系型、内存中的数据结构存储系统,可以用作数据库、缓存和消息中间件。它...

    redis笔记+资料

    5. **发布/订阅**:Redis 提供了 Pub/Sub(发布/订阅)模式,实现消息的异步通信。 6. **主从复制**:通过主从复制,可以实现数据备份和负载均衡,提升系统的可用性和性能。 7. **lua脚本**:Redis 允许用户使用 Lua...

    读《Redis 深度历险》学习笔记与实践.zip

    7. **发布订阅**:`PUBLISH channel message`在频道上发布消息,`SUBSCRIBE channel`订阅频道接收消息,构建简单的消息通信模型。 8. **lua脚本**:`EVAL script numkeys key [key ...] arg [arg ...]`允许执行Lua...

Global site tag (gtag.js) - Google Analytics