Redis | 第10章 二进制数组、慢查询日志和监视器《Redis设计与实现》
前言
参考资料:《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 位:查表法;
- BITCOUNT 命令使用查表法和 variable-precision SWAR 法两种;
- 算法的时间复杂度为: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设计与实现》的更多相关文章
- redis 笔记06 发布与订阅、事务、慢查询日志、监视器
发布与订阅 1. 服务器状态在pubsub_channels字典保存了所有频道的订阅关系:SUBSCRIBE命令负责将客户端和被订阅的频道关联到这个字典里面,而UNSUBSCRIBE命令则负责 解除客 ...
- 【笔记】《Redis设计与实现》chapter22 二进制位数组 chapter23 慢查询日志 chapter24 监视器
chapter22 二进制位数组 22.4 BITCOUNT命令的实现 遍历算法 查表算法 variable-precision SWAP算法 chapter23 慢查询日志 Redis的慢查询日志功 ...
- Redis 设计与实现 (八)--排序、慢查询日志、监视器
一.排序 SORT <key> 对一个数字值的key进行排序 1.alpha 对字符串类型的键进行排序 2.asc / desc redis 默认升序排序asc desc 与之相反 3. ...
- C Primer Plus_第10章_数组和指针_编程练习
1. /*rain.c 针对若干年的降水量数据,计算年降水总量.年降水平均量,以及月降水平均量*/ #include <stdio.h> #define MONTHS 12 #define ...
- Redis | 第8章 发布订阅与事务《Redis设计与实现》
目录 前言 1. 发布订阅 1.1 频道的订阅与退订 1.2 模式的订阅与退订 1.3 发送消息 1.4 查看订阅消息 2. 事务 2.1 事务的实现 2.2 WATCH 命令的实现 2.3 事务的 ...
- Redis | 第9章 Lua 脚本与排序《Redis设计与实现》
目录 前言 1. Lua 脚本 1.1 Redis 创建并修改 Lua 环境的步骤 1.2 Lua 环境协作组件 1.3 EVAL 命令的实现 1.4 EVALSHA 命令的实现 1.5 脚本管理命令 ...
- 浅谈Redis之慢查询日志
首先我们需要知道redis的慢查询日志有什么用?日常在使用redis的时候为什么要用慢查询日志? 第一个问题: 慢查询日志是为了记录执行时间超过给定时长的redis命令请求 第二个问题: 让使用者更好 ...
- 【redis 学习系列07】Redis小功能大用处01 慢查询分析以及Redis Shell
Redis提供了5种数据结构已经足够强大,但除此之外,Redis还提供了诸如慢查询分析.功能强大的Redis Shell.Pipeline.事务与Lua脚本.Bitmaps.HyperLogLog.发 ...
- redis实战笔记(10)-第10章 扩展Redis
本章主要内容 扩展读性能 扩展写性能以及内存容量 扩展复杂的查询 随着Redis的使用越来越多, 只使用一台Redis服务器没办法存储所有数据或者没办法处理所有读写请求的问题迟早都会出现, 这 ...
随机推荐
- STM32单片机的学习方法(方法大体适用所有开发版入门)
1,一款实用的开发板. 这个是实验的基础,有时候软件仿真通过了,在板上并不一定能跑起来,而且有个开发板在手,什么东西都可以直观的看到,效果不是仿真能比的.但开发板不宜多,多了的话连自己都不知道该学哪个 ...
- 零基础学习C语言入门必备知识
今天跟大家一起从零学C语言: 1. C语言简介 1.1 C语言发展史 C语言是一种广泛使用的面向过程的计算机程序设计语言,既适合于系统程序设计,又适合于应用程序设计.C语言的发展历程大致如图1-1所示 ...
- Luogu P2024 [NOI2001]食物链 | 并查集
题目链接 思路:并查集,因为一开始我们并不知道每一只动物是哪一个种类的,所以我们干脆建立三倍于n的空间,1~n这三分之一用来存第i只动物是A的情况,n+1~2n这三分之一用来存第(i-n)只动物是B的 ...
- Linux Kernel 記憶體管理機制之美<转>
转自--http://five.rdaili.com/sohu.com.php?u=Mq3EniVnae0axim7jkGhH0IhA9uho6CQso7R1aYomXWJ9UemfwUQYmKRc8 ...
- 微服务之十四如何在 Ocelot 网关中配置多实例 Swagger 访问
一.介绍 当我们开发基于微服务的应用程序的时候,有一个环节总是跳不过去的,那就是要创建 WebApi,然后,我们的应用程序基于 WebApi 接口去访问.在没有 Swagger 以前,我们开发好了 W ...
- 五(一)、spring 声明式事务注解配置
一.事务概述: 事务就是一系列的动作, 它们被当做一个单独的工作单元. 这些动作要么全部完成, 要么全部不起作用:比如 用户购买图书:购买动作之前需要确认 ①图书的数量是否足够:②用户账号余额是否足够 ...
- k8s入坑之路(7)kubernetes设计精髓List/Watch机制和Informer模块详解
1.list-watch是什么 List-watch 是 K8S 统一的异步消息处理机制,保证了消息的实时性,可靠性,顺序性,性能等等,为声明式风格的API 奠定了良好的基础,它是优雅的通信方式,是 ...
- virtualenv笔记
virtualenv venv --python=python2.7 mkvirtualenv venv --python=python linux中使用virtualenvwrapper 安装 pi ...
- 『学了就忘』Linux基础命令 — 39、挂载U盘和挂载NTFS分区
目录 1.在Linux系统中挂载U盘 (1)插入U盘 (2)查询U盘设备文件名 (3)挂载U盘 (4)U盘中的中文乱码 (5)U盘卸载 2.在Linux系统中挂载NTFS分区 (1)Linux的驱动加 ...
- 第二课 Dubbo设计的架构设计
总体架构 Dubbo的总体架构,如图所示: Dubbo框架设计一共划分了10个层,而最上面的Service层是留给实际想要使用Dubbo开发分布式服务的开发者实现业务逻辑的接口层.图中左边淡蓝背景的为 ...