为什么要阅读源代码?

起因是看了“伯乐在线”上的两篇博客,《向优秀代码学习:Redis源码概览》《阅读优秀代码是提高开发人员修为的一种捷径》。 我只对c语言比较熟悉,虽然已经读过了很多c语言名著,比如说《c和指针》、《c专家编程》,c语言的语法已经基本了解,但是自己仍然写不出漂亮的代码,这一点在做“编译原理”课程设计的时候表现的尤为突出。老师要求我们实现一个编译器,我第一次用c语言写大型的程序,结果我对源文件的管理和变量的定义一塌糊涂,最后实在是写不下去了,只能草草了事。

所以,我想通过阅读比较优秀的源代码,学习源程序文件的组织和管理以及变量名的定义。选择Redis是因为它是一个主要用ANSI c开发的开源项目,可以获得它的源代码。1.0版本是Redis的第一个稳定版本,鉴于自己水平有限,所以先从这个版本开始阅读。

Redis-1.0下载地址

Redis介绍

该部分翻译自Redis-1.0源代码中的doc。

介绍

Redis是一个数据库。更准确的说,它是一个小型的数据库,实现了一个”key”与”value”相关联的字典。比如说,我可以把key “surname_1992”关联到value “Smith”上。有趣的事情是,关联到key上的value类型并不局限于简单的strings,还可以是lists和sets,为这些类型提供了一系列的运行于服务器端的原子操作。 Redis将整个数据集存储在内存中,但是数据集可以异步的持久化到硬盘上。每次服务器重启的时候,备份就会被重新加载。 Redis保存数据集的操作是可配置的,你可以配置它在经过给定的秒数或对数据集操作多少次之后来保存数据集。比如说,你可以让Redis在操作数据集1000次并且至少经过60秒之后保存数据集。你可以设置这个组合操作的次数。 因为数据写操作是异步的,如果系统崩溃,上几次的查询操作会丢失(不过,这在很多应用中都是可以接受的)。但是,如果你的应用连丢失几条记录都是不可接受的,Redis提供了另外的解决方案,它支持master-slave复制操作。

超越了key-value数据库

在大多数的key-value数据库中,key和value都是简单的strings类型。Redis的key也是strings类型,但是value可以是Strings、Lists、Sets类型,对这些类型。Redis都提供了一些命令来实现复杂的原子操作,所以你可以认为Redis是一个数据结构服务器。 比如说,你可以用LPUSH和RPUSH操作添加元素到key为“mylist”的list中,复杂度为O(1)。而后,你还以用LRANGE得到元素的范围,或者用LTRIM命令减少元素数目。Sets也很灵活,你可以对Sets(无序的字符串集合)添加和删除元素,然后让服务器端对Sets进行交、并、补操作。 所有的这些特征,对Lists和Sets排序的支持,可以允许你将Redis作为你的可扩展的应用的数据库,而不需要使用关系数据库。

Redis与Memcached的不同之处有哪些?

主要有以下两点: Memcached不能持久化,它仅仅是把所有的东西都放在内存中,但不保存,因为它主要用来作为cache.Redis可以用来作为应用程序的主要数据库。 和Memcached一样,Redis使用key-value模型,key是strings类型,但是value可以是lists和sets类型。而且可以进行复杂的操作,比如说,交操作,设置/获取lists中的第n个元素。也可以使用lists作为消息队列。

Redis支持锁操作吗?

不支持,Redis提供了原子原语,这样,程序员就可以使用“无锁”算法来使用Redis.想象一下,你有十台电脑和一个Redis服务器。你要计算一个很大的文本文件的单词数目,该文本划分到10台电脑,每台电脑只处理一部分,使用INCR命令就可以在每次发现一个单词对计数器加一。 Redis还支持其他的原子原语,比如说lists的PUSH/POP操作,POP RANDOM KEY UPDATE操作等。

多数据库支持

另一个同步原语是支持多数据库。每一个新连接默认选择“DB 0”,但是使用“SELECT”命令可以选择不同的数据库。“MOVE”操作可以将一个item原子地 从一个数据库移到另一个。和“RANDOMKEY”命令一起使用可以当作”无锁”算法的基础。

Redis数据类型

Redis支持将以下三种类型作为value的类型: Strings: 字节序列。Redis的Strings是二进制安全的,所以它可以不仅可以存储文本,图像、压缩数据和其他任何东西都可以存储。 Lists:字符串列表,支持的操作有在头部添加元素,在尾部添加元素,获取列表长度,得到元素的范围,将列表截取到指定的长度,将列表排序等等。 Sets:无序的字符串集合。支持向集合中添加、删除元素,还支持集合间的交、并、差等操作。 value的类型可以是Strings、Lists、Sets。key的类型是Strings的子集,但不包含换行符(‘\n’)和空格(‘ ’)。 注意:有时候Strings中可以包含数字值,但是必须能够被Redis解析。比如说INCR命令被用来自动增加存储在指定key中的数值。这种情况下,Redis能够处理的处理的整数必须要能存储在“long long”类型中,”long long”代表64位无符号整数。

实现细节

Stings类型是用自动分配内存的字符串来实现的。Lists使用缓存长度的双链表实现的。Sets使用哈希表来实现,并采用链地址法来解决冲突。

(结束)