REDIS源码中一些值得学习的技术细节02

1. Redis中散列函数的实现:

Redis针对整数key和字符串key,采用了不同的散列函数

对于整数key,redis使用了 Thomas Wang的 32 bit Mix Function,实现了dict.c/dictIntHashFunction函数:

 1 /* Thomas Wang‘s 32 bit Mix Function */
 2 unsigned int dictIntHashFunction(unsigned int key)
 3 {
 4     key += ~(key << 15);
 5     key ^=  (key >> 10);
 6     key +=  (key << 3);
 7     key ^=  (key >> 6);
 8     key += ~(key << 11);
 9     key ^=  (key >> 16);
10     return key;
11 }

这段代码的妙处我还没来得及仔细研究,等研究好了会在这里补上,不过找到了两个初看还不错的链接:

首先是Thomas Wang大神本人的链接:

http://web.archive.org/web/20071223173210/http://www.concentric.net/~Ttwang/tech/inthash.htm

再者是他人根据上面链接和其他资料写的总结

http://blog.csdn.net/jasper_xulei/article/details/18364313

对于字符串形式的key,redis使用了MurmurHash2算法和djb算法:

MurmurHash2算法对于key是大小写敏感的,而且在大端机器和小端机器上生成结果不一致

redis的dict.c/dictGenHashFunction是MurmurHash2算法的C语言实现:

 1 unsigned int dictGenHashFunction(const void *key, int len) {
 2     /* ‘m‘ and ‘r‘ are mixing constants generated offline.
 3      They‘re not really ‘magic‘, they just happen to work well.  */
 4     uint32_t seed = dict_hash_function_seed;
 5     const uint32_t m = 0x5bd1e995;
 6     const int r = 24;
 7
 8     /* Initialize the hash to a ‘random‘ value */
 9     uint32_t h = seed ^ len;
10
11     /* Mix 4 bytes at a time into the hash */
12     const unsigned char *data = (const unsigned char *)key;
13
14     while(len >= 4) {
15         uint32_t k = *(uint32_t*)data;
16
17         k *= m;
18         k ^= k >> r;
19         k *= m;
20
21         h *= m;
22         h ^= k;
23
24         data += 4;
25         len -= 4;
26     }
27
28     /* Handle the last few bytes of the input array  */
29     switch(len) {
30     case 3: h ^= data[2] << 16;
31     case 2: h ^= data[1] << 8;
32     case 1: h ^= data[0]; h *= m;
33     };
34
35     /* Do a few final mixes of the hash to ensure the last few
36      * bytes are well-incorporated. */
37     h ^= h >> 13;
38     h *= m;
39     h ^= h >> 15;
40
41     return (unsigned int)h;
42 }

而redis则借助djb函数实现了不区分大小写的散列函数dict.c/dictGenCaseHashFunction:

1 unsigned int dictGenCaseHashFunction(const unsigned char *buf, int len) {
2     unsigned int hash = (unsigned int)dict_hash_function_seed;
3
4     while (len--)
5         hash = ((hash << 5) + hash) + (tolower(*buf++)); /* hash * 33 + c */
6     return hash;
7 }

以上三个散列函数(dictIntHashFunction, dictIntHashFunction, dictGenCaseHashFunction)分别用在了redis的不同地方,用以实现了不同场合下的散列需求,接下来将会详细介绍。

2.Redis中不同场合下几种不同散列函数的使用

时间: 2024-10-26 10:25:46

REDIS源码中一些值得学习的技术细节02的相关文章

Redis源码中探秘SHA-1算法原理及其编程实现

导读 SHA-1算法是第一代"安全散列算法"的缩写,其本质就是一个Hash算法.SHA系列标准主要用于数字签名,生成消息摘要,曾被认为是MD5算法的后继者.如今SHA家族已经出现了5个算法.Redis使用的是SHA-1,它能将一个最大2^64比特的消息,转换成一串160位的消息摘要,并能保证任何两组不同的消息产生的消息摘要是不同的.虽然SHA1于早年间也传出了破解之道,但作为SHA家族的第一代算法,对我们仍然很具有学习价值和指导意义. SHA-1算法的详细内容可以参考官方的RFC:ht

多个Android项目源码-覆盖方方面面值得学习

Android PDF 阅读器 http://sourceforge.net/projects/andpdf/files/个人记账工具 OnMyMeans http://sourceforge.net/projects/onmymeans/developAndroid电池监控 Android Battery Dog http://sourceforge.net/projects/andbatdog/RSS阅读软件 Android RSS http://code.google.com/p/andr

