前言

参考资料:《Redis设计与实现 第二版》;

第三部分为独立功能的实现,主要由以下模块组成:发布订阅事务Lua 脚本排序二进制位数组慢查询日志监视器

本篇将介绍 Redis 的二进制位数组慢查询日志监视器。Redis 提供了一些命令操作二进制位数组;通过 SLOWLOG 相关命令可以对慢查询日志进行操作;通过 MONITOR 命令可以进入监视器模式;

与本章相关的 Redis 命令总结在下篇文章,欢迎点击收藏,本篇将不再重复:

《Redis常用命令及示例总结(API)》https://blog.csdn.net/dlhjw1412/article/details/119713214


1. 二进制位数组

1.1 位数组的表示

  • Redis 使用字符串对象来表示位数组,因为字符串对象使用的 SDS 是二进制安全的;
  • 使用逆序保存位数组,下图实际为:1111 0000 1100 0011 1010 0101;
    • 使用逆序保存位数组,可以直接在新扩展的二进制位中完成,不必改动位数组原来已有的二进制位;

1.2 GETBIT 命令的实现

  • GETBIT key offset 命令;
  • 1)计算 byte=offset / 8;byte 值表示位数组的哪个字节;
  • 2)计算 bit=(offset mod 8)+1;bit 值表示在 byte 下标字节的第几个二进制位;
  • 3)根据 byte 和 bit 的值定位 offfset 偏移量指定的二进制位;
  • 4)向客户端返回二进制位的值;

1.3 SETBIT 命令的实现

  • SETBIT key offset value 命令;

  • 1)计算 len=offset/8+1;len 值表示 offset 指定的二进制位至少需要多少字节;

  • 2)根据 len 值进行扩展新空间,如果原位数组长度够则不扩展;

  • 3)计算 byte=offset/8;byte 值表示位数组的哪个字节;

  • 4)计算 bit=(offset mod 8)+1;bit 值表示在 byte 下标字节的第几个二进制位;

  • 5)根据 byte 和 bit 的值定位 offfset 偏移量指定的二进制位 oldvalue,并修改;

  • 6)向客户端返回二进制位 oldvalue 的值;

  • 无扩展操作的 SETBIT 命令示例如下:

  • 带扩展操作的 SETBIT 命令示例如下:

1.4 BITECOUNT 命令的实现

  • 遍历算法

    • 遍历位数组中的每个二进制位,遇到 1 时将计数器值赠 1;
    • 实现简单,效率低;
  • 查表法

    • 对于长度有限的位数组而言,能表示的二进制位有限,而每种排列顺序的 1 的个数是确定的;
    • 查表法是典型的空间换时间策略,节约时间越多,花费内存越大
    • 受 CPU 缓存限制:创建表越大,能加载进缓存的内容越少,缓存不命中的情况越高,缓存的换入换出操作就越频繁,最终影响实际效率;

  • variable-precision SWAR 算法

    • 又称:计算汉明重量法;

    • 一个处理 32 位长度位数的算法示例:

      uint32_t swar(unit32_t i){
      //步骤1:按每2个二进制位为一组分组,各组的十进制为汉明重量
      i = (i & 0x55555555) + ((i >> 1) & 0x55555555);
      //步骤2:按每4个二进制位为一组分组,各组的十进制为汉明重量
      i = (i & 0x33333333) + ((i >> 2) & 0x33333333);
      //步骤3:按每8个二进制位为一组分组,各组的十进制为汉明重量
      i = (i & 0x0F0F0F0F) + ((i >> 4) & 0x0F0F0F0F);
      //步骤4
      i = (i*(0x01010101) >> 24);
      return i;
      }
    • 一个示例如下:



  • Redis 的实现

    • BITCOUNT 命令使用查表法variable-precision SWAR 法两种;

      • 查表法:使用键长为 8 位的表,记录 0000 0000 到 1111 1111 在内的二进制位的汉明重量;
      • variable-precision SWAR 法:每次循环中载入 128 个二进制位,调用 4 次 32 位的variable-precision SWAR 法计算 128 位二进制位的汉明重量;
    • 程序根据未处理的二进制位的数量决定使用哪种算法:
      • 未处理二进制位大于等于 128 位:variable-precision SWAR 法
      • 未处理二进制位小于 128 位:查表法
  • 算法的时间复杂度为:O(n),n 为输入二进制位的数量;

