Redis设计与实现(一~五整合版)(6)

至于主动脱离,更简单了,通过redis的cron job来检查时间,对于过期的blocking客户端,直接释放即可。伪代码如下:

def server_cron_job(): # cron_job其他操作 ... # 遍历所有已连接客户端 for client in server.all_connected_client: # 如果客户端状态为“正在阻塞”,并且最大阻塞时限已到达 if client.state == BLOCKING and \ client.max_blocking_timestamp < current_timestamp(): # 那么给客户端发送空回复, 脱离阻塞状态 client.send_empty_reply() # 并清除客户端在服务器上的阻塞信息 server.blocking_keys.remove_blocking_info(client) # cron_job其他操作 ... 5. 集合

这个就是set,底层实现有2种:

REDIS_ENCODING_INTSET

REDIS_ENCODING_HT(字典)

对于集合来说,和前面的2种不同点在于,集合的编码是决定于第一个添加进集合的元素:

如果第一个添加进集合的元素是long long类型的,那么编码就使用第一种

否则使用第二种

同样,切换也需要达到一个阈值:

intset保存的整数值个数超过server.set_max_intset_entries(默认值为512)

从第二个元素开始,如果插入的元素类型不是long long的,就要转化成第二种

然后对于集合,有3个操作的算法很好玩,但是因为没用到过,就暂时列一下:

6. 有序集

终于看到最后一个数据结构了,虽然只有5个- -。。。。首先从命令上就可以区分这几种了:

GET/SET是字符串

H开头的是哈希表

L开头的是列表

S开头的是集合

Z开头的是有序集

继续说有序集,这个东西我还真的没用过。。。其他最起码都了解过,这个算是第一次接触。现在看来,它也算一个sort过的map,sort的依据就是score,对score排序后得到的集合。

首先还是底层实现,有2种:

REDIS_ENCODING_ZIPLIST

REDIS_ENCODING_SKIPLIST

这个竟然用到了跳跃表,不用这个的话,跳跃表好像都快被我忘了呢。。对于编码的选择,和集合类似,也是决定于第一个添加进有序集的元素:

如果满足:1.服务器属性server.zset_max_ziplist_entries值大于0(默认为128)2.元素的member长度小于服务器属性server.zset_max_ziplist_value(默认为64),就以第一种作为底层数据结构

否则使用第二种

对于编码的转换阈值是这样的:

ziplist保存的元素数量超过服务器属性server.zset_max_ziplist_entries的值(默认为128)

ziplist的元素长度大于服务器属性server.zset_max_ziplist_value(默认为64)

那我们知道,如果有序集是用ziplist实现的,而ziplist终对于member和score是按次序存储的,如member1,score1,member2,score2...这样的。那么,检索时候就蛋疼了,肯定是O(N)复杂度,既然这样,效率一下子就没有了。庆幸的是,转换成跳跃表之后,redis搞的很高明:

它用一个字典和一个跳跃表同时来存储有序集的元素,而且因为member和score是在内存区域其字典有指针,就可以共享一块内存,不用每个元素复制两份。

通过使用字典结构,并将 member 作为键,score 作为值,有序集可以在 O(1) 复杂度内:

检查给定member是否存在于有序集(被很多底层函数使用)

取出 member 对应的 score 值(实现 ZSCORE 命令)

通过使用跳跃表,可以让有序集支持以下两种操作:

在 O(logN) 期望时间、O(N) 最坏时间内根据 score 对 member 进行定位(被很多底层函数使用)

范围性查找和处理操作,这是(高效地)实现 ZRANGE 、ZRANK 和 ZINTERSTORE等命令的关键

通过同时使用字典和跳跃表,有序集可以高效地实现按成员查找和按顺序查找两种操作。所以,对于有序集来说,redis的思路确实是很流弊的。

7. 总结

上面几个小节讲述了redis的数据结构的底层实现,但是没有涉及到具体的命令,如果调研后发现redis的某种数据结构满足需求,就可以对症下药,去查看redis对应的API即可。

四 前言

这一章主要讲解redis内部的一些功能,主要分为以下4个:

那么,我们就来逐个击破!

1. 事务

事务对于刚接触计算机的人来说可能会比较抽象。因为事务是对计算机某些操作的称谓。通俗来说,事务就是一个命令、一组命令执行的最小单元。事务一般具有ACID属性(redis只支持两种,下文详细说明):

原子性(atomicity):一个事务是一个不可分割的最小工作单位,事务中包括的诸操作要么都做,要么都不做。

一致性(consistency):事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/6be4ac5bc3f297e5261a68427fc4282e.html