Redis源码中的CRC校验码(crc16、crc64)原理浅析

在阅读Redis源码的时候,看到了两个文件:crc16.c.crc64.c.下面我抛砖引玉,简析一下原理. CRC即循环冗余校验码,是信息系统中一种常见的检错码.大学课程中的"计算机网络"."计算机组成"等课程中都有提及.我们可能都了解它的数学原理,在试卷上手工计算一个CRC校验码,并不是难事.但是计算机不是人,现实世界中的数学原理需要转化为计算机算法才能实现目的.实际上作为计算机专业背景人并不会经常使用或接触到CRC的计算机算法实现的原理,通常是电子学科背景的人士

详解Redis源码中的部分快速排序算法(pqsort.c)

看标题,你可能会疑惑:咦?你这家伙,怎么不讲解完整的快排,只讲一部分快排---.- 哎,冤枉."部分快排"是算法的名字,实际上本文相当详细呢.本文几乎与普通快排无异.看懂了本文,你对普通的快排也会有更深的认识了. 快速排序算法(qsort)的原理我们大都应该了解.本文介绍的是部分快速排序算法.其实其算法本质是一样的,只不过限定了排序的左右区间,也就是只对一个数字序列的一部分进行排序,故称为"部分快速排序算法",简称:pqsort Redis项目中的pqsort.c

Redis源码分析(二十三)--- CRC循环冗余算法和RAND随机数算法

今天开始研究Redis源码中的一些工具类的代码实现,工具类在任何语言中,实现的算法原理应该都是一样的,所以可以借此机会学习一下一些比较经典的算法.比如说我今天看的Crc循环冗余校验算法和rand随机数产生算法. CRC算法全称循环冗余校验算法.CRC校验的基本思想是利用线性编码理论,在发送端根据要传送的k位二进制码序列,以一定的规则产生一个校验用的监督码(既CRC码)r位,并附在信息后边,构成一个新的二进制码序列数共(k+r)位,最后发送出去.在接收端, 则根据信息码和CRC码之间所遵循的规则进

玩一把redis源码(一):为redis添加自己的列表类型

2019年第一篇文档,为2019年做个良好的开端,本文档通过step by step的方式向读者展示如何为redis添加一个数据类型,阅读本文档后读者对redis源码的执行逻辑会有比较清晰的认识,并且可以深入理解redis 源码中关于链表数据结构的使用,写这篇文档作者获益良多,阅读系统软件源码的兴趣也大大提高. 同时也再次感受到良好的基础是深入学习的前提.特别强调本文档仅用于学习,并非是要修改redis源码. 建议读者阅读本文档时实际动手敲一下代码,然后翻阅下redis源码,debug下redi

redis 源码分析(一) 内存管理

一,redis内存管理介绍 redis是一个基于内存的key-value的数据库,其内存管理是非常重要的,为了屏蔽不同平台之间的差异,以及统计内存占用量等,redis对内存分配函数进行了一层封装,程序中统一使用zmalloc,zfree一系列函数,其对应的源码在src/zmalloc.h和src/zmalloc.c两个文件中,源码点这里. 二,redis内存管理源码分析 redis封装是为了屏蔽底层平台的差异,同时方便自己实现相关的函数,我们可以通过src/zmalloc.h 文件中的相关宏定义

Redis源码解析:15Resis主从复制之从节点流程

Redis的主从复制功能,可以实现Redis实例的高可用,避免单个Redis 服务器的单点故障,并且可以实现负载均衡. 一:主从复制过程 Redis的复制功能分为同步(sync)和命令传播(commandpropagate)两个操作: 同步操作用于将从节点的数据库状态更新至主节点当前所处的数据库状态: 命令传播操作则用于在主节点的数据库状态被修改,导致主从节点的数据库状态不一致时,让主从节点的数据库重新回到一致状态: 1:同步 当客户端向从节点发送SLAYEOF命令,或者从节点的配置文件中配置了

如何阅读 Redis 源码?ZZ

原文链接 在这篇文章中, 我将向大家介绍一种我认为比较合理的 Redis 源码阅读顺序, 希望可以给对 Redis 有兴趣并打算阅读 Redis 源码的朋友带来一点帮助. 第 1 步:阅读数据结构实现 刚开始阅读 Redis 源码的时候, 最好从数据结构的相关文件开始读起, 因为这些文件和 Redis 中的其他部分耦合最少, 并且这些文件所实现的数据结构在大部分算法书上都可以了解到, 所以从这些文件开始读是最轻松的.难度也是最低的. 下表列出了 Redis 源码中, 各个数据结构的实现文件: 文