有书共读:《Redis设计与实现》第20章到第24章读书笔记
第20章: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命令接受一个或多个SHAI校验和为参数,并通过检查lua_scripts字典来确认校验和对应的脚本是否存在。
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命令接受一个或多个SHAI校验和为参数,并通过检查lua_scripts字典来确认校验和对应的脚本是否存在。
SCRIPT LOAD命令接受一个Lua脚本为参数,为该脚本在Lua环境中创建函数,并将脚本保存到lua_scripts字典中。
服务器在执行脚本之前,会为Lua环境设置一个超时处理钩子,当脚本出现超时运行情况时,客户端可以通过向服务器发送SCRIPT KILL命令来让钩子停止正在执行的脚本,或者发送SHUTDOWN nosave命令来让钩子关闭整个服务器。
主服务器复制EVAL、SCRIPT FLUSH、SCRIPT LOAD三个命令的方法和复制普通Redis命令一样,只要将相同的命令传播给从服务器就可以了。
主服务器复制EVAL、SCRIPT FLUSH、SCRIPT LOAD三个命令的方法和复制普通Redis命令一样,只要将相同的命令传播给从服务器就可以了。
主服务器在复制EVALSHA命令时,必须确保所有从服务器都已经载入了EVALSHA命令指定的SHAI校验和所对应的Lua脚本,如果不能确保这一点的话,主服务器会将EVALSHA命令转换成等效的EVAL命令,并通过传播EVAL命令来获得相同的脚本执行效果。
第21章:排序
Redis的SORT命令可以对列表键、集合键或者有序集合键的值进行排序。
SORT命令通过将被排序键包含的元素载入大数组里面,然后对数组进行排序来完成对键进行排序的工作。
在默认情况下,SORT命令假设被排序键包含的都是数字值,并且以数字值的方式来进行排序。
如果SORT命令使用了ALPHA选项,那么SORT命令假设被排序键包含的都是字符串值,并且以字符串的方式来进行排序。
SORT命令的排序操作由快速排序算法实现。
SORT命令会根据用户是否使用了DESC选项来决定是使用升序对比还是降序对比来比较被排序的元素,升序对比会产生升序排序结果,被排序的元素按值的大小从小到大排序,降序对比会产生降序排序结果,被排序的元素按值得从大到小排序。
当SORT命令使用了BY选项时,命令使用其他键的值作为权重来进行排序操作。
当SORT命令使用了LIMIT选项时,命令只保留排序结果集中LIMIT选项指定的元素。
当SORT命令使用了GET选项时,命令会根据排序结果集中的元素,以及GET选项给定的模式,查找并返回其他键的值,而不是返回被排序的元素。
当SORT命令使用了STORE选项时,命令会将排序结果集保存在指定的键里面。
当SORT命令同时使用多个选项时,命令会先执行排序操作(可用的选项为ALPHA、ASC或DESC、BY),然后执行LIMIT选项,之后执行GET选项,再之后执行STORE,最后才将排序结果集返回给客户端。
除了GET选项之外,调整选项的摆放位置不会影响SORT命令的排序结果。
第22章:二进制数组
Redis提供了SETBIT、GETBIT、BITCOUNT、BITOP四个命令用于处理二进制位数组(bit array,又称“位数组”)。其中,SETBIT命令用于为位数组指定偏移量上的二进制位设置值,位数组的偏移量从0开始计数,而二进制位的值则可以是0或者1。GETBIT命令则用于获取位数组指定偏移量上的二进制位的值。BITCOUNT命令用于统计位数组里面,值为1的二进制位的数量。BITOP命令则可以对多个位数组进行按位与、按位或、按位异或运算。
Redis使用SDS来保存位数组。
SDS使用逆序来保存位数组,这种保存顺序简化了SETBIT命令的实现,使得SETBIT命令可以在不移动现有二进制位的情况下,对数组进行空间扩展。
BITCOUNT命令使用了查表算法和variable-precision SWAR算法来优化命令的执行效率。
Redis使用SDS来保存位数组。
SDS使用逆序来保存位数组,这种保存顺序简化了SETBIT命令的实现,使得SETBIT命令可以在不移动现有二进制位的情况下,对数组进行空间扩展。
BITCOUNT命令使用了查表算法和variable-precision SWAR算法来优化命令的执行效率。
BITOP命令的所有操作都使用C语言内置的位操作来实现。
第23章:慢查询日志
Redis的慢查询日志功能用于记录执行时间超过给定时长的命令请求,用户可以通过这个功能产生的日志来监视和优化查询速度。
服务器配置有两个和慢查询日志有关的选项:
1)slowlog-log-slower选项指定执行时间超过多少微秒(1秒等于1000000微秒)的命令请求会被记录到日志上。
2)slowlog-max-len选项指定服务器最多保存多少条慢查询日志。
服务器使用先进先出的方式保存多条慢查询日志,当服务器存储的慢查询日志数量等于slowlog-max-len选项的值时,服务器在添加一条新的慢查询日志之前,会先将最旧的一条慢查询日志删除。
Redis服务器将所有的慢查询日志保存在服务器状态的slowlog链表中,每个链表节点都包含一个slowlogEntry结构,每个slowlogEntry结构代表一个慢查询日志。
打印和删除慢查询日志可以通过遍历slowlog链表来完成。
slowlog链表的长度就是服务器所保存慢查询日志的数量。
第24章:监视器
客户端可以通过MONITOR命令,将客户端转换成监视器,接收并打印服务器处理的每个命令请求的相关信息。
每当一个客户端向服务器发送一条命令请求时,服务器除了会处理这条命令请求之外,还会将关于这条命令请求的信息发送给所有监视器。
每当一个客户端向服务器发送一条命令请求时,服务器除了会处理这条命令请求之外,还会将关于这条命令请求的信息发送给所有监视器。
当一个客户端从普通客户端变为监视器时,该客户端的REDIS_MONITOR标识会被打开。
服务器将所有监视器都记录在monitors链表中。
每次处理命令请求时,服务器都会遍历monitors链表,将相关信息发送给监视器。