Redis 独立功能实现

发布与订阅

SUBSCRIBE命令:RedisServer维护一个pubsub_channels的字典用以实现频道订阅的功能。键为频道channels,值为订阅频道的客户端链表

PSUBSCRIBE命令:维护一个pubsub_patterns的链表,链表中的节点保存了pattern和客户端。

UNSUBSCRIBE命令:退订频道,删除字典中值存储的链表中的一个节点

PUNSUBSCRIBE命令:退订频道模式,删除pubsub_patterns链表中的一个节点

PUBLISH命令:在pubsub_channels中找到channel与其对应的客户端链表,把消息发送给所有的节点;从pubsub_patterns链表中遍历所有的节点,把消息发送给匹配该channel的模式的所有节点。

PUBSUB命令:查看订阅信息

PUBSUB CHANNELS //查看所有的频道,pubsub_channels 字典中的键

PUBSUB NUMSUB [channel1 channel2 ...] //查看对应订阅频道的客户端

PUBSUB NUMPAT //当前服务器被订阅模式的数量,pubsub_patterns.length

事务

Redis 的事务非常简单,因为是单线程的执行命令。所以执行事务时只要保证提交命令的过程中保存在数据库中的值没有修改,这个可以使用WATCH命令进行检查被监视的键是否被更改。

一个事务的开启使用命令MULTI,之后服务器会等待客户端进行命令的提交,从MULTI往后所有的命令都不会立即执行,将会存入命令队列中,知道执行EXEC命令,EXEC命令执行时会将之前入队的命令一次性的、按顺序的执行,由于REDIS的执行机制式单线程的,所以他保证了EXEC执行所有命令时是一次性的。

当然还有一个问题是,在一个客户端提交事务处理命令的时候,另一个客户端执行了一个更改尚未提交事务中相关键值的命令。这个时候可以使用WATCH进行监视键的修改情况,如果提交(执行)事务时其所监视的键已被更改,服务器将拒绝执行事务。由于这是在执行入队命令之前的检查,所有不需要执行队列中的任何命令,所以Redis没有关系数据库中的回滚操作。

当然如果不是监视的键值被修改,而是入队的命令执行出错的话,Redis事务会继续执行,没有回滚,据Redis作者在文档中解释,不支持事务回滚是因为这种复杂的功能和Redis 追求简单高效的设计主旨不相符, 并且他认为, Redis 事务的执行时错误通常都是编程错误产生的, 这种错误通常只会出现在开发环境中, 而很少会在实际的生产环境中出现,所以他认为没有必要为Redis 开发事务回滚功能。

Lua脚本

EVAL 命令执行Lua脚本

排序

SORT命令

ALPHA选项

SORT <key> ALPHA 对包含字符串值的键进行排序

BY选项

MSET apple-price 8 banana-price 5.5 cherry-price 9

MSET:同时设置多个键值对

SADD fruits “apple” “banana” “cherry”

SORT fruits BY *-price

BY 可以按照给定的pattern的值来排序

LIMIT选项

GET选项

get选项类似于关系数据库中的字段,先通过select查找一个字段值,再根据这个字段查找另一个关联表的字段。

SORT fruits  ALPHA
结果为:
1)"apple" 
2)"banana" 
3)"cherry"

SORT fruits  ALPHA GET *-price
结果为:
1)8
2)5.5
3)9

STORE选项

可以将结果保存到指定的键中

SORT fruits ALPHA STORE fruits-sort

多个选项的执行顺序

二进制位数组

Redis 提供了SETBIT 、GETBIT 、BITCOUNT 、BITOP 四个命令用于处理二进制位数组。

redis> SETBIT bit 0 1   # 0000 0001
(integer) 0

//0 代表第0位,这个字节的第一位,从后往前数

Redis使用字符串对象来表示位数组,SDS数据结构就是二进制的,所以直接使用SDS的数据结构。

SETBIT key offset value通过计算偏移量的位置进行设置(对8取余决定是buf的第几个元素,再根据余数确定位置)

BITTOP

BITTOP OR

BITTOP AND

BITTOP XOR

BITTOP NOT

这些命令实际上都是c语言的 & | ^ ~来实现的,因为C允许对字节直接进行逻辑操作

慢查询日志

Redis慢查询日志功能用于记录执行时间超过给定时长的命令请求

监视器

MONITOR命令可以将一个客户端变为一个监视器,实时的接收并打印出当前服务器处理的命令请求的相关信息。