Redis源代码分析(23)--- CRC循环冗余算法RAND随机数的算法
他今天就开始学习Redis源代码的一些工具来实现,在任何一种语言工具。算法实现的原理应该是相同的,一些比較经典的算法。比方说我今天看的Crc循环冗余校验算法和rand随机数产生算法。
CRC算法全称循环冗余校验算法。CRC校验的基本思想是利用线性编码理论,在发送端依据要传送的k位二进制码序列,以一定的规则产生一个校验用的监督码(既CRC码)r位,并附在信息后边,构成一个新的二进制码序列数共(k+r)位,最后发送出去。
在接收端, 则依据信息码和CRC码之间所遵循的规则进行检验,以确定传送中是否出错。
16位的CRC码产生的规则是先将要发送的二进制序列数左移16位(既乘以 )后,再除以一个多项式,最后
所得到的余数既是CRC码。在Redis中实现的冗余校验算法为字节型算法;
字节型算法的一般描写叙述为:本字节的CRC码。等于上一字节CRC码的低8位左移8位,与上一字节CRC右移8位同本字节异或后所得的CRC码异或。
字节型算法例如以下:
1)CRC寄存器组初始化为全"0"(0x0000)。(注意:CRC寄存器组初始化全为1时,最后CRC应取反。)
2)CRC寄存器组向左移8位,并保存到CRC寄存器组。
3)原CRC寄存器组高8位(右移8位)与数据字节进行异或运算,得出一个指向值表的索引。
4)索引所指的表值与CRC寄存器组做异或运算。
5)数据指针加1,假设数据没有所有处理完,则反复步骤2)。
6)得出CRC。
我们来相应一下在Redis中的代码,全然符合;
/* Crc64循环冗余运算算法,crc:基础值0,s:传入的内容,l:内容长度 */
uint64_t crc64(uint64_t crc, const unsigned char *s, uint64_t l) {
uint64_t j; for (j = 0; j < l; j++) {
uint8_t byte = s[j];
crc = crc64_tab[(uint8_t)crc ^ byte] ^ (crc >> 8);
}
return crc;
}
Redis内置的样例。
/* Test main */
/* 測试的代码 */
#ifdef TEST_MAIN
#include <stdio.h>
int main(void) {
printf("e9c6d914c4b8d9ca == %016llx\n",
(unsigned long long) crc64(0,(unsigned char*)"123456789",9));
return 0;
}
对字符串1到9做冗余运算。
以下说说Redis中的随机算法实现的原理,一開始以为是调用的是math.Rand()方法,后来发现,我真的是错了。作者给出的理由是:
/* Pseudo random number generation functions derived from the drand48()
* function obtained from pysam source code.
*
* This functions are used in order to replace the default math.random()
* Lua implementation with something having exactly the same behavior
* across different systems (by default Lua uses libc's rand() that is not
* required to implement a specific PRNG generating the same sequence
* in different systems if seeded with the same integer).
*
* The original code appears to be under the public domain.
* I modified it removing the non needed functions and all the
* 1960-style C coding stuff...
*
* 随机函数在不同的系统可能会表现出不同的行为,作者就没有採用系统自带的math.random,
* ,而是基于drand48()随机算法,重写了随机函数行为,作者在重写随机代码的时候取出了不须要的方法
* ----------------------------------------------------------------------------
也就是说作者是重写了随机算法。基于的算法实现是drand48()算法。
由于此算法用到了48位的数字所以用此名。
srand48和drand48是Unix库函数,drand48的作用是产生[0,1]之间均匀分布的随机数。採用了线性同余法和48位整数运算来产生伪随机序列函数用上面的算法产生一个48位的伪随机整数,然后再取出此整数的高32位作为随机数,然后将这个32位的伪随机数规划到[0,1]之间,用函数srand48来初始化drand48(),其仅仅对于48位整数的高32位进行初始化。而其低16位被设定为随机值。这是一种统计特性比較好的伪随机发生器。这2个函数原版的C语言实现:
#ifndef DRAND48_H
#define DRAND48_H #include <stdlib.h> #define m 0x100000000LL
#define c 0xB16
#define a 0x5DEECE66DLL static unsigned long long seed = 1; double drand48(void)
{
seed = (a * seed + c) & 0xFFFFFFFFFFFFLL;
unsigned int x = seed >> 16;
return ((double)x / (double)m); } void srand48(unsigned int i)
{
seed = (((long long int)i) << 16) | rand();
} #endif
由于这里还是用到了系统的rand()函数,z作者全然没实用系统自带的,所以在Redis中这里的实现就略有不同了:
int32_t redisLrand48() {
next();
return (((int32_t)x[2] << (N - 1)) + (x[1] >> 1));
}
/* 设置种子 */
void redisSrand48(int32_t seedval) {
SEED(X0, LOW(seedval), HIGH(seedval));
}
static void next(void) {
uint32_t p[2], q[2], r[2], carry0, carry1;
MUL(a[0], x[0], p);
ADDEQU(p[0], c, carry0);
ADDEQU(p[1], carry0, carry1);
MUL(a[0], x[1], q);
ADDEQU(p[1], q[0], carry0);
MUL(a[1], x[0], r);
x[2] = LOW(carry0 + carry1 + CARRY(p[1], r[0]) + q[1] + r[1] +
a[0] * x[2] + a[1] * x[1] + a[2] * x[0]);
x[1] = LOW(p[1] + r[0]);
x[0] = LOW(p[0]);
}
详细next实现,谈到来源。各种4和操作的操作。
版权声明:本文博客原创文章,博客,未经同意,不得转载。
Redis源代码分析(23)--- CRC循环冗余算法RAND随机数的算法的更多相关文章
- redis 源代码分析(一) 内存管理
一,redis内存管理介绍 redis是一个基于内存的key-value的数据库,其内存管理是很重要的,为了屏蔽不同平台之间的差异,以及统计内存占用量等,redis对内存分配函数进行了一层封装,程序中 ...
- Redis源代码分析(十一年)--- memtest内存测试
今天,我们继续redis源代码test下测试在封装中的其它文件.今天读数memtest档,翻译了,那是,memory test 存储器测试工具..可是里面的提及了非常多东西,也给我涨了非常多见识,网上 ...
- Redis源代码分析(一)--Redis结构解析
从今天起,本人将会展开对Redis源代码的学习,Redis的代码规模比較小,很适合学习,是一份很不错的学习资料,数了一下大概100个文件左右的样子,用的是C语言写的.希望终于能把他啃完吧,C语言好久不 ...
- Redis源代码分析(二十四)--- tool工具类(2)
在上篇文章中初步的分析了一下,Redis工具类文件里的一些使用方法,包含2个随机算法和循环冗余校验算法,今天,继续学习Redis中的其它的一些辅助工具类的使用方法.包含里面的大小端转换算法,sha算法 ...
- Redis源代码分析(十二)--- redis-check-dump本地数据库检測
这个文件我在今天分析学习的时候,一直有种似懂非懂的感觉,代码量700+的代码,最后开放给系统的就是一个process()方法.这里说的说的数据库检測,是针对key的检測,会用到,以下提到的结构体: / ...
- CRC循环冗余检测C语言实现----花了几天时间乱写的
由于笔者目前正在上计算机网络的课,老师要我们编一下crc的循环检测过程,所以我想着刚好在学c,那就随便看看写不写的了,首先百度了一下网上资料,基本都是用位移运算符实现的,由于本人懒得去看一下位移运算, ...
- Redis源代码分析(三)---dict哈希结构
昨天分析完adlist的Redis代码.今天立即马不停蹄的继续学习Redis代码中的哈希部分的结构学习,只是在这里他不叫什么hashMap,而是叫dict.并且是一种全新设计的一种哈希结构,他仅仅是通 ...
- Redis源代码分析(三十五)--- redis.c服务端的实现分析(2)
在Redis服务端的代码量真的是比較大,假设一个一个API的学习怎么实现,无疑是一种效率非常低的做法,所以我今天对服务端的实现代码的学习,重在他的运行流程上.而对于他的模块设计在上一篇中我已经分析过了 ...
- Redis源代码分析(十三)--- redis-benchmark性能測试
今天讲的这个是用来给redis数据库做性能測试的,说到性能測试,感觉这必定是高大上的操作了.redis性能測试.測的究竟是哪方面的性能,怎样測试,通过什么指标反映此次測试的性能好坏呢.以下我通过源代码 ...
随机推荐
- [置顶] ※数据结构※→☆线性表结构(stack)☆============栈 序列表结构(stack sequence)(六)
栈(stack)在计算机科学中是限定仅在表尾进行插入或删除操作的线性表.栈是一种数据结构,它按照后进先出的原则存储数据,先进入的数据被压入栈底,最后的数据在栈顶,需要读数据的时候从栈顶开始弹出数据.栈 ...
- hdu-4833-Best-Financing(DP)
Best Financing Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- ubuntu下ssh使用 与 SCP 使用
1 ssh远程登录服务器 ssh username@remote_ip #将username换成自己的用户名,将remote_ip换成远程服务器的ip地址 2 将文件/文件夹从远程服务器拷至本地(sc ...
- Tier和Layer
在实际开发工作中.我们经常听到"架构设计"和"架构师"这种名词,它并不新奇和神奇,可是却非常少有人对"架构"有全面的了解和认识.更谈不上掌握 ...
- C++——STL中三种顺序容器的简要差别
C++ STL 提供了3个顺序容器 :vector, deque, list Vector动态数组.支持高速訪问:list双向链表,支持高速插入和删除. vector 中的元素是顺序存放的.所以随机訪 ...
- LeetCode——Valid Sudoku
Determine if a Sudoku is valid, according to: Sudoku Puzzles - The Rules. The Sudoku board could be ...
- iOS使用CoreImage处理图像40中可用的滤镜名称
NSString* localPath = [[NSBundle mainBundle] pathForResource:@"1" ofType:@"jpg"] ...
- 隐马尔科夫模型(HMM)及事实上现
马尔科夫模型 马尔科夫模型是单重随机过程,是一个2元组:(S,A). 当中S是状态集合,A是状态转移矩阵. 仅仅用状态转移来描写叙述随机过程. 马尔科夫模型的2个如果 有限历史性如果:t+l时刻系统状 ...
- VS2015配置Andriod开发环境
原文:VS2015配置Andriod开发环境 折腾了好久终于配置OK了,分享给大家! 第一步: http://xamarin.com/download下载XamarinInstaller 第二步: 运 ...
- javascript实现的一个信息提示的小功能/
//什么状况.CSDN的排版怎么这么多状况,还是本人太次?调整几次都没弄好.最后一遍了-- 最近由于公司业务问题.须要做一些面向公众的平台,于是对UI要求会高一点, 对于传统的alert的这样的方式来 ...