参考文档redis底层实现原理word范文模板 10页.docx
《参考文档redis底层实现原理word范文模板 10页.docx》由会员分享,可在线阅读,更多相关《参考文档redis底层实现原理word范文模板 10页.docx(11页珍藏版)》请在冰点文库上搜索。
参考文档redis底层实现原理word范文模板10页
本文部分内容来自网络整理,本司不为其真实性负责,如有异议或侵权请及时联系,本司将立即删除!
==本文为word格式,下载后可方便编辑和修改!
==
redis底层实现原理
篇一:
redis-server启动原理简析
Redis笔记
参考地址:
/articles/redis-under-the-hood.html
Redis数据库存储引擎之下的东西。
Redis如何工作的呢?
我对于redis的内部构造十分的感兴趣,因此我开始让自己熟悉源代码,通过大量的阅读和在Emacs编辑器里面的跳来跳去。
当我将像剥洋葱片的外壳一样一层层将redis神秘的外衣剥落的时候,我意识到我正在努力尝试记住太多太多的细节,并且它并不是很清晰它是如何成为一个整体工作的。
我因此决定写下我对于redis的理解,讲述它是如何启动redisserver的和对它自己进行初始化工作,同时它是如何操作客户端发出的请求应答的,这个是对于我自己的理解而言的,它是一个很有时代前沿感的技术。
幸运的是,redis有一个很漂亮干净的代码基础,它很容易阅读和跟踪。
通过设定标签,以及使用GDB等等,我开始打算看看它在表层之下是如何工作的。
很偶然的事情是,我是在研究redis源代码基于antirez(redis的作者)发布的代码。
当然,内部构造就像我下面描述的轮廓或许会有一点点的变化。
然而,主要的redis服务器的构架不会有太大的变化,我现在试着努力记住一直这一点。
这篇文章开始的时候探究redisserver如何启动,并且在一个很高的层次来看待请求应答循环。
在一个子文章中,我将更多详细的描述并且跟踪SET/GET命令对在redis中工作的情形。
Redis笔记.......................................................................................................................1
目录..........................................................................................................................1
1.redis启动...........................................................................................................1
1.1
1.2
1.3
1.4开始进行全局服务端状态初始化..............................................................2设立命令表..............................................................................................3导入配置文件..........................................................................................4initServer()...............................................................................................4
1.5backtomain()...........................................................................................7
2.Processingtoarequestandreturnarespons..........................................................8
2.1
2.2
2.3
Handlinganewconnection.........................................................................9Readingacommandfromclient.............................................................10Executeacommand.................................................................................113.Redissummary..................................................................................................12
1.redis启动
让我们开始阅读在redis.c中的main()函数。
1.1开始进行全局服务端状态初始化
首先调用,initServerConfig()。
这个函数将结构体变量server的部分变量进行初始化,server的类型是structredisServer,这个作为全局的服务端状态。
在这个结构体中有大量的成员变量,但是他们一般在下面这些类别里面:
generalserverstate
?
statistics?
?
?
?
?
?
?
?
configurationfromconfigfilereplicationsortparametersvirtualmemoryconfig,state,I/Othreads,&statszipstructureeventloophelperspub/sub
例如,在这个结构体中包含的成员变量,一般都是会映射到配置文件里面(一般是叫做redis.conf),例如,服务器监听的端口和冗长的日志应该怎么形成,连接进来的客户端的链表的指针,以及redis的从服务器,(有时候使用主从结构),以及统计从开始到截止时候执行的所有命令的条数等等。
initServerConfig()提供了很多在通过配置文件redis.conf配置变量的默认参数,有的时候,配置文件并没有配置说明某个变量的值,这个时候initServerConfig()会给出默认参数。
1.2设立命令表
下一件main()函数做的事情是,将redis的命令分类,这些命令是通过一个全局的变量readonlyCommandTable这个变量是通过structredisCommand.//redis.c:
70
structredisCommand*commandTable;
structredisCommandreadonlyCommandTable[]={
{"get",getCommand,2,REDIS_CMD_INLINE,NULL,1,1,1},
{"set",setCommand,3,REDIS_CMD_BULK|REDIS_CMD_DENYOOM,NULL,0,0,0},
{"setnx",setnxCommand,3,REDIS_CMD_BULK|REDIS_CMD_DENYOOM,NULL,0,0,0},{"setex",setexCommand,4,REDIS_CMD_BULK|REDIS_CMD_DENYOOM,NULL,0,0,0},{"append",appendCommand,3,REDIS_CMD_BULK|REDIS_CMD_DENYOOM,NULL,1,1,1},//...
};
//redis.h:
458
typedefvoidredisCommandProc(redisClient*c);
//...
structredisCommand{
char*name;
redisCommandProc*proc;
intarity;
intflags;
//...
};
这个只读的命令表是通过分类排序的,例如string命令,list命令,set命令,等等,这些都是为了使这个可以给程序员更容易的浏览类似的命令。
这个已经排好序的表的命令由变量名commandTable来声明的,并且使用标准的二分查找来查找命令,用命令lookupCommand(),这个将会返回一个redisCommand的指针。
(初始化变量在
initServerConfig())中进行的,因为命令表被作者认为是初始化配置的一部分。
)一个redisCommand结构体记录了命令的名字-有助于记忆的,如get是一个指向执行实际命令的C语言函数指针,同时这个命令的参数,例如命令的标志是否返回一个大块的响应和一个VM的特殊成员。
1.3导入配置文件
Main()函数开始处理由用户输入的命令行参数,这样开始启动redis-server的执行。
现在,有一个仅仅只有一个参数的情况下,redisserver通常version–v并且help–h,或者路径中说明配置文件的路径。
如果,路径已经给出来,redis加载配置文件并且override那些在initServerConfig中设置的默认参数,通过调用loadServerConfig()。
这个函数是相当的简单的,循环读取配置文件中的每一行,并且将那些可以匹配到在server结构体中成员变量的变量名值转化出来。
在这点上,redis将会使这个成为守护进程并且将这个从终端分离如果用户已经设置了这样做的话。
1.4initServer()
initServer()完成初始化server结构体的工作,这个最开始是从initServerConfig()开始的。
首先,它建立起信号处理,(SIGHUP和SIGPIPE被忽略的,当接受到SIGHUP信号的时候,可以重新加载配置文件,就像其他的守护进程一样。
包括打印堆栈信息,如果server收到一个SIGSEGV,更多详情可以看segvHandler().
很多的双向链表(参见adlist.h)在这里被建立起来用来跟踪客户端和从服务器和监视器(一个客户端有MONITOR命令)还有一个object的空链表。
1.4.1共享object
一个有趣的事情是,redis创建了大量的共享的object,这些都是可以通过全局变量shared结构体来访问的。
普通的redisobject需要很多的不同的命令,对于响应字符串和错误信息的响应,例如,可以被共享而不需要每一次都申请他们,这样可以节省内存,这个是通过启动的时候做更多的事情来做的一个折中。
在initServer函数中调用
1.4.1.1共享的整型
通过共享内存节省的内存的最大来源是建立的一个巨大的共享整型池。
createSharedObjects();首先建立10,000个非负整数的数组来作为redis的
object,(string有一个整型的编码).多种的redisobject像string,set,list,常常
包含了许多小的整数,例如他们的ID,或者计数值。
并且他们可以在已经申
请到的内存空间来复用这些相同的object,这样可以节省很多内存。
你可以想
象一下,常数个共享整型被建立之后,REDIS_SHARED_INTEGERS,这个值是可
以被用户在配置文件中配置的,这个需要基于他们的应用程序的大小和需要,为了增加共享整数的节省的内存,这个是需要用户来设定的。
开始的时候采用
的是折中的方式,也就是在启动的时候稍微多申请一些内存,然而这个大小相
对于整个数据库的大小和潜在节省空间来说是很小的一部分。
1.4.2EventLoop
InitServer()继续执行,通过调用aeCreateEventLoop()(seeae.c),创建出了核心
的EventLoop,并且赋值给server.el。
ae.h提供了一个独立的封装平台,用来建立监听I/O事件监听循环,他们都
是使用Linux中的epoll,BSD上的kqueue,然后回调之后选择它期望的选择。
Redis的事件循环轮询给新的连接,和I/O事件(读请求和写请求到一个socket)当一个事件到达时候被触发。
这个就是为什么吗redis响应快的原因了。
它可以为上千个客户端同时服务,而不会产生阻塞,这个时候会为每一个请求做响应。
1.4.3Database
initServer()也对大量的redisDBobject进行初始化,这些都是结构体封装好了
一个特殊的redisdatabase,包括跟踪的expiringkeys,这是会阻塞的,这些键将会被检查设置。
默认情况下,有16个不同的数据库,这个可以被用来作为redisserver的命名空间。
篇二:
基于Redis实现分布式消息队列
基于Redis实现分布式消息队列
1、为什么需要消息队列?
当系统中出现“生产“和“消费“的速度或稳定性等因素不一致的时候,就需要消息队列,作为抽象层,弥合双方的差异。
举个例子:
业务系统触发短信发送申请,但短信发送模块速度跟不上,需要将来不及处理的消息暂存一下,缓冲压力。
再举个例子:
调远程系统下订单成本较高,且因为网络等因素,不稳定,攒一批一起发送。
再举个栗子,交互模块5:
00到24:
00和电商系统联通,和内部ERP断开。
1:
00到4:
00和ERP联通,和电商系统断开。
再举个例子,服务员点菜快,厨师做菜慢。
再举个例子,到银行办事的人多,提供服务的窗口少。
乖乖排队吧。
2、使用消息队列有什么好处?
2.1、提高系统响应速度
使用了消息队列,生产者一方,把消息往队列里一扔,就可以立马返回,响应用户了。
无需等待处理结果。
处理结果可以让用户稍后自己来取,如医院取化验单。
也可以让生产者订阅(如:
留下手机号码或让生产者实现listener接口、加入监听队列),有结果了通知。
获得约定将结果放在某处,无需通知。
2.2、提高系统稳定性
考虑电商系统下订单,发送数据给生产系统的情况。
电商系统和生产系统之间的网络有可能掉线,生产系统可能会因维护等原因暂停服务。
如果不使用消息队列,电商系统数据发布出去,顾客无法下单,影响业务开展。
两个系统间不应该如此紧密耦合。
应该通过消息队列解耦。
同时让系统更健壮、稳定。
3、为什么需要分布式?
3.1、多系统协作需要分布式
消息队列中的数据需要在多个系统间共享数据才能发挥价值。
所以必须提供分布式通信机制、协同机制。
3.2、单系统内部署环境需要分布式
单系统内部,为了更好的性能、为了避免单点故障,多为集群环境。
集群环境中,应用运行在多台服务器的多个JVM中;数据也保存在各种类型的数据库或非数据库的多个节点上。
为了满足多节点协作需要,需要提供分布式的解决方案。
4、分布式环境下需要解决哪些问题
4.1、并发问题
需进行良好的并发控制。
确保“线程安全“。
不要出现一个订单被出货两次。
不要出现顾客A下的单,发货发给了顾客B等情况。
4.2、简单的、统一的操作机制
需定义简单的,语义明确的,业务无关的,恰当稳妥的统一的访问方式。
4.3、容错
控制好单点故障,确保数据安全。
4.4、可横向扩展
可便捷扩容。
5、如何实现?
成熟的消息队列中间件产品太多了,族繁不及备载。
成熟产品经过验证,接口规范,可扩展性强。
结合事业环境因素、组织过程遗产、实施运维考虑、技术路线考虑、开发人员情况等原因综合考虑,基于Redis自己做一个是最可行的选择。
如何做呢?
请听下回分解。
Ubuntu14.04下Redis安装及简单测试
/Linux/201X-05/101544.htm
Redis集群明细文档/Linux/201X-09/90118.htm
Ubuntu12.10下安装Redis(图文详解)+Jedis连接
Redis/Linux/201X-06/85816.htm
Redis系列-安装部署维护篇/Linux/201X-12/75627.htmCentOS6.3安装Redis/Linux/201X-12/75314.htmRedis安装部署学习笔记/Linux/201X-07/104306.htm
篇三:
详细介绍Redis的几种数据结构以及使用注意事项
详细介绍Redis的几种数据结构以及使用注意事项
目录结构1.Overview
1.1资料
非常非常的快,有测评说比Memcached还快(当大家都是单CPU的时候),而且是无短板的快,读写都一般的快,所有API都差不多快,也没有MySQLCluster、MongoDB那样更新同一条记录如Counter时慢下去的毛病。
丰富的数据结构,超越了一般的Key-Value数据库而被认为是一个数据结构服务器。
组合各种结构,限制Redis用途的是你自己的想象力,作者自己捉刀写的用途入门。
因为是个人作品,Redis目前只有2.3万行代码,Keepitsimple的死硬做法,使得普通公司而不需淘宝那个级别的文艺公司也可以吃透它。
Redis宣言就是作者的自白,我最喜欢其中的"代码像首诗","设计是一场与复杂性的战斗","Coding是一件艰苦的事情,唯一的办法是享受它。
如果它已不能带来快乐就停止它。
为了防止这一天的出现,我们要尽量避免把Redis往乏味的路上带。
让人又爱又恨的单线程架构,使得代码不用处理平时最让人头痛的并发而大幅简化,也不用老是担心作者的并发有没有写对,但也带来CPU的瓶颈,而且单线程被慢操作所阻塞时,其他请求的延时变得不确定。
那Redis不是什么?
Redis不是BigData,数据都在内存中,无法以T为单位。
在Redis-Cluster发布并被稳定使用之前,Redis没有真正的平滑水平扩展能力。
Redis不支持Ad-HocQuery,提供的只是数据结构的API,没有SQL一样的查询能力。
1.3Feature速览所有数据都在内存中。
五种数据结构:
String/Hash/List/Set/OrderedSet。
数据过期时间支持。
不完全的事务支持。
服务端脚本:
使用LuaScript编写,类似存储过程的作用。
PubSub:
捞过界的消息一对多发布订阅功能,起码Redis-Sentinel使用了它。
持久化:
支持定期导出内存的Snapshot与记录写操作日志的AppendOnlyFile两种模式。
Replication:
Master-Slave模式,Master可连接多个只读Slave,暂无专门的GeographicReplication支持。
Fail-Over:
Redis-Sentinel节点负责监控Master节点,在master失效时提升slave,独立的仲裁节点模式有效防止脑裂。
Sharding:
开发中的Redis-Cluser。
动态配置:
所有参数可用命令行动态配置不需重启,并重新写回配置文件中,对云上的大规模部署非常合适。
1.4八卦作者是意大利的SalvatoreSanfilippo(antirez),又是VMWare大善人聘请了他专心写Redis。
EMC与VMWare将旗下的开源产品如Redis和Spring都整合到了孙公司Pivotal公司。
Pivotal做的antirez访谈录,内含一切八卦,比如他的爱好是举重、跑步和品红酒。
默认端口6379,是手机按键上MERZ对应的号码,意大利歌女AlessiaMerz是antirez和朋友们认为愚蠢的代名词。
2.数据结构
2.1Key
2.2String
Key-HashMap结构,相比String类型将这整个对象持久化成JSON格式,Hash将对象的各个属性存入Map里,可以只读取/更新对象的某些属性。
这样有些属性超长就让它一边呆着不动,另外不同的模块可以只更新自己关心的属性而不会互相并发覆盖冲突。
另一个用法是土法建索引。
比如User
对象,除了id有时还要按name来查询。
可以有如下的数据记录:
底层实现是hashtable,一般操作复杂度是O
(1),要同时操作多个field时就是O(N),N是field的数量。
2.4List