🚀 Redis 精简版(MiniRedis):内存存储 + 命令解析
目标:打造一个可以在命令行下运行的 Redis Mini 实现,支持基本命令:SET、GET、DEL,并支持简单的 TCP 客户端连接。
📁 项目结构
less
复制
编辑
MiniRedis/
├── main.cpp // 启动入口
├── server.cpp/h // 网络服务器代码(监听连接)
├── command.cpp/h // 命令解析与执行
├── datastore.cpp/h // 内存数据库
├── utils.h // 辅助函数
✅ 支持的基础命令
命令 功能
SET key value 设置 key 的值
GET key 获取 key 的值
DEL key 删除 key
EXIT 断开连接
🧠 第一步:数据存储模块(datastore.h/.cpp)
cpp
复制
编辑
// datastore.h
pragma once
include <unordered_map>
include <string>
include <mutex>
class DataStore {
public:
std::string get(const std::string& key);
void set(const std::string& key, const std::string& value);
bool del(const std::string& key);
private:
std::unordered_map<std::string, std::string> store;
std::mutex mtx; // 支持并发访问
};
cpp
复制
编辑
// datastore.cpp
include "datastore.h"
std::string DataStore::get(const std::string& key) {
std::lock_guard<std::mutex> lock(mtx);
return store.count(key) ? store[key] : "nil";
}
void DataStore::set(const std::string& key, const std::string& value) {
std::lock_guard<std::mutex> lock(mtx);
store[key] = value;
}
bool DataStore::del(const std::string& key) {
std::lock_guard<std::mutex> lock(mtx);
return store.erase(key) > 0;
}
🧠 第二步:命令解析与执行(command.h/.cpp)
cpp
复制
编辑
// command.h
pragma once
include <string>
include "datastore.h"
std::string executeCommand(const std::string& input, DataStore& store);
cpp
复制
编辑
// command.cpp
include "command.h"
include <sstream>
include <vector>
std::vector<std::string> split(const std::string& str) {
std::istringstream iss(str);
std::string token;
std::vector<std::string> tokens;
while (iss >> token) tokens.push_back(token);
return tokens;
}
std::string executeCommand(const std::string& input, DataStore& store) {
auto tokens = split(input);
if (tokens.empty()) return "Invalid command\n";
const std::string& cmd = tokens[0];
if (cmd == "SET" && tokens.size() == 3) {
store.set(tokens[1], tokens[2]);
return "OK\n";
}
if (cmd == "GET" && tokens.size() == 2) {
return store.get(tokens[1]) + "\n";
}
if (cmd == "DEL" && tokens.size() == 2) {
return store.del(tokens[1]) ? "Deleted\n" : "Key not found\n";
}
if (cmd == "EXIT") {
return "BYE\n";
}
return "Unknown or invalid command\n";
}
🧠 第三步:网络服务模块(server.cpp)
使用 socket + select 处理多个客户端的连接
cpp
复制
编辑
// main.cpp
include "datastore.h"
include "command.h"
include <iostream>
include <thread>
include <netinet/in.h>
include <unistd.h>
void handleClient(int clientSocket, DataStore& store) {
char buffer[1024] = {0};
while (true) {
int bytes = read(clientSocket, buffer, sizeof(buffer) - 1);
if (bytes <= 0) break;
buffer[bytes] = '\0';
std::string response = executeCommand(buffer, store);
if (response == "BYE\n") {
write(clientSocket, response.c_str(), response.length());
break;
}
write(clientSocket, response.c_str(), response.length());
}
close(clientSocket);
}
int main() {
int server_fd, new_socket;
sockaddr_in address;
int opt = 1;
int addrlen = sizeof(address);
server_fd = socket(AF_INET, SOCK_STREAM, 0);
setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(6379);
bind(server_fd, (struct sockaddr*)&address, sizeof(address));
listen(server_fd, 3);
std::cout << "MiniRedis started on port 6379...\n";
DataStore store;
while (true) {
new_socket = accept(server_fd, (struct sockaddr*)&address, (socklen_t*)&addrlen);
std::thread(handleClient, new_socket, std::ref(store)).detach();
}
return 0;
}
✅ 示例运行效果
shell
复制
编辑
$ telnet localhost 6379
Trying 127.0.0.1...
Connected to localhost.
SET name ChatGPT
OK
GET name
ChatGPT
DEL name
Deleted
GET name
nil
EXIT
BYE
🚀 可扩展方向
你可以逐步扩展:
扩展内容 实现建议
支持过期时间 TTL 增加一个 map 存储过期时间 + 定时清理
实现 LRU 缓存 使用 std::list + map 双向链表实现
支持事务 MULTI 维护一个命令队列,等待 EXEC 执行
支持持久化(RDB) 将数据定期写入磁盘
客户端 CLI 工具 自定义命令行客户端
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。