用 Go 造一个 Redis:推荐两个开源项目供参考
2021-07-22 19:12:00 Author: mp.weixin.qq.com(查看原文) 阅读量:66 收藏

阅读本文大概需要 5 分钟。

大家好,我是 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

点击「阅读原文」同样可以优惠购买。


文章来源: http://mp.weixin.qq.com/s?__biz=MzAxNzY0NDE3NA==&mid=2247487682&idx=1&sn=9b1d1d51c44da56df991dcbd9142e464&chksm=9be33f23ac94b6357065760b2fde52796f0d92c750f7c87b5f50e74ec35428bece005f6ee195#rd
如有侵权请联系:admin#unsafe.sh