1.5 BITOP 命令的实现

  • BITOP 命令的所有操作都是使用 C 语言内置的位操作来实现的;

    BITOP 命令 C语言操作 说明
    BITOP AND & 逻辑与
    BITOP OR | 逻辑或
    BITOP XOR ^ 逻辑异或
    BITOP NOT ~ 逻辑非

2. 慢查询日志

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

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

    • slowlog-log-slower-than 选项:指定执行时间超过多少毫秒的命令请求会被记录到日志上;
    • slowlog-max-len 选项:指定服务器最多保存多少条慢查询日志。采用先进先出的方式;
  • 使用 SLOWLOG 相关命令可以操作慢查询日志;

2.1 慢查询记录的保存

  • 服务器状态中包含与慢查询日志功能相关的属性:

    struct redisServer{
    //...
    // 下一条慢查询日志的 ID
    long long slowlog_entry_id;
    // 保存了所有慢查询日志的链表
    list *slowlog;
    // 服务器配置 slow_log_slower_than 选项的值
    long long slow_log_slower_than;
    // 服务器配置 slowlog_max_len 选项的值
    unsigned long slowlog_max_len;
    };

  • slowlog 链表结构如下:

    typedef struct slowlogEntry{
    // 唯一标识符
    long long id;
    // 命令执行时的时间,格式为 UNIX 时间戳
    time_t time;
    // 执行命令消耗的时间,以微秒为单位
    long long duration;
    // 命令与命令参数
    robj **argv;
    // 命令与命令参数的数量
    int argc;
    } slowlogEntry;

2.2 慢查询日志的阅览与删除

  • SLOWLOG GET [number];打印所有 slow log ,最大长度取决于 slowlog-max-len 选项的值;
  • SLOWLOG LEN;查看当前日志的数量。其值为 slowlog 链表的长度;
  • SLOWLOG RESET;清除所有慢查询日志;

2.3 添加新日志

  • 每次执行命令的之前和之后,程序会记录微秒格式的当前 UNIX 时间戳,两个时间戳之间的差值就是服务器执行命令所消耗的时长;
  • 新的慢查询日志会被添加到 slowlog 链表的表头,如果日志的数量超过 slowlog-max-len 选项的值,那么多出来的日志会被删除;

3. 监视器

  • 执行 MONITOR 命令,客户端可以将自己变为一个监视器,实时打印服务器当前处理的命令请求相关信息;
  • 当一个客户端从普通客户端变为监视器时,该客户端的 REDIS_MONITOR 标识会被打开,该客户端会被添加到 monitors 链表的表尾;
  • 所有监视器都记录在 monitors 链表里;
  • 每次处理命令请求时,服务器会遍历 monitors 链表,将相关信息发送给监视器;


最后

新人制作,如有错误,欢迎指出,感激不尽!
欢迎关注公众号,会分享一些更日常的东西!
如需转载,请标注出处!

Redis | 第10章 二进制数组、慢查询日志和监视器《Redis设计与实现》的更多相关文章

  1. redis 笔记06 发布与订阅、事务、慢查询日志、监视器

    发布与订阅 1. 服务器状态在pubsub_channels字典保存了所有频道的订阅关系:SUBSCRIBE命令负责将客户端和被订阅的频道关联到这个字典里面,而UNSUBSCRIBE命令则负责 解除客 ...

  2. 【笔记】《Redis设计与实现》chapter22 二进制位数组 chapter23 慢查询日志 chapter24 监视器

    chapter22 二进制位数组 22.4 BITCOUNT命令的实现 遍历算法 查表算法 variable-precision SWAP算法 chapter23 慢查询日志 Redis的慢查询日志功 ...

  3. Redis 设计与实现 (八)--排序、慢查询日志、监视器

    一.排序 SORT <key>  对一个数字值的key进行排序 1.alpha 对字符串类型的键进行排序 2.asc / desc redis 默认升序排序asc desc 与之相反 3. ...

  4. C Primer Plus_第10章_数组和指针_编程练习

    1. /*rain.c 针对若干年的降水量数据,计算年降水总量.年降水平均量,以及月降水平均量*/ #include <stdio.h> #define MONTHS 12 #define ...

  5. Redis | 第8章 发布订阅与事务《Redis设计与实现》

    目录 前言 1. 发布订阅 1.1 频道的订阅与退订 1.2 模式的订阅与退订 1.3 发送消息 1.4 查看订阅消息 2. 事务 2.1 事务的实现 2.2 WATCH 命令的实现 2.3 事务的 ...

  6. Redis | 第9章 Lua 脚本与排序《Redis设计与实现》

    目录 前言 1. Lua 脚本 1.1 Redis 创建并修改 Lua 环境的步骤 1.2 Lua 环境协作组件 1.3 EVAL 命令的实现 1.4 EVALSHA 命令的实现 1.5 脚本管理命令 ...

  7. 浅谈Redis之慢查询日志

    首先我们需要知道redis的慢查询日志有什么用?日常在使用redis的时候为什么要用慢查询日志? 第一个问题: 慢查询日志是为了记录执行时间超过给定时长的redis命令请求 第二个问题: 让使用者更好 ...

  8. 【redis 学习系列07】Redis小功能大用处01 慢查询分析以及Redis Shell

    Redis提供了5种数据结构已经足够强大,但除此之外,Redis还提供了诸如慢查询分析.功能强大的Redis Shell.Pipeline.事务与Lua脚本.Bitmaps.HyperLogLog.发 ...

  9. redis实战笔记(10)-第10章 扩展Redis

    本章主要内容   扩展读性能 扩展写性能以及内存容量 扩展复杂的查询   随着Redis的使用越来越多, 只使用一台Redis服务器没办法存储所有数据或者没办法处理所有读写请求的问题迟早都会出现, 这 ...

随机推荐

  1. MiniFly四轴飞行器之部分系统及电源分析

    最近硬件四轴很火,了解了很久,还是选择了MiniFly,主要还是资料多,后边可以有人讨论,不像很多就是建了个群,研究问题还是在论坛方便很多. 四轴终于拿到手,功能很强大,主要是还支持二次开发,可以研究 ...

  2. 常用Java API:HashMap 和 TreeMap

    摘要 本文主要介绍Map接口下的HashMap和TreeMap. HashMap HashMap是基于哈希表的 Map 接口的实现,是无序的 clear()//清空. containsKey(Obje ...

  3. AtCoder Beginner Contest 215 F题题解

    F - Dist Max 2 什么时候我才能突破\(F\)题的大关... 算了,不说了,看题. 简化题意:给定\(n\)个点的坐标,定义没两个点的距离为\(min(|x_i-x_j|,|y_i-y_j ...

  4. 重学STM32---(九)之CAN通信(一)

    目录 1.CAN 是什么 2.CAN 特点 3.错误状态的种类 4.总线拓扑 5.CAN 协议 1.CAN 是什么   CAN 是 Controller Area Network的缩写(以下称为 CA ...

  5. Flink入门-第一篇:Flink基础概念以及竞品对比

    Flink入门-第一篇:Flink基础概念以及竞品对比 Flink介绍 截止2021年10月Flink最新的稳定版本已经发展到1.14.0 Flink起源于一个名为Stratosphere的研究项目主 ...

  6. flyway的使用

    1.使用它之前先要了解一些概念: 版本:对数据库的每一次变更可称为一个版本. 迁移:Flyway把数据库结构从一个版本更新到另一个版本叫做迁移. 可用的迁移:Flyway的文件系统识别出来的迁移版本. ...

  7. 在线编辑Word——插入图表

    在Word中可插入图表,配合使用表格能够更加全方位的展示数据的可信度并增加数据的可读性.本文将通过使用在线编辑器 Spire.Cloud Word 演示如何来插入图表,并设置相关格式化操作.具体步骤如 ...

  8. Python打包成exe,文件太大问题解决办法

    Python打包成exe,文件太大问题解决办法 原因 解决办法 具体步骤 情况一:初次打包 情况二:再次打包 原因 由于使用pyinstaller打包.py文件时,会把很多已安装的无关库同时打包进去, ...

  9. FZU ICPC 2020 寒假训练 2

    A - 排序 输入一行数字,如果我们把这行数字中的'5'都看成空格,那么就得到一行用空格分割的若 干非负整数(可能有些整数以'0'开头,这些头部的'0'应该被忽略掉,除非这个整数就是由 若干个'0'组 ...

  10. 编解码再进化:Ali266 与下一代视频技术

    过去的一年见证了人类百年不遇的大事记,也见证了多种视频应用的厚积薄发.而因此所带来的视频数据量的爆发式增长更加加剧了对高效编解码这样的底层硬核技术的急迫需求. 新视频编解码标准 VVC 定稿不久之后, ...