广告
返回顶部
首页 > 资讯 > 后端开发 > Python >Redisbook学习笔记(1)字典(3
  • 910
分享到

Redisbook学习笔记(1)字典(3

字典学习笔记Redisbook 2023-01-31 03:01:26 910人浏览 八月长安

Python 官方文档:入门教程 => 点击学习

摘要

渐进式rehash在上一节,我们了解了字典的rehash 过程,需要特别指出的是,rehash 程序并不是在激活之后就马上执行直到完成的,而是分多次、渐进式地完成的。假设这样一个场景:在一个有很多键值对的字典里,某个用户在添加新键值对时触发

渐进式rehash

在上一节,我们了解了字典的rehash 过程,需要特别指出的是,rehash 程序并不是在激活之

后就马上执行直到完成的,而是分多次、渐进式地完成的。

假设这样一个场景:在一个有很多键值对的字典里,某个用户在添加新键值对时触发了rehash

过程,如果这个rehash 过程必须将所有键值对迁移完毕之后才将结果返回给用户,这样的处理

方式将是非常不友好的。

另一方面,要求服务器必须阻塞直到rehash 完成,这对于Redis 服务器本身也是不能接受的。

为了解决这个问题,Redis 使用了渐进式(incremental)的rehash 方式:通过将rehash 分散

到多个步骤中进行,从而避免了集中式的计算。

渐进式rehash 主要由_dictRehashStep 和dictRehashMilliseconds 两个函数进行:
. _dictRehashStep 用于对数据库字典、以及哈希键的字典进行被动rehash ;
. dictRehashMilliseconds 则由Redis 服务器常规任务程序(server cron job)执行,用
于对数据库字典进行主动rehash ;
_dictRehashStep
每次执行_dictRehashStep ,ht[0]->table 哈希表第一个不为空的索引上的所有节点就会全
部迁移到ht[1]->table 。

在rehash 开始进行之后(d->rehashidx 不为-1),每次执行一次添加、查找、删除操作,
_dictRehashStep 都会被执行一次:

wKiom1Lfx8-xIvSUAAFG-ophSV4572.jpg

因为字典会保持哈希表大小和节点数的比率在一个很小的范围内,所以每个索引上的节点数量
不会很多(从目前版本的rehash 条件来看,平均只有一个,最多通常也不会超过五个),所以
在执行操作的同时,对单个索引上的节点进行迁移,几乎不会对响应时间造成影响。
dictRehashMilliseconds
dictRehashMilliseconds 可以在指定的毫秒数内,对字典进行rehash 。
当Redis 的服务器常规任务执行时,dictRehashMilliseconds 会被执行,在规定的时间内,
尽可能地对数据库字典中那些需要rehash 的字典进行rehash ,从而加速数据库字典的rehash
进程(progress)。
其他措施
在哈希表进行rehash 时,字典还会采取一些特别的措施,确保rehash 顺利、正确地进行:
 因为在rehash 时,字典会同时使用两个哈希表,所以在这期间的所有查找、删除等操作,
除了在ht[0] 上进行,还需要在ht[1] 上进行。
 在执行添加操作时,新的节点会直接添加到ht[1] 而不是ht[0] ,这样保证ht[0] 的节
点数量在整个rehash 过程中都只减不增。

字典的收缩
上面关于rehash 的章节描述了通过rehash 对字典进行扩展(expand)的情况,如果哈希表的
可用节点数比已用节点数大很多的话,那么也可以通过对哈希表进行rehash 来收缩(shrink)
字典。
收缩rehash 和上面展示的扩展rehash 的操作几乎一样,它执行以下步骤:
1. 创建一个比ht[0]->table 小的ht[1]->table ;
2. 将ht[0]->table 中的所有键值对迁移到ht[1]->table ;
3. 将原有ht[0] 的数据清空,并将ht[1] 替换为新的ht[0] ;
扩展rehash 和收缩rehash 执行完全相同的过程,一个rehash 是扩展还是收缩字典,关键在于
新分配的ht[1]->table 的大小:
. 如果rehash 是扩展操作,那么ht[1]->table 比ht[0]->table 要大;
. 如果rehash 是收缩操作,那么ht[1]->table 比ht[0]->table 要小;
字典的收缩规则由redis.c/htNeedsResize 函数定义:


int htNeedsResize(dict *dict) {
long long size, used;
// 哈希表已用节点数量
size = dictSlots(dict);
// 哈希表大小
used = dictSize(dict);
// 当哈希表的大小大于DICT_HT_INITIAL_SIZE
// 并且字典的填充率低于REDIS_HT_MINFILL 时
// 返回1
return (size && used && size > DICT_HT_INITIAL_SIZE &&
(used*100/size < REDIS_HT_MINFILL));
}

在默认情况下,REDIS_HT_MINFILL 的值为10 ,也即是说,当字典的填充率低于10% 时,程
序就可以对这个字典进行收缩操作了。
字典收缩和字典扩展的一个区别是:
. 字典的扩展操作是自动触发的(不管是自动扩展还是强制扩展);
. 而字典的收缩操作则是由程序手动执行。
因此,使用字典的程序可以决定何时对字典进行收缩:
. 当字典用于实现哈希键的时候,每次从字典中删除一个键值对,程序就会执行一次
htNeedsResize 函数,如果字典达到了收缩的标准,程序将立即对字典进行收缩;
. 当字典用于实现数据库键空间(key space) 的时候, 收缩的时机由
redis.c/tryResizeHashTables 函数决定.

字典其他操作
除了添加操作和伸展/收缩操作之外,字典还定义了其他一些操作,比如常见的查找、删除和更
新。
因为链地址法哈希表实现的相关信息可以从任何一本数据结构算法书上找到,这里不再对字
典的其他操作进行介绍,不过前面对创建字典、添加键值对、收缩和扩展rehash 的讨论已经涵
盖了字典模块的核心内容。

字典的迭代
字典带有自己的迭代器实现——对字典进行迭代实际上就是对字典所使用的哈希表进行迭代:
. 迭代器首先迭代字典的第一个哈希表,然后,如果rehash 正在进行的话,就继续对第二
个哈希表进行迭代。
. 当迭代哈希表时,找到第一个不为空的索引,然后迭代这个索引上的所有节点。
. 当这个索引迭代完了,继续查找下一个不为空的索引,如此循环,一直到整个哈希表都迭
代完为止。
整个迭代过程可以用伪代码表示如下:

def iter_dict(dict):
// 迭代0 号哈希表
iter_table(ht[0]->table)
// 如果正在执行rehash ,那么也迭代1 号哈希表
if dict.is_rehashing(): iter_table(ht[1]->table)
def iter_table(table):
// 遍历哈希表上的所有索引
for index in table:
// 跳过空索引
if table[index].empty():
continue
// 遍历索引上的所有节点
for node in table[index]:
// 处理节点
do_something_with(node)

字典的迭代器有两种:
 安全迭代器:在迭代进行过程中,可以对字典进行修改。
 不安全迭代器:在迭代进行过程中,不对字典进行修改。
以下是迭代器的数据结构定义:


typedef struct dictIterator {
dict *d; // 正在迭代的字典
int table, // 正在迭代的哈希表的号码(0 或者1)
index, // 正在迭代的哈希表数组的索引
safe; // 是否安全?
dictEntry *entry, // 当前哈希节点
*nextEntry; // 当前哈希节点的后继节点
} dictIterator;

小结
 字典由键值对构成的抽象数据结构。
 Redis 中的数据库和哈希键都基于字典来实现。
 Redis 字典的底层实现为哈希表,每个字典使用两个哈希表,一般情况下只使用0 号哈希
表,只有在rehash 进行时,才会同时使用0 号和1 号哈希表。
 哈希表使用链地址法来解决键冲突的问题。
 Rehash 可以用于扩展或收缩哈希表。
 对哈希表的rehash 是分多次、渐进式地进行的。

--结束END--

本文标题: Redisbook学习笔记(1)字典(3

本文链接: https://www.lsjlt.com/news/187161.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Redisbook学习笔记(1)字典(3
    渐进式rehash在上一节,我们了解了字典的rehash 过程,需要特别指出的是,rehash 程序并不是在激活之后就马上执行直到完成的,而是分多次、渐进式地完成的。假设这样一个场景:在一个有很多键值对的字典里,某个用户在添加新键值对时触发...
    99+
    2023-01-31
    字典 学习笔记 Redisbook
  • python学习笔记:字典
     python版本:Python 2.6.6   系统环境:CentOS release 6.2 x86_64   本文参考了互联网上前辈的一些文章   一、字典是python中最灵活的内置数据结构类型,如果把列表看作是有序的对象集合,那么...
    99+
    2023-01-31
    字典 学习笔记 python
  • Redis学习笔记(三) 字典
    Redis的字典使用哈希表作为底层实现,一个哈希表中可以有多个哈希表节点,而每个哈希节点就保存在字典中的一个键值对。 redis字典所用的哈希表由disht结构定义。 typedef struct dictht{ dic...
    99+
    2014-05-20
    Redis学习笔记(三) 字典
  • Python学习笔记1—Python字符
        字符串是python中重要的数据对象    python字符串是以单引号、双引号、或者三个三单引号三个双引号包含的任意的python数据对象都可以称为python字符串    注意:以单引号或双引号包含的数据对象中间不可以换行(若需...
    99+
    2023-01-31
    学习笔记 字符 Python
  • 学习笔记3
    一文件查找和压缩1文件查找locate 搜索依赖于数据库,非实时搜索,搜索新建文件需手动更新,适于搜索稳定不频繁修改文件 find 实时搜索,精确搜索,默认当前目录递归搜索 find用法 -maxdepth...
    99+
    2023-01-31
    学习笔记
  • 学习笔记(3)
    1.* 匹配零个或多个字符(通配符中)2.ls 的-d选项不仅仅可以显示指定目录的信息,还可以用来表示不递归子文件夹。  # ls -dl /etc 显示/etc目录的信息  # ls -d /etc 只显示/etc下面的文件夹3.显示/v...
    99+
    2023-01-31
    学习笔记
  • Python学习笔记(1)
    1 def sum_args(*args): 2 return sum(args)) 3 4 def run_with_positional_args(func, *args): 5 return func(*...
    99+
    2023-01-31
    学习笔记 Python
  • Python学习笔记(1)
    Python开发框架:       a.Python基础;       b.网络编程;       c.WEB框架;       d.设计模式+算法;       e.项目阶段; 开发:   开发语言:       高级语言:Python...
    99+
    2023-01-30
    学习笔记 Python
  • python学习笔记(1
    关于随笔 python随笔只是个人笔记,可能会有遗漏或错误,仅供参考 学习文档地址 https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e5...
    99+
    2023-01-30
    学习笔记 python
  • python学习笔记3:转义字符
    本文列出python中的转义字符,以方便项目参考 转义字符 描述 \(在行尾时) 续行符 \\ 反斜杠符号 \' 单引号 \" 双引号 \a 响铃 \b 退格(Backspace) \e 转义 \00...
    99+
    2023-01-31
    学习笔记 字符 python
  • cisco学习笔记(3)
    1. 交换机支持的命令:交换机基本状态: switch: ;ROM状态, 路由器是rommon>hostname> ;用户模式hostname# ;特权模式...
    99+
    2023-01-31
    学习笔记 cisco
  • OSPF 学习笔记3
    ospf特殊区域 减少LSA洪泛,达到优化路由表的目的 sub区域特点 1、过滤了LSA4/5 2、通过ABR的LSA3学习到一条到达域外的缺省路由(O*IA) 3、区域内所有的路由器都得设置为stub路由器 ...
    99+
    2023-01-31
    学习笔记 OSPF
  • perl学习笔记(3)
    条件结构: if(...){       ...; }elsif(...){       ...; }else{       ...; } 数值关系运算符 ==,>...
    99+
    2023-01-31
    学习笔记 perl
  • shell 学习笔记3
    ####shell结构 #!指定执行脚本的shell #注释行 命令和控制结构  第一步:创建一个包含命令和控制结构的文件  第二步:修改这个文件的权限使它可以执行,chmod u+x...
    99+
    2023-01-31
    学习笔记 shell
  • GEF学习笔记3
    八、创建嵌套的视图 前面的步骤,创建了公司视图,下面再创建一个国家视图用来容纳公司视图。这就需要按前面的方法把MVC都重新创建一遍。 Model View(Figure) Control(EditPart) 注意重写红框中标...
    99+
    2023-01-31
    学习笔记 GEF
  • PowerShell 学习笔记(3)
    获取对象的过程中,最好先筛选出对象,再进行操作。(即筛选在排序左边)不区分大小写get-process | where {$_.handles –ge 1000}使用where获取所有对象,用对象执行大括号里的代码,如果...
    99+
    2023-01-31
    学习笔记 PowerShell
  • PHP 学习笔记 (3)
    昨天笔记2说道了PHP的标记以及短标记,今天记录下如何吧PHP从HTML分离手册参考:http://www.php.net/manual/zh/language.basic-syntax.phpmode.phpPHP手册告诉我们,PHP凡是...
    99+
    2023-01-31
    学习笔记 PHP
  • CCNP学习笔记(3)
    一、RIPv2:Routing Information Protocol 路由信息协议 1.特性: ①属于“距离矢量”路由协议 ②定期发送路由更新(30S一次,路由表中所有路由) ③依据“跳数”衡量路径好坏 ...
    99+
    2023-01-31
    学习笔记 CCNP
  • python学习笔记(3)
    在大概了解了程序之后,我也买了本python书学习一下,因为现在新版的python3.4.0已经不再兼容2.x.x的内容,书虽然很新,但是有些例子还是用的过去的。1.比如在3.0中print 42不能再产生输出了,要改成print(42)&...
    99+
    2023-01-31
    学习笔记 python
  • shell学习笔记(3)
    一、if基础 1、单分支 1.1 语法 if语句语法 单分支结构语法: if [条件]; then 指令 fi 或 if [条件] then ...
    99+
    2023-01-31
    学习笔记 shell
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作