Redis源码分析(一)--Redis结构解析,redis--redis


           从今天起,本人将会展开对Redis源码的学习,Redis的代码规模比较小,非常适合学习,是一份非常不错的学习资料,数了一下大概100个文件左右的样子,用的是C语言写的。希望最终能把他啃完吧,C语言好久不用,快忘光了。分析源码的第一步,先别急着想着从哪开始看起,先浏览一下源码结构,可以模块式的渐入,不过比较坑爹的是,Redis的源码全部放在在里面的src目录里,一下90多个文件统统在里面了,所以我选择了拆分,按功能拆分,有些文件你看名字就知道那是干什么的。我拆分好后的而结果如下:


11个包,这样每个包中的文件就比较可接受了,但是分出这个类别,我也是花了一定时间,思考了下,Redis下的主要的一些文件的特征,最后定的,应该算是比较全的了。

下面开始一个包一个包的介绍:


test:(测试)
1.memtest.c 内存检测
2.redis_benchmark.c 用于redis性能测试的实现。
3.redis_check_aof.c 用于更新日志检查的实现。
4.redis_check_dump.c 用于本地数据库检查的实现。
5.testhelp.c 一个C风格的小型测试框架。


struct:(结构体)
1.adlist.c 用于对list的定义,它是个双向链表结构
2.dict.c 主要对于内存中的hash进行管理
3.sds.c 用于对字符串的定义
4.sparkline.c 一个拥有sample列表的序列
5.t_hash.c hash在Server/Client中的应答操作。主要通过redisObject进行类型转换。
6.t_list.c list在Server/Client中的应答操作。主要通过redisObject进行类型转换。
7.t_set.c  set在Server/Client中的应答操作。主要通过redisObject进行类型转换。
8.t_string.c string在Server/Client中的应答操作。主要通过redisObject进行类型转换。
9.t_zset.c zset在Server/Client中的应答操作。主要通过redisObject进行类型转换。
10.ziplist.c  ziplist是一个类似于list的存储对象。它的原理类似于zipmap。
11.zipmap.c  zipmap是一个类似于hash的存储对象。


data:(数据操作)
1.aof.c 全称为append only file,作用就是记录每次的写操作,在遇到断电等问题时可以用它来恢复数据库状态。
2.config.c 用于将配置文件redis.conf文件中的配置读取出来的属性通过程序放到server对象中。
3.db.c对于Redis内存数据库的相关操作。
4.multi.c用于事务处理操作。
5.rdb.c  对于Redis本地数据库的相关操作,默认文件是dump.rdb(通过配置文件获得),包括的操作包括保存,移除,查询等等。
6.replication.c 用于主从数据库的复制操作的实现。


tool:(工具)
1.bitops.c 位操作相关类
2.debug.c 用于调试时使用
3.endianconv.c 高低位转换,不同系统,高低位顺序不同
4.help.h  辅助于命令的提示信息
5.lzf_c.c 压缩算法系列
6.lzf_d.c  压缩算法系列
7.rand.c 用于产生随机数
8.release.c 用于发步时使用
9.sha1.c sha加密算法的实现
10.util.c  通用工具方法
11.crc64.c 循环冗余校验


event:(事件)
1.ae.c 用于Redis的事件处理,包括句柄事件和超时事件。
2.ae_epoll.c 实现了epoll系统调用的接口
3.ae_evport.c 实现了evport系统调用的接口
4.ae_kqueue.c 实现了kqueuex系统调用的接口
5.ae_select.c 实现了select系统调用的接口


baseinfo:(基本信息)
1.asciilogo,c redis的logo显示
2.version.h定有Redis的版本号


compatible:(兼容)
1.fmacros.h 兼容Mac系统下的问题
2.solarisfixes.h 兼容solary下的问题


main:(主程序)
1.redis.c redis服务端程序
2.redis_cli.c redis客户端程序


net:(网络)
1.anet.c 作为Server/Client通信的基础封装
2.networking.c 网络协议传输方法定义相关的都放在这个文件里面了。


wrapper:(封装类)
1.bio.c background I/O的意思,开启后台线程用的
2.hyperloglog.c 一种日志类型的
3.intset.c  整数范围内的使用set,并包含相关set操作。
4.latency.c 延迟类
5.migrate.c 命令迁移类,包括命令的还原迁移等
6.notify.c 通知类
7.object.c  用于创建和释放redisObject对象
8.pqsort.c  排序算法类
9.pubsub.c 用于订阅模式的实现,有点类似于Client广播发送的方式。
10.rio.c redis定义的一个I/O类
11.slowlog.c 一种日志类型的,与hyperloglog.c类似
12.sort.c 排序算法类,与pqsort.c使用的场景不同
13.syncio.c 用于同步Socket和文件I/O操作。
14.zmalloc.c 关于Redis的内存分配的封装实现


others:(存放了一些我暂时还不是很清楚的类,所以没有解释了)
1.scripting.c
2.sentinel.c
2.setproctitle.c
3.valgrind.sh
4.redisassert.h

    我分析的此Redis源代码是目前最新的代码redis-2.8.17,确保是最新的,新加了crc64.c等这些在2.2左右的版本上根本没有, 里面的很多.h头文件被我省掉了,因为很多同个文件名.h,.c文件都是其实指的是同个功能,后续,我将会分模块式分析Redis源代码,工作的时候根本没时间进行代码级别的研究。抓紧时间啦,fighting!



Java 开发 20: 现实世界中的 Redis :Redis 怎在包含大量读取操作的应用程序中战胜 memcached

