资讯专栏INFORMATION COLUMN

用Go实现Redis之一准备工作

zhangke3016 / 707人阅读

摘要:命令实现命令是最常用的命令之一,也是最能反映缓存发展历史的操作。命令在客户端接收之后,经由协议转换传递给服务端执行。服务端执行命令前先查询是否支持该命令,以决定是否执行。,是的简称,代表的是只存增量的持久化方式。

缘起

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

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

进入正题 基本流程

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

客户端/服务端交互

set/get 命令实现

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 v1.0版本中,将以最简单的方式实现AOF持久化,做到下次开机可以查到上次set的数据 :)
持久化不应该对所有命令一视同仁,减少没必要的执行开销。在server中增加dirty字段,标记数据是否已经被污染,再决定是否持久化。

数据结构关联

经过如上说明,这里还有一幅Godis v1.0版数据结构图:

下集预告

完成服务端/客户端交互

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/28767.html

相关文章

  • Go实现Redis之一准备工作

    摘要:命令实现命令是最常用的命令之一,也是最能反映缓存发展历史的操作。命令在客户端接收之后,经由协议转换传递给服务端执行。服务端执行命令前先查询是否支持该命令,以决定是否执行。,是的简称,代表的是只存增量的持久化方式。 缘起 最近公司的第一个PHP转GO项目已经在生产环境稳定运行数周,又逢需求小年儿,最近可以得空分享下去年学GO过程中的练手项目Godis——用Golang实现的Redis. ...

    yacheng 评论0 收藏0
  • Go实现Redis之二客户端/服务端交互

    摘要:写在前面在前一篇梳理了版本的基本功能,这一篇要做的是实现客户端服务端的交互。进入正题事件处理器既要实现交互,网络编程必不可少。 写在前面 在前一篇梳理了Godis v1.0版本的基本功能,这一篇要做的是实现客户端/服务端的交互。先让代码跑起来,才算有了生命力。本篇Godis版本号:v0.0.1 在这个系列文章里,尽量减少介绍Golang语法、C语言语法和redis原理,聚焦在用Gol...

    qieangel2013 评论0 收藏0
  • Go实现Redis之二客户端/服务端交互

    摘要:写在前面在前一篇梳理了版本的基本功能,这一篇要做的是实现客户端服务端的交互。进入正题事件处理器既要实现交互,网络编程必不可少。 写在前面 在前一篇梳理了Godis v1.0版本的基本功能,这一篇要做的是实现客户端/服务端的交互。先让代码跑起来,才算有了生命力。本篇Godis版本号:v0.0.1 在这个系列文章里,尽量减少介绍Golang语法、C语言语法和redis原理,聚焦在用Gol...

    Scliang 评论0 收藏0
  • Go实现Redis之三get/set命令实现

    摘要:在读者阅读实现代码时,也可以看到最新版本,与有一处是在文件清除掉回车换行符该行被暂时注释掉,也就是在版本,使用作为文本协议分隔符,确定命令的结尾。 写在前面 本篇Godis版本号:v0.0.2 前一篇文章实现了客户端/服务端的交互。这一篇,主要介绍get/set命令的实现。命令本身比较简单,支撑命令的整个系统基础比较麻烦。本文会介绍get/set操作涉及的组件和模块,并适当简化,最后实...

    flyer_dev 评论0 收藏0
  • Go实现Redis之三get/set命令实现

    摘要:在读者阅读实现代码时,也可以看到最新版本,与有一处是在文件清除掉回车换行符该行被暂时注释掉,也就是在版本,使用作为文本协议分隔符,确定命令的结尾。 写在前面 本篇Godis版本号:v0.0.2 前一篇文章实现了客户端/服务端的交互。这一篇,主要介绍get/set命令的实现。命令本身比较简单,支撑命令的整个系统基础比较麻烦。本文会介绍get/set操作涉及的组件和模块,并适当简化,最后实...

    Ethan815 评论0 收藏0

发表评论

0条评论

zhangke3016

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<