Redigo

October 18, 2025 · View on GitHub

poster

🚀 从零开始,用 Go 语言手写一个完整的 Redis 服务器

带有完整项目笔记,没有遗漏任何细节,适合用于学习 Redis 的实现原理。

📖 笔记

🌐 在线笔记

📚 完整笔记 - 在线阅读

Deepwiki:AI 生成的技术文档,可以和代码对话

本地运行笔记:

cd guide
npm install
npm run dev
# 访问 http://localhost:3000

笔记目录

🏗️ 基础架构

  1. TCP 服务器搭建

  2. RESP 协议解析

  3. 内存数据库核心

🔧 数据结构篇

  1. 哈希表实现

  2. 链表结构

  3. 集合实现

  4. 有序集合

🚀 高级特性

  1. 数据持久化

  2. 集群模式

  3. 并发安全

✨ 核心特性

🎯 已实现功能

  • 网络层:TCP 服务器
  • 协议层:RESP 协议解析器
  • 存储引擎:内存数据库
  • 数据结构:String、List、Hash、Set、ZSet
  • 并发安全:Key级别细粒度锁定机制
  • 持久化:AOF (Append Only File) 机制
  • 集群:一致性哈希

🔧 支持的 Redis 命令

🔑 键操作命令

DEL key [key ...]              # 删除一个或多个键
EXISTS key [key ...]           # 检查键是否存在
FLUSHDB                        # 清空当前数据库
TYPE key                       # 获取键的数据类型
RENAME key newkey              # 重命名键
RENAMENX key newkey            # 仅当新键不存在时重命名
KEYS pattern                   # 查找匹配模式的键

📝 字符串操作

SET key value                  # 设置键值对
GET key                        # 获取键的值
SETNX key value               # 仅当键不存在时设置
GETSET key value              # 设置新值并返回旧值
STRLEN key                    # 获取字符串长度

📋 列表操作

LPUSH key value [value ...]   # 从左侧插入元素
RPUSH key value [value ...]   # 从右侧插入元素
LPOP key                      # 从左侧弹出元素
RPOP key                      # 从右侧弹出元素
LRANGE key start stop         # 获取指定范围的元素
LLEN key                      # 获取列表长度
LINDEX key index              # 获取指定位置的元素
LSET key index value          # 设置指定位置的元素值

🏠 哈希操作

HSET key field value          # 设置哈希字段
HGET key field                # 获取哈希字段值
HEXISTS key field             # 检查哈希字段是否存在
HDEL key field [field ...]    # 删除哈希字段
HLEN key                      # 获取哈希字段数量
HGETALL key                   # 获取所有字段和值
HKEYS key                     # 获取所有字段名
HVALS key                     # 获取所有字段值
HMGET key field [field ...]   # 获取多个字段值
HMSET key field value [field value ...]  # 设置多个字段
HSETNX key field value        # 仅当字段不存在时设置

🎯 集合操作

SADD key member [member ...]  # 添加集合成员
SCARD key                     # 获取集合成员数量
SISMEMBER key member          # 检查成员是否在集合中
SMEMBERS key                  # 获取所有集合成员
SREM key member [member ...]  # 删除集合成员
SPOP key [count]              # 随机弹出集合成员
SRANDMEMBER key [count]       # 随机获取集合成员
SUNION key [key ...]          # 计算集合并集
SUNIONSTORE dest key [key ...]  # 存储集合并集
SINTER key [key ...]          # 计算集合交集
SINTERSTORE dest key [key ...]  # 存储集合交集
SDIFF key [key ...]           # 计算集合差集
SDIFFSTORE dest key [key ...]   # 存储集合差集

⚖️ 有序集合操作

ZADD key score member [score member ...]  # 添加有序集合成员
ZSCORE key member             # 获取成员分数
ZCARD key                     # 获取有序集合成员数量
ZRANGE key start stop [WITHSCORES]  # 按索引范围获取成员
ZREM key member [member ...]  # 删除有序集合成员
ZCOUNT key min max            # 统计分数范围内的成员数量
ZRANK key member              # 获取成员排名

🔧 系统命令

PING                          # 测试连接
SELECT index                  # 选择数据库

🚀 快速开始

环境要求

  • Go 1.21+
  • Git
  • Node.js 18+ (可选,用于运行笔记)

查看笔记的方式

# 1. 克隆项目
git clone https://github.com/inannan423/redigo.git
cd redigo

# 2. 启动笔记(可选,可以访问 https://redigo.vercel.app)
cd guide
npm install
npm run dev
# 访问 http://localhost:3000 开始学习


# 3. 按笔记进度切换分支学习
git checkout tcp-server    # 第一章:TCP 服务器
git checkout resp-parser   # 第二章:RESP 协议
git checkout database      # 第三章:数据库核心
# ... 更多分支见笔记

方式二:直接运行完整版 🏃‍♂️

# 1. 克隆项目
git clone https://github.com/inannan423/redigo.git
cd redigo

# 2. 启动单机模式
go run main.go

# 3. 启动集群模式(需要配置 redis.conf)
# 编辑 redis.conf 设置集群节点
go run main.go

客户端连接测试

# 使用 Redis 官方客户端
redis-cli -h localhost -p 6380

# 测试基本命令
127.0.0.1:6380> SET hello world
OK
127.0.0.1:6380> GET hello
"world"
127.0.0.1:6380> PING
PONG

📊 性能基准与压力测试

Redis 提供了 redis-benchmark 工具来测试性能,以下是详细的使用指导:

📋 基础用法

安装 redis-benchmark

确保已安装 Redis 客户端工具:

# macOS
brew install redis

# Ubuntu/Debian
sudo apt-get install redis-tools

# CentOS/RHEL
sudo yum install redis

基本测试命令

# 启动 Redigo 服务器
go run main.go

# 在另一个终端运行基准测试
redis-benchmark -h localhost -p 6380 -n 100000 -c 50

🎯 常用测试场景

字符串操作性能测试

# SET 命令测试
redis-benchmark -h localhost -p 6380 -n 100000 -c 50 -t set

# GET 命令测试
redis-benchmark -h localhost -p 6380 -n 100000 -c 50 -t get

# 混合 SET/GET 测试
redis-benchmark -h localhost -p 6380 -n 50000 -c 25 -t set,get

列表操作性能测试

# LPUSH 测试
redis-benchmark -h localhost -p 6380 -n 50000 -c 25 -t lpush

# LPOP 测试
redis-benchmark -h localhost -p 6380 -n 50000 -c 25 -t lpop

# LRANGE 测试
redis-benchmark -h localhost -p 6380 -n 10000 -c 10 -t lrange_100,lrange_300,lrange_500

哈希操作性能测试

# HSET 测试
redis-benchmark -h localhost -p 6380 -n 50000 -c 25 -t hset,hget

集合操作性能测试

# SADD 测试
redis-benchmark -h localhost -p 6380 -n 50000 -c 25 -t sadd,spop

有序集合操作性能测试

# ZADD 测试
redis-benchmark -h localhost -p 6380 -n 50000 -c 25 -t zadd,zrem

# ZRANGE 测试
redis-benchmark -h localhost -p 6380 -n 10000 -c 10 -t zadd,zrange_100,zrange_300,zrange_500

一次测试所有命令

redis-benchmark -h localhost -p 6380 -n 100000 -c 50 -t set,get,lpush,lpop,lrange,hset,hget,hdel,hlen,hkeys,hvals,hmget,hmset,hsetnx,sadd,spop,smembers,srem,sinter,sinterstore,sdiff,sdiffstore,zadd,zrem,zcard,zrange,zcount,zrank

📊 参数详解

参数描述示例
-h <hostname>Redis 服务器地址-h localhost
-p <port>Redis 服务器端口-p 6380
-n <requests>总请求数-n 100000
-c <clients>并发连接数-c 50
-d <size>数据大小(字节)-d 1024
-t <tests>指定测试命令-t set,get,lpush
-k <boolean>保持连接-k 1
-r <keyspacelen>键空间大小-r 100000
-P <pipeline>管道请求数-P 10
-q静默模式,只显示结果-q
--csvCSV 格式输出--csv

📈 性能指标解读

测试完成后,redis-benchmark 会显示以下关键指标:

====== SET ======
  100000 requests completed in 1.23 seconds
  50 parallel clients
  3 bytes payload
  keep alive: 1

99.95% <= 1 milliseconds
100.00% <= 2 milliseconds
81234.56 requests per second

关键指标说明:

  • Requests per second (RPS):每秒处理的请求数,越高越好
  • Latency percentiles:延迟百分位数,显示响应时间分布
  • 平均延迟:所有请求的平均响应时间
  • 吞吐量:服务器的数据处理能力

📋 实际测试结果分析

测试环境: MacBook Pro M2, 16GB RAM, macOS 15.2

基于 redis-benchmark -h localhost -p 6380 -n 100000 -c 50 -t set,get,lpush,lpop,lrange,hset,hget,hdel,hlen,hkeys,hvals,hmget,hmset,hsetnx,sadd,spop,smembers,srem,sinter,sinterstore,sdiff,sdiffstore,zadd,zrem,zcard,zrange,zcount,zrank 的综合测试结果:

🚀 核心操作性能表现

操作类型QPS平均延迟(ms)P95延迟(ms)P99延迟(ms)
SET148,3680.1930.2950.671
GET149,0310.1860.2790.447
LPUSH163,6660.1760.2470.399
LPOP153,6100.1840.2790.359
HSET163,1320.1740.2470.335
SADD143,0620.1930.2870.407
SPOP160,7720.1750.2550.311
ZADD162,8660.1770.2470.359

📋 范围查询性能分析

LRANGE操作QPS平均延迟(ms)P95延迟(ms)P99延迟(ms)适用场景
LRANGE_10045,1670.6131.0872.703小数据量查询
LRANGE_30022,6191.1461.6472.719中等数据量查询
LRANGE_50015,3521.6632.2793.487大数据量查询
LRANGE_60013,3441.8812.3752.903超大数据量查询

🎯 性能亮点

基础操作(SET/GET/LPUSH/HSET等)均达到 14万+ QPS,最高性能的 LPUSH 操作达到 16.3万+ QPS,所有基础操作平均延迟均低于 0.2ms,P95 延迟保持在 0.3ms 以内,P99 延迟控制在 0.7ms 以内

🗓 TODO

  • 完善集群模式
  • 实现更多 Redis 命令
  • 增加更多数据结构支持
  • 提升测试覆盖率

🤝 贡献指南

欢迎贡献!

  • 🐛 Bug 修复:发现问题请提交 Issue,或者直接提交 Commit
  • 📚 文档改进:让笔记更清晰易懂
  • 新功能:实现更多 Redis 命令
  • 🎯 性能优化:优化 Redigo 的性能
  • 🧪 测试用例:提高代码覆盖率

如何贡献

  1. Fork 本项目
  2. 创建特性分支 (git checkout -b feature/AmazingFeature)
  3. 提交改动 (git commit -m 'Add some AmazingFeature')
  4. 推送到分支 (git push origin feature/AmazingFeature)
  5. 创建 Pull Request

💬 学习交流

📜 开源协议

本项目采用 GPL-3.0 协议,详情请查看 LICENSE 文件。

🙏 致谢

  • Godis 本项目学习了 Godis 的设计思路和部分实现,感谢大佬们的贡献!

如果这个项目对你有帮助,请给我一个 Star!

📧 有问题? 欢迎提交 Issue 或发邮件讨论。