此外,我还讨论过较为常见的基于服务器的数据存储,比如 MongoDB 和 CouchDB。每个数据存储都有其优势和劣势,特别是当应用于特定领域时。 本期的 Java 开发 2.0 关注的是 Redis,一种轻量级键值对数据存储。多数 NoSQL 实现本质上都是键值对,但是 Redis 支持非常丰富的值集,其中包括字符串、列表、集以及散列。因此,Redis 通常被称为数据结构服务器。Redis 也以异常快速而闻名,这使得它成为某一特定类型使用案例的最优选择。 当我们想要了解一种新事物时,将其同熟知的事物进行比较可能会有所帮助,因此,我们将通过对比其与 memcached 的相似性以开启 Redis 探索之旅。接着我们将介绍 Redis 的主要功能,这些功能可以使其在某些应用场景可以胜过 memcached。最后我将向您展示如何将 Redis 作为一个传统数据存储用于模型对象。Redis 和 memcached Memcached 是一个众所周知的内存对象缓存系统,通过将目标键和值导入内存缓存运行。因此,Memcached 能回避读取磁盘时发生的 I/O 成本问题。在 Web 应用程序和数据库之间粘贴 memcached 时会产生更好的读取性能。因此,对于那些需要快速数据查询的应用程序,Memcached 是一个不错的选择。其中的一个例子为股票查询服务,需要另外访问数据库获取相对静态数据,如股票名称或价格信息。 MemcacheDB 将Redis 与 memcached 相比较并不公平,它与 MemcacheDB 相比要好的多,MemcacheDB 是一个分布式键值对存储系统,专为数据持久化而设计。MemcacheDB 与 Redis 较为相似,其新增优势可以使其轻松地与 memcached 实现的客户端进行通信。 但是memcached 也有其局限性,其中一个事实就是它所有的值均是简单的字符串。Redis 作为 memcached 的替代者,支持更加丰富的功能集。一些基准 (benchmarks) 也表明 Redis 的速度要比 memcached 快很多。Redis 提供的丰富数据类型使其可以在内存中存储更为复杂的数据,这是使用 memcached 无法实现的。同 memcached 不一样,Redis 可以持久化其数据。 Redis 解决了一个重大的缓存问题,而其丰富的功能集又为其找到了其他用途。由于 Redis 能够在磁盘上存储数据以及跨节点复制数据,因而可以作为数据仓库用于传统数据模式(也就是说,您可以使用 Redis,就像使用 RDBMS 一样)。Redis 还经常被用作队列系统。在本用例中,Redis 是备份和工作队列持久化存储(利用 Redis 的列表类型)的基础。GitHub 是以此种方法使用 Redis 的大规模基础架构示例准备好 Redis,立即开始! 要开始使用 Redis,您需要访问它,可以通过本地安装或者托管供应商来实现访问。如果您使用的 MAC,安装过程可能就不那么简单。如果您使用的是 Windows??,您需要先安装 Cygwin。如果您正在寻找一个托管供应商,Redis4You 拥有一个免费计划。不管您以何种方式访问,您都能够根据本文下列示例进行操作,但是我需要指出的是,使用一个托管供应商进行缓存可能并不是很好的缓存解决方案,因为网络延迟可能会抵消任何性能优势。 您需要通过命令与 Redis 进行交互,这就是说,这里没有 SQL 类查询语言。使用 Redis 工作非常类似于使用传统 map 数据结构,即所有的......余下全文>>
 

Java 开发 20: 现实世界中的 Redis :Redis 怎在包含大量读取操作的应用程序中战胜 memcached

这里就不再逐个讨论了,我将会在一个实际应用程序开发场景中介绍其中的一些。使用Redis 作为一个缓存解决方案 我之前提到过,Redis 可轻易地用作一个缓存解决方案,碰巧我现在正好需要这样一个!在该应用程序示例中,我将 Redis 集成到我基于定位的移动 Web 服务中,称之为 Magnus。 如果您没有关注本系列,那么我会先使用 Play 框架实现 Magnus,从那时起我就已经在各种实现中开发和重构它了。Magnus 是一个简单服务,可以通过 HTTP PUT 请求使用 JSON 文档。这些文档描述了特定帐号的位置,表示持有移动设备的人。 现在,我想要将缓存集成到 Magnus,也就是说我想要通过将不常更改的数据存储在内存中以减少 I/O 流量。Magnus 缓存! 在清单 5 中的第一步中,可以通过 get 调用了解新引入的帐户名称(一个键)是否为 REdis 中的一个键。get 调用可以将帐户 ID 作为一个值返回,或者将返回 null。如果返回一个值,我将用其作为我的 acctId 变量。如果返回的是 null(表明该帐户名称不是 Redis 中一个键),那么我将在 MongoDB 查找该帐户值,并通过 set 命令将其添加到 Redis。 这里的优势是速度:接下来,被请求的帐户将提交一个位置,这样我就能够从 Redis 中获取其 ID(作为内存缓存),而不是转到 MongoDB 并带来额外读取 I/O 成本。清单5. 使用 Redis 作为内存缓存 "/location/:account" { put { def jacksonMapper = new ObjectMapper() def json = jacksonMapper.readValue(request.contentText, Map.class) def formatter = new SimpleDateFormat("dd-MM-yyyy HH:mm") def dt = formatter.parse(json['timestamp']) def res = [:] try{ def jedis = pool.getResource() def acctId = jedis.get(request.parameters['account']) if(!acctId){ def acct = Account.findByName(request.parameters['account']) jedis.set(request.parameters['account'], acct.id.toString()) acctId = acct.id } pool.returnResource(jedis) new Location(acctId.toString(), dt, json['latitude'].doubleValue(), json['longitude'].doubleValue() ).save() res['status'] = 'success' }catch(exp){ res['status'] = "error ${exp.message}" } response.json = jacksonMapper.w......余下全文>>
 

相关内容