Lua脚本
重点回顾
- Redis服务器在启动时,会对内嵌的Lua环境执行一系列修改操作,从未确保内嵌的Lua环境可以满足Redis在功能性和安全性等方面的需要
- Redis服务器专门使用一个为客户端来执行Lua脚本中包含的redis命令
- Redis使用脚本字典来保存所有被EVAL命令执行过,或者SCRIPT LOAD命令载入过的lua脚本,这些脚本可以用于实现SCRIPT EXISTS命令,以及实现脚本复制功能
- EVAL命令为客户端输入的脚本在Lua环境中定义一个函数,并通过这个函数来执行脚本
- EVALSHA命令通过直接调用Lua脚本中已定义的函数来执行脚本
- script flush命令会清空服务器lua_scripts字典中保存的脚本,并充值Lua环境
- SCRIPT EXISTS命令接收一个或多个SHA1校验和为参数,并通过lua_scripts字典确认校验和对应脚本是否存在
- SCRIPT LOAD命令接受一个Lua脚本为参数,为该脚本在Lua环境中创建函数,并将脚本保存在lua_scripts脚本中
- 服务器在执行脚本之前,会为lua环境设置一个超时处理的钩子,当脚本出现超时运行情况时,客户端可以铜鼓向服务器发送SCRIPT KILL 命令让钩子停止正在执行的脚本,或者发送SHUTDOWN nosave命令让钩子关闭整个服务器
- 主服务器复制EVAL 、 SCRIPT FLUSH、SCRIPT LOAD 三个命令的方法和复制普通Redis命令一样,只要将相同的命令传播给从服务器就可以
- 主服务器在复制EVALSHA命令中,必须确保素有从服务器都已经载入了EVALSHA命令指定的SHA1校验和对应的脚本,如果不能确保这一点,主服务器会将EVALSHA命令转成等效的EVAL命令,并通过EVAL命令来获得相同的脚本执行效果
排序
回顾
- SORT命令通过将被排序键包含的元素载入到数组里,然后对数组进行排序
- 默认情况下,SORT命令假设被排序键包含的都是数字值,以数字值的方式进行排序
- SORT命令使用了ALPHA选项,那么SORT命令假设被排序键包含的都是字符串,以字符串的方式进行排序
- SORT命令的排序操作快排算法实现
- SORT命令会根据用户是否使用了DESC选项决定使用升序还是降序
- SORT命令使用BY选项时,命令使用其他键的值来进行排序操作
- SORT命令使用LIMIT选项时,命令只保留排序结果集中LIMIT选项指定的元素
- SORT命令使用STORE选项时,会将排序结果集保存在指定的键里面
- SORT命令同时使用多个选项时,,先执行排序操作(ALPHA、ASC、DESC、BY),然后执行LIMIT选项,之后执行GET选项,再执行STORE选项,最后将排序结果集返回给客户端
- 除了GET选项之外,调整选项的摆放位置不会影响STORE命令的排序结果
二进制位数组
位数组的表示
使用字符串对象表示位数组,因为字符串对象使用SDS数据结构是二进制安全的
buf数组保存的顺序和我们平时书写位数组的顺序是完全相反的,上图中位数组为 0100 1101 ,
假如每次扩展buf数组之后,程序都需要将位数组已有的位进行移动,然后才执行写入操作,这比setbit命令实现方式更复杂,而且移位带来的CPU时间消耗也会影响命令的执行速度,所以采用setbit命令采用倒序的方式完成扩展,写入操作可以直接在扩展的二进制未中完成,而不必改动数组原来已有的二进制位
bitcount命令实现
三种常用的算法:
- 遍历算法
- 查表算法,保存一张表,表的键为某种排列的位数组,值为该位数组中1的个数
- 二进制位统计算法:variable-precision SWAR算法:计算汉明重量
Redis中采用的算法:
采用了查表和cariable-precision SWAR两种算法,未处理的二进制位数大于等于128位,采用SWAR算法,否则采用查表算法;实现的算法负责度为O(n),n为输入二进制的数量
重点回顾
- Redis使用SDS保存二进制数组
- SDS使用逆序保存位数组,这种保存顺序简化了SETBIT命令的实现,使得setbit命令可以在不移动现有二进制位的情况下,对位数组进行空间扩展
- BITCOUNT命令使用了查表和variable-precision SWAR算法优化命令的执行效率
- BITOP命令的所有操作都使用C语言内置的位操作来实现
慢日志查询
回顾
- Redis慢日志查询功能用于记录执行时间超过指定时长的命令
- Redis服务器将所有的慢查询日志保存在服务器状态的slowlog链表中,每个链表节点都包含一个slowlogEntry结构,每个slowlogEntry结构表示一条慢查询日志
- 打印和删除慢查询日志可以通过遍历slowlog链表完成
- slowlog链表的长度就是服务器保存的慢查询日志的数量
- 新的慢查询日志会被添加到slowlog链表的表头,如果日志的数量超过slowlog-max-len选项的值,多出来的日志将会删除
监视器
回顾
- 客户端可以通过执行MONITOR命令,将客户端转换成监视器,接收并打印服务器处理的每个命令请求的相关信息
- 当一个客户端从普通客户端变成监视器,这个客户端REDIS_MONITOR标识会被打开
- 服务器将所有的监视器记录在monitors链表中
- 每次处理命令请求中,服务器都会遍历monitors链表,将相关信息发送给监视器