用Golang实现redis

alphali · · 5936 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

缘起

最近公司的第一个PHP转GO项目已经在生产环境稳定运行数周,又逢需求小年儿,得空分享下去年学GO过程中的练手项目Godis——用Golang实现的redis.

redis3.0版本,代码简明精炼,再加上是Web后端程序员使用最多组件之一,熟悉redis原理并阅读多源码的开发者人数颇多,这个系列小文便不再对redis细节做过多介绍。不过,有必要系统性说明的地方仍然会以较大篇幅尝试解读。

进入正题

基本流程

Godis第一版的目标是“最基本的kv缓存”,feature list如下:

  1. 客户端/服务端交互
  2. set/get 命令实现
  3. AOF持久化实现

已经做到,再精简就等于没写的境界。遵循实际工作中的编码流程,先设计基本架构再填充实现的方式,Godis的架构图一步到位、毫无点缀:

图片描述

原理分析

1. 客户端/服务端交互

客户端与服务端通过建立网络连接,发送、处理、返回数据给对方,完成通信。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切换操作,该指向也会随之变化。

2. set/get 命令实现

set、get 命令是redis最常用的命令之一,也是最能反映缓存发展历史的操作。对最简单命令代码的阅读,可以看到redis最核心的原理。
set命令将数据以k-v键值对,保存到数据库,也就是redis-server占用的内存中,并且任何连接到此redis服务器的客户端,都可以通过get命令查询到。
上一小节提到,保存服务器相关的信息需要一个结构体,这里set命令保存的数据,也存在这个结构体中。不过,存储的是数据的指针。
所以,set/get的实现原理可以简化为,在服务器数据结构中保存set命令的数据,get命令执行时,也从这个数据结构中查找。
set、get命令在客户端接收之后,经由协议转换传递给服务端执行。服务端执行命令前先查询是否支持该命令,以决定是否执行。所以server结构体还需要有个commands字段,记录支持的命令列表。

3. AOF持久化实现

set命令保存的数据不能一直在内存中,万一宕机或者硬件故障,数据岂不是烟消云散?
这就需要持久化技术,这也是存储领域的一大关键技术。AOF,是Append Only File的简称,代表的是“只存增量”的持久化方式。在Godis v0.0.1版本中,将以最简单的方式实现AOF持久化,做到下次开机可以查到上次set的数据 :)
持久化不应该对所有命令一视同仁,减少没必要的执行开销。在server中增加dirty字段,标记数据是否已经被污染,再决定是否持久化。

数据结构关联

经过如上说明,这里还有一幅Godis v0.0.1版数据结构图:
图片描述

下集预告

  1. 实现主要数据结构
  2. 完成服务端/客户端交互

有疑问加站长微信联系

本文来自:Segmentfault

感谢作者:alphali

查看原文:用Golang实现redis

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:1006366459

5936 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传