my simplest kv db
最简单的kv db
最基本的网络连接 使用STL map存储key value 作为多线程互斥的简单例子。
以后有机会逐步优化添加功能
1增加ASIO 异步通讯
2优化存储空间 传递指针 避免过多的拷贝操作
3优化代码结构
4优化全局锁 操作map时候 锁定部分区域而不是锁全局 。(思路在之前博客有提过多线程查找大量数据加锁的速度降低)
效果图:
部分代码

1 #include "NetWork.h" 2 #include "Handler.h" 3 #include <thread> 4 5 6 void DEF::NetWorkClass::work() { 7 try { 8 while (1) { 9 std::shared_ptr<boost::asio::ip::tcp::socket> psocket = 10 std::make_shared<boost::asio::ip::tcp::socket>(*pio_service_); 11 pacceptor_->accept(*psocket); 12 std::thread t = std::thread(DEF::Handler, psocket); 13 t.detach(); 14 } 15 } 16 catch (std::exception& e) { 17 std::cerr << __FUNCTION__ << " " << 18 e.what() << std::endl; 19 } 20 return; 21 }

#pragma once #include "PreHead.h" #include <boost/asio.hpp> #include <memory> #include <iostream> using boost::asio::ip::tcp; NAMESPACEBEGIN(DEF) class NetWorkClass { public: NetWorkClass(short port):port_(port),pacceptor_ (nullptr), pio_service_(nullptr){} bool Init() { bool b = false; pio_service_ = std::make_shared<boost::asio::io_service>(); if (nullptr == pio_service_) { std::cerr << __FUNCTION__ << " make io_service() error!" << std::endl; return b; } pacceptor_ = std::make_shared<tcp::acceptor>(*pio_service_, tcp::endpoint(tcp::v4(), port_)); if (nullptr == pio_service_) { std::cerr << __FUNCTION__ << " make acceptor() error!" << std::endl; return b; } b = true; return b; } void work(); private: short port_; std::shared_ptr<tcp::acceptor> pacceptor_; std::shared_ptr<boost::asio::io_service> pio_service_; }; NAMESPACEEND

1 #pragma once 2 #include "PreHead.h" 3 #include <memory> 4 #include <iostream> 5 #include <boost/asio.hpp> 6 7 NAMESPACEBEGIN(DEF) 8 9 bool Handler(std::shared_ptr<boost::asio::ip::tcp::socket> psocket); 10 11 struct Item { 12 std::string command_; 13 std::string key_; 14 std::string value_; 15 std::string result_; 16 }; 17 18 class ParseRecvString { 19 public: 20 static void TestSplitBySpace(); 21 static std::vector<std::string> SplitBySpace(const std::string& recvStr) { 22 std::vector<std::string> vecStr; 23 size_t begPos = recvStr.find_first_not_of(' '); 24 size_t endPos = recvStr.find_first_of(' ', begPos+1); 25 while (begPos != std::string::npos) { 26 endPos = recvStr.find_first_of(' ', begPos); 27 if (endPos != std::string::npos){ 28 vecStr.push_back(recvStr.substr(begPos, endPos - begPos)); 29 begPos = recvStr.find_first_not_of(' ', endPos + 1); 30 } 31 else { 32 vecStr.push_back(recvStr.substr(begPos)); 33 begPos = endPos; 34 } 35 } 36 37 return vecStr; 38 } 39 40 private: 41 }; 42 43 class CommandHandler { 44 public: 45 CommandHandler(const std::vector<std::string>& command) :command_(command) {} 46 47 private: 48 std::vector<std::string> command_; 49 }; 50 51 class Session { 52 public: 53 Session(std::shared_ptr<boost::asio::ip::tcp::socket> psocket): psocket_(psocket){} 54 Session(const Session& s) = delete; 55 Session operator=(const Session& s) = delete; 56 bool LoopHandle(); 57 private: 58 void SetFunc(const std::vector<std::string>& vecStr, Item& item); 59 void GetFunc(const std::vector<std::string>& vecStr, Item& item); 60 void AppendFunc(const std::vector<std::string>& vecStr, Item& item); 61 void PreAppendFunc(const std::vector<std::string>& vecStr, Item& item); 62 void DeleteFunc(const std::vector<std::string>& vecStr, Item& item); 63 void DispatchCommand(const std::vector<std::string>& vecStr, Item& item); 64 bool ParseRecvData(char* recvData,size_t len,Item& item); 65 std::shared_ptr<boost::asio::ip::tcp::socket> psocket_; 66 }; 67 68 69 70 NAMESPACEEND

#include "Handler.h" #include "DbStored.h" #include <iostream> #include <string> extern DEF::DBStored g_dbStored; bool DEF::Handler(std::shared_ptr<boost::asio::ip::tcp::socket> psocket) { bool b = false; Session s(psocket); b = s.LoopHandle(); return b; } bool DEF::Session::ParseRecvData(char* recvData, size_t len, Item& item) { bool b = false; recvData[len] = '\0'; std::string recvstr(recvData); std::vector<std::string> vecStr = ParseRecvString::SplitBySpace(recvstr); DispatchCommand(vecStr,item); return b; } void DEF::Session::SetFunc(const std::vector<std::string>& vecStr, Item& item) { assert(vecStr.size() >= 3); bool b = g_dbStored.InsertDBWithLock(vecStr[1], vecStr[2]); item.key_ = vecStr[1]; item.value_ = vecStr[2]; if (b) { item.result_ = "STORED"; } else { item.result_ = "STORED_FAILED"; } return ; } void DEF::Session::GetFunc(const std::vector<std::string>& vecStr, Item& item) { assert(vecStr.size() >= 2); std::string getVal; bool b = g_dbStored.GetFromDbWithLock(vecStr[1], getVal); item.key_ = vecStr[1]; item.value_ = getVal; if (b) { item.result_ = getVal; } else { item.result_ = "GET_FAILED"; } return ; } void DEF::Session::AppendFunc(const std::vector<std::string>& vecStr, Item& item) { assert(0); return ; } void DEF::Session::PreAppendFunc(const std::vector<std::string>& vecStr, Item& item) { assert(0); return ; } void DEF::Session::DeleteFunc(const std::vector<std::string>& vecStr, Item& item) { return ; } void DEF::Session::DispatchCommand(const std::vector<std::string>& vecStr, Item& item) { std::string s = vecStr[0]; std::string result; transform(s.begin(), s.end(), s.begin(), tolower); //可使用MAP 进行命令分发 if (s == "set") { item.command_ = "set"; SetFunc(vecStr, item); } else if (s == "get") { item.command_ = "get"; GetFunc(vecStr, item); } else if (s == "append") { item.command_ = "append"; AppendFunc(vecStr, item); } else if (s == "preappend") { item.command_ = "preappend"; PreAppendFunc(vecStr, item); } else if (s == "del") { item.command_ = "del"; DeleteFunc(vecStr, item); } else { item.result_ = "ERROR_COMMAND"; } return; } void DEF::ParseRecvString::TestSplitBySpace() { std::string s1 = " set "; std::string s2 = " set"; std::string s3 = "set"; std::string s4 = "set "; std::string s5 = " set mykey myvalue"; std::string s6 = " set mykey myvalue "; std::string s7 = " set mykey myvalue "; std::string s8 = "set mykey myvalue"; std::vector<std::string> vs; vs = DEF::ParseRecvString::SplitBySpace(s1); assert(vs.size() == 1 && vs[0] == "set"); vs.clear(); vs = DEF::ParseRecvString::SplitBySpace(s2); assert(vs.size() == 1 && vs[0] == "set"); vs.clear(); vs = DEF::ParseRecvString::SplitBySpace(s3); assert(vs.size() == 1 && vs[0] == "set"); vs.clear(); vs = DEF::ParseRecvString::SplitBySpace(s4); assert(vs.size() == 1 && vs[0] == "set"); vs.clear(); vs = DEF::ParseRecvString::SplitBySpace(s5); assert(vs.size() == 3 && vs[0] == "set" && vs[1] == "mykey" && vs[2] == "myvalue"); vs.clear(); vs = DEF::ParseRecvString::SplitBySpace(s6); assert(vs.size() == 3 && vs[0] == "set" && vs[1] == "mykey" && vs[2] == "myvalue"); vs.clear(); vs = DEF::ParseRecvString::SplitBySpace(s7); assert(vs.size() == 3 && vs[0] == "set" && vs[1] == "mykey" && vs[2] == "myvalue"); vs.clear(); vs = DEF::ParseRecvString::SplitBySpace(s8); assert(vs.size() == 3 && vs[0] == "set" && vs[1] == "mykey" && vs[2] == "myvalue"); vs.clear(); } bool DEF::Session::LoopHandle() { bool b = false; if (psocket_ == nullptr) return b; char recvData[1024]; try { while (1) { boost::system::error_code error; size_t len = psocket_->read_some(boost::asio::buffer(recvData,1024), error); if (error == boost::asio::error::eof) { return (b = true); } else if (error) { throw boost::system::system_error(error); } Item item; b = ParseRecvData(recvData, len,item); len = psocket_->write_some(boost::asio::buffer(item.result_.c_str(),item.result_.size()), error); if (error) { throw boost::system::system_error(error); } } } catch (std::exception& e) { std::cerr << e.what() << std::endl; } return b; }
作 者: itdef
欢迎转帖 请保持文本完整并注明出处
技术博客 http://www.cnblogs.com/itdef/
B站算法视频题解
https://space.bilibili.com/18508846
qq 151435887
gitee https://gitee.com/def/
欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
如果觉得不错,欢迎点赞,你的鼓励就是我的动力
欢迎转帖 请保持文本完整并注明出处
技术博客 http://www.cnblogs.com/itdef/
B站算法视频题解
https://space.bilibili.com/18508846
qq 151435887
gitee https://gitee.com/def/
欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
如果觉得不错,欢迎点赞,你的鼓励就是我的动力


【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话