my-redis是一个用Rust编写的迷你Redis。
Fork自此仓库,但做了些许修改,且具有较为完全的中文注释。
声明:此项目的目的是学习使用Tokio编写应用。
my-redis目前支持的命令如下:
Ping [<message>]Set <key> <value> [<expiration(ms)>]Get <key>Publish <channel> <message>Subscribe <channel> [<channel> ...]
首先开启服务器:
cargo run --bin my-redis-server-
运行
Ping:cargo run --bin my-redis-cli ping hello-server
-
运行
Get和Set:cargo run --bin my-redis-cli set foo bar cargo run --bin my-redis-cli get foo -
运行
Subscribe和Publish:cargo run --bin my-redis-cli subscribe c cargo run --bin my-redis-cli publish c 100
这个学习项目应用了很多有用的模式,包括:
server.rs启动了一个TCP服务器来接收连接,并为每一个连接开启一个异步任务来处理。它优雅地处理连接时可能发生的错误。
服务器维护一个Db实例,所有连接都可以访问该实例。Db实例管理键值状态以及发布/订阅功能。
connection.rs和frame.rs展示了如何理想地实现一个网络协议。该协议使用中间表示形式Frame结构建模。Connection接收一个TcpStream,并公开一个发送和接收Frame值的 API。
tokio::signal用于侦听 SIGINT。一旦收到信号,关机就会开始。服务器停止接受新连接。现有连接会收到关机通知,等待所有执行中的工作完成,然后关闭服务器。
服务器具有非堆成的发布/订阅功能。客户端可以订阅一个或多个频道,此时客户端处于订阅状态,等待接收信息,无法执行除关闭客户端(Ctrl + C)外的其他活动。服务器使用广播信道和每个连接一个StreamMap来实现此功能。客户端可以向某个频道发布信息,其他订阅了此频道的客户端就可以收到这些信息。
服务器使用std::sync::Mutex确保在并发环境下的数据安全。
可能对项目理解有帮助的架构图:
-
本项目没有提供单元测试和集成测试,如果有需要可以查看原仓库的
tests文件夹。 -
处于订阅状态的客户端无法进行除了退出
Ctrl + C以外的任何操作,无法重新订阅、取消订阅等操作。