大家好,我是 polarisxu。
项目中,我想大部分人都使用过 Redis,而且面试中,Redis 相关知识点几乎也是必问的。大家在学习 Go 的过程中,总是苦于没有具体的项目可以练手,你有没有想过使用 Go 实现一个 Redis?
这个难度确实不小,但有挑战才会更有收获。对自己够狠的,特别是大学生或刚入职场不久的,强烈建议试试,如果能够坚持啃下来,相信无论对 Go 还是对 Redis 知识,都会有极大的提升。
也许你不知道如何入手,这里我推荐两个开源项目供参考:
1)Redcon
项目地址:https://github.com/tidwall/redcon,tidwall,不知道大家有印象没?我之前写过一篇文章:推荐一位高产的 Go 开源库作者,就是 tidwall。
Redcon 是一个兼容 Redis 协议的 Server 框架。什么意思?也就是说,Redcon 为你搭建好了构建一个 Redis 的架子,基于它你可以完善 Redis 相关的功能。
这个框架对外接口很简单,包括一个函数 ListenAndServe 和两个类型:Conn 和 Command,包括如下特性:
支持 pipelining 和 telnet 命令 因为兼容 Redis 协议,所以各种现有 Redis 客户端可以直接用 支持 TLS 支持 pub/sub 多线程
为了方便使用,作者提供了相关例子,基于这个例子,可以构建你的 Redis:
package main
import (
"log"
"strings"
"sync"
"github.com/tidwall/redcon"
)
var addr = ":6380"
func main() {
var mu sync.RWMutex
var items = make(map[string][]byte)
var ps redcon.PubSub
go log.Printf("started server at %s", addr)
err := redcon.ListenAndServe(addr,
func(conn redcon.Conn, cmd redcon.Command) {
switch strings.ToLower(string(cmd.Args[0])) {
default:
conn.WriteError("ERR unknown command '" + string(cmd.Args[0]) + "'")
case "ping":
conn.WriteString("PONG")
case "quit":
conn.WriteString("OK")
conn.Close()
case "set":
if len(cmd.Args) != 3 {
conn.WriteError("ERR wrong number of arguments for '" + string(cmd.Args[0]) + "' command")
return
}
mu.Lock()
items[string(cmd.Args[1])] = cmd.Args[2]
mu.Unlock()
conn.WriteString("OK")
case "get":
if len(cmd.Args) != 2 {
conn.WriteError("ERR wrong number of arguments for '" + string(cmd.Args[0]) + "' command")
return
}
mu.RLock()
val, ok := items[string(cmd.Args[1])]
mu.RUnlock()
if !ok {
conn.WriteNull()
} else {
conn.WriteBulk(val)
}
case "del":
if len(cmd.Args) != 2 {
conn.WriteError("ERR wrong number of arguments for '" + string(cmd.Args[0]) + "' command")
return
}
mu.Lock()
_, ok := items[string(cmd.Args[1])]
delete(items, string(cmd.Args[1]))
mu.Unlock()
if !ok {
conn.WriteInt(0)
} else {
conn.WriteInt(1)
}
case "publish":
if len(cmd.Args) != 3 {
conn.WriteError("ERR wrong number of arguments for '" + string(cmd.Args[0]) + "' command")
return
}
conn.WriteInt(ps.Publish(string(cmd.Args[1]), string(cmd.Args[2])))
case "subscribe", "psubscribe":
if len(cmd.Args) < 2 {
conn.WriteError("ERR wrong number of arguments for '" + string(cmd.Args[0]) + "' command")
return
}
command := strings.ToLower(string(cmd.Args[0]))
for i := 1; i < len(cmd.Args); i++ {
if command == "psubscribe" {
ps.Psubscribe(conn, string(cmd.Args[i]))
} else {
ps.Subscribe(conn, string(cmd.Args[i]))
}
}
}
},
func(conn redcon.Conn) bool {
// Use this function to accept or deny the connection.
// log.Printf("accept: %s", conn.RemoteAddr())
return true
},
func(conn redcon.Conn, err error) {
// This is called when the connection has been closed
// log.Printf("closed: %s, err: %v", conn.RemoteAddr(), err)
},
)
if err != nil {
log.Fatal(err)
}
}
2)Tidis
第二个开源项目是:https://github.com/yongman/tidis,这是一个分布式 NoSQL 数据库,兼容 Redis 协议,但使用 TiKV 作为后端。架构图如下:
这是一个完整的 NoSQL 数据库实现。
此外,在 GitHub 搜索 Redis,还能找到其他一些 Go 的实现。
不过,只看别人的源码,可能有点云里雾里,要想自己用 Go 实现一个 Redis,必须掌握 Redis 相关知识。
你对 Redis 掌握多少?可能这张图能够很好地让你做一个判断:
我相信,在你学习和用 Go 实现 Redis 的过程中,你还可以不断完善它。这样一来,积累越多,画像就越丰富。
那怎么更好、更快的学习 Redis 相关知识呢?这里推荐一个极客时间的 Redis 专栏:《Redis 核心技术与实战》。这个专栏原价 199 元,跟极客时间小姐姐申请了额外优惠码:Happy2021,到手 119 元。
大概介绍下这个专栏
该专栏的作者是蒋德钧,上面 Redis 问题画像图就是他画的,他是中科院计算所副研究员,长期致力于 Redis 研究,与阿里、蚂蚁金服、百度、华为、中兴等公司开展了多种项目合作,具有丰富的 Redis 实战经验,申请了 NVM(非易失内存)相关专利二十多项。
在专栏中,他总结了一条系统高效的 Redis 学习路径,帮你透彻理解 Redis 核心原理,并通过上手实战,掌握高并发场景下的缓存解决方案。同时,还有不少 Redis 高频面试题讲解,都是工作、面试中用得上的、实打实的硬货。
这是专栏大纲:
购买时记得用专属优惠哦:
秒杀+专属口令「Happy2021」立省 ¥80,
到手仅 ¥119,即将恢复到原价¥199
点击「阅读原文」同样可以优惠购买。