前言
你是否曾经遇到过这样的困惑:刚开始接触Go语言时,不像java一样有着良好的生态,不知道该从何入手?也许你想参考一下知名项目如 Kubernetes 和 etcd ,但光是看目录就已经让你头晕目眩,更别提从哪里开始阅读源码了。为了帮助解决这个问题,Tiny-Redis项目应运而生。通过这个项目,你将了解开发中间件的思路,涉及到RESP协议的应用,如何开发一个服务端,以及在高并发情况下的解决方案。希望你通过学习这个项目后,能够在秋招中大展身手。
简介
tiny-redis 是一个由 Go 编写的高性能独立缓存服务器。它实现了完整的 RESP(Redis 序列化协议),因此支持所有的 Redis 客户端。
特点
*支持基于 RESP 协议的所有客户端。 *支持字符串、列表、集合、哈希数据类型。 *支持 TTL(键-值对将在 TTL 后被删除)。 *完全内存存储。 *支持一些需要的原子操作命令(如 INCR、DECR、INCRBY、MSET、SMOVE 等)。
开始之前
在开始之前,建议你先克隆 Tiny-Redis 项目的 GitHub 仓库,你可以通过以下命令来实现:
git clone https://github.com/HSn0918/tinyredis.git
cd tinyredis
在这个项目中,你会看到几个重要的文件和目录,它们分别是:
|-- README.md
|-- RESP//RESP协议数据类型和解析RESP函数
|-- config//配置
|-- go.mod
|-- logger//日志
|-- main.go
|-- memdb//数据库数据类型
|-- server//服务端
`-- util
|-- README.md
|-- RESP
| |-- arraydata.go
| |-- bulkdata.go
| |-- errordata.go
| |-- intdata.go
| |-- parser_test.go
| |-- parsestream.go
| |-- plaindata.go
| |-- stringdata.go
| `-- structure.go//解析RESP协议
|-- config
| `-- config.go
|-- go.mod
|-- logger
| |-- level.go
| `-- logger.go
|-- main.go
|-- memdb
| |-- command.go//方法注册函数
| |-- concurrentmap.go//ConcurrentMap
| |-- db.go//内存数据库
| |-- dblock.go//锁
| |-- hash.go
| |-- hash_struct.go
| |-- keys.go
| |-- keys_test.go
| |-- list.go
| |-- list_struct.go
| |-- list_test.go
| |-- set.go
| |-- set_struct.go
| |-- string.go
| |-- string_test.go
| |-- zset.go
| `-- zset_struct.go
|-- server
| |-- handler.go//监听端口
| `-- server.go//启动服务
`-- util
`-- util.go//hash函数和正则实现
从源码构建
go build -o tiny-redis main.go
./tiny-redis -h
Usage of ./tiny-redis:
-config string
Appoint a config file: such as /etc/redis.conf
-host string
Bind host ip: default is 127.0.0.1 (default "127.0.0.1")
-logdir string
Set log directory: default is /tmp (default "./")
-loglevel string
Set log level: default is info (default "info")
-port int
Bind a listening port: default is 6379 (default 6379)
./tiny-redis
从Docker构建
值得注意的是,我们已经在 /data
目录为你准备好了 redis-cli
命令行工具方便你调试使用。由于项目未做数据持久化,所以即使你挂载了 /data
目录也只能得到一些日志文件,以及 tiny-redis
,redis-cli
。
docker build -t tiny-redis:0.1 .
docker run -d \
--name tiny-redis \
-p 6379:6379 \
-v tinyredis-data:/data\
tiny-redis:0.1
任何 Redis 客户端都可以与 tiny-redis 服务器通信。
目前支持图形化客户端:Medis、AnotherRedisDesktopManager。然而需要注意的是,这些客户端中显示的关于服务端的信息可能并不是准确的
例如,可以使用 redis-cli 与 tiny-redis 服务器通信:
$ ./tiny-redis
[info][server.go:25] 2023/09/17 00:55:35 [Server Listen at 127.0.0.1:6379]
[info][server.go:35] 2023/09/17 00:55:40 [127.0.0.1:7810 connected]
$ redis-cli
127.0.0.1:6379> PING
PONG
127.0.0.1:6379> MSET key1 a key2 b
OK
127.0.0.1:6379> MGET key1 key2 nonekey
1) "a"
2) "b"
3) ""
127.0.0.1:6379> RPUSH list1 1 2 3 4 5
(integer) 5
127.0.0.1:6379> LRANGE list1 0 -1
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
127.0.0.1:6379> TYPE list1
list
127.0.0.1:6379> EXPIRE list1 100
(integer) 1
127.0.0.1:6379> TTL list1
(integer) 96
127.0.0.1:6379> PERSIST list1
(integer) 1
127.0.0.1:6379> TTL list1
(integer) -1
性能基准测试
性能基准测试的结果是基于 redis-benchmark 工具进行的。redis-benchmark 测试在Lenovo Legion R70002021, AMD Ryzen 5 5600H with Redeon Graphics, NVIDA Geforce RTX3050 laptop CPU 4GB, 16GB (3200MHX), Windows11 with Ubuntu 20.04.6 LTS(WSL2) redis-benchmark -c 50-n 200000 -t get
get: 146716.22 requests per second
set: 153433.08 requests per second
incr: 144334.86 requests per second
lpush: 145313.64 requests per second
rpush: 139470.00 requests per second
lpop: 152226.30 requests per second
rpop: 147929.08 requests per second
sadd: 160599.60 requests per second
hset: 147765.06 requests per second
spop: 144109.50 requests per second
lrange_100: 83880.90 requests per second
lrange_300: 50652.36 requests per second
lrange_500: 37703.82 requests per second
lrange_600: 27895.92 requests per second
mset: 126196.26 requests per second
可用命令
最后
笔者也是初学 Go,借鉴了其他优秀的开源代码,如果文章/代码有错误的地方,敬请斧正。
项目链接
GitHub - HSn0918/tinyredis: tiny-redis
如需转载,请保留项目链接。