最近公司的第一个PHP转GO项目已经在生产环境稳定运行数周,又逢需求小年儿,最近能够得空分享下去年学GO过程当中的练手项目Godis——用Golang实现的Redis.程序员
Redis3.0版本,代码简明精炼,再加上是Web后端程序员使用最多组件之一,熟悉Redis原理并阅读多源码的开发者人数颇多,这个系列小文便再也不对Redis细节作过多介绍。不过,有必要系统性说明的地方仍然会以较大篇幅尝试解读。redis
Godis初版的目标是“最基本的kv缓存”,feature list以下:数据库
已经作到,再精简就等于没写的境界。遵循实际工做中的编码流程,先设计基本架构再填充实现的方式,Godis的架构图一步到位、毫无点缀:segmentfault
客户端与服务端经过创建网络链接,发送、处理、返回数据给对方,完成通讯。Redis的单机应用中,一个服务端redis-server进程能够处理多个客户端的请求。后端
客户端须要一个数据结构来保存信息,接收命令,维持和服务端的链接,与服务端进行一对一的交互。
客户端具体须要哪些信息,暂且不表。缓存
服务端为了响应多个客户端的请求,对数据进行查询、存储、更新、删除操做,也须要一个结构来保存基本信息,包括数据自己、正在链接中的客户端等。
客户端和服务端经过这两个基本数据结构,即可以在创建链接(能够简化为socket demo)以后,保存自身和对方的必要信息,维持以后的交互。服务器
从原理分析入手,使用下图所示的结构体,能够知足存储客户端、服务端的数据存储要求:网络
client并不是是咱们用来和redis-server交互的client,而是与redis-server创建链接后,服务端在服务器建立的、用来存储当前链接的结构。与redis-server创建链接的客户端什么样,redis-server不关心,毕竟与之交互的都是协议而已。数据结构
由图,client和server结构体均有Db字段,不一样的是,server.Db指向的是0号db(Redis支持多db,能够自行查阅了解);client.Db指向的是正在链接的db。若是有select切换操做,该指向也会随之变化。架构
set、get 命令是redis最经常使用的命令之一,也是最能反映缓存发展历史的操做。对最简单命令代码的阅读,能够看到Redis最核心的原理。
set命令将数据以k-v键值对,保存到数据库,也就是redis-server占用的内存中,而且任何链接到此Redis服务器的客户端,均可以经过get命令查询到。
上一小节提到,保存服务器相关的信息须要一个结构体,这里set命令保存的数据,也存在这个结构体中。不过,存储的是数据的指针。
因此,set/get的实现原理能够简化为,在服务器数据结构中保存set命令的数据,get命令执行时,也从这个数据结构中查找。
set、get命令在客户端接收以后,经由协议转换传递给服务端执行。服务端执行命令前先查询是否支持该命令,以决定是否执行。因此server结构体还须要有个commands字段,记录支持的命令列表。
set命令保存的数据不能一直在内存中,万一宕机或者硬件故障,数据岂不是烟消云散?
这就须要持久化技术,这也是存储领域的一大关键技术。AOF,是Append Only File的简称,表明的是“只存增量”的持久化方式。在Godis v1.0版本中,将以最简单的方式实现AOF持久化,作到下次开机能够查到上次set的数据 :)
持久化不该该对全部命令一视同仁,减小不必的执行开销。在server中增长dirty字段,标记数据是否已经被污染,再决定是否持久化。
通过如上说明,这里还有一幅Godis v1.0版数据结构图: