最简单的kv db

最基本的网络连接 使用STL map存储key value 作为多线程互斥的简单例子。

以后有机会逐步优化添加功能

1增加ASIO 异步通讯

2优化存储空间 传递指针 避免过多的拷贝操作

3优化代码结构

4优化全局锁 操作map时候 锁定部分区域而不是锁全局 。(思路在之前博客有提过多线程查找大量数据加锁的速度降低)

效果图:

部分代码

 #include "NetWork.h"
#include "Handler.h"
#include <thread> void DEF::NetWorkClass::work() {
try {
while () {
std::shared_ptr<boost::asio::ip::tcp::socket> psocket =
std::make_shared<boost::asio::ip::tcp::socket>(*pio_service_);
pacceptor_->accept(*psocket);
std::thread t = std::thread(DEF::Handler, psocket);
t.detach();
}
}
catch (std::exception& e) {
std::cerr << __FUNCTION__ << " " <<
e.what() << std::endl;
}
return;
}

NetWork.cpp

#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

NetWork.h

 #pragma once
#include "PreHead.h"
#include <memory>
#include <iostream>
#include <boost/asio.hpp> NAMESPACEBEGIN(DEF) bool Handler(std::shared_ptr<boost::asio::ip::tcp::socket> psocket); struct Item {
std::string command_;
std::string key_;
std::string value_;
std::string result_;
}; class ParseRecvString {
public:
static void TestSplitBySpace();
static std::vector<std::string> SplitBySpace(const std::string& recvStr) {
std::vector<std::string> vecStr;
size_t begPos = recvStr.find_first_not_of(' ');
size_t endPos = recvStr.find_first_of(' ', begPos+);
while (begPos != std::string::npos) {
endPos = recvStr.find_first_of(' ', begPos);
if (endPos != std::string::npos){
vecStr.push_back(recvStr.substr(begPos, endPos - begPos));
begPos = recvStr.find_first_not_of(' ', endPos + );
}
else {
vecStr.push_back(recvStr.substr(begPos));
begPos = endPos;
}
} return vecStr;
} private:
}; class CommandHandler {
public:
CommandHandler(const std::vector<std::string>& command) :command_(command) {} private:
std::vector<std::string> command_;
}; class Session {
public:
Session(std::shared_ptr<boost::asio::ip::tcp::socket> psocket): psocket_(psocket){}
Session(const Session& s) = delete;
Session operator=(const Session& s) = delete;
bool LoopHandle();
private:
void SetFunc(const std::vector<std::string>& vecStr, Item& item);
void GetFunc(const std::vector<std::string>& vecStr, Item& item);
void AppendFunc(const std::vector<std::string>& vecStr, Item& item);
void PreAppendFunc(const std::vector<std::string>& vecStr, Item& item);
void DeleteFunc(const std::vector<std::string>& vecStr, Item& item);
void DispatchCommand(const std::vector<std::string>& vecStr, Item& item);
bool ParseRecvData(char* recvData,size_t len,Item& item);
std::shared_ptr<boost::asio::ip::tcp::socket> psocket_;
}; NAMESPACEEND

Handler.h

#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() >= );
bool b = g_dbStored.InsertDBWithLock(vecStr[], vecStr[]);
item.key_ = vecStr[];
item.value_ = vecStr[];
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() >= );
std::string getVal;
bool b = g_dbStored.GetFromDbWithLock(vecStr[], getVal);
item.key_ = vecStr[];
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(); return ;
} void DEF::Session::PreAppendFunc(const std::vector<std::string>& vecStr, Item& item) {
assert(); 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[];
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() == && vs[] == "set");
vs.clear();
vs = DEF::ParseRecvString::SplitBySpace(s2);
assert(vs.size() == && vs[] == "set");
vs.clear();
vs = DEF::ParseRecvString::SplitBySpace(s3);
assert(vs.size() == && vs[] == "set");
vs.clear();
vs = DEF::ParseRecvString::SplitBySpace(s4);
assert(vs.size() == && vs[] == "set");
vs.clear();
vs = DEF::ParseRecvString::SplitBySpace(s5);
assert(vs.size() == && vs[] == "set" && vs[] == "mykey" && vs[] == "myvalue");
vs.clear();
vs = DEF::ParseRecvString::SplitBySpace(s6);
assert(vs.size() == && vs[] == "set" && vs[] == "mykey" && vs[] == "myvalue");
vs.clear();
vs = DEF::ParseRecvString::SplitBySpace(s7);
assert(vs.size() == && vs[] == "set" && vs[] == "mykey" && vs[] == "myvalue");
vs.clear();
vs = DEF::ParseRecvString::SplitBySpace(s8);
assert(vs.size() == && vs[] == "set" && vs[] == "mykey" && vs[] == "myvalue");
vs.clear();
} bool DEF::Session::LoopHandle() {
bool b = false;
if (psocket_ == nullptr)
return b;
char recvData[];
try {
while () {
boost::system::error_code error;
size_t len = psocket_->read_some(boost::asio::buffer(recvData,), 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;
}

Handler.cpp

my simplest kv db的更多相关文章

  1. 一些开源搜索引擎实现——倒排使用原始文件,列存储Hbase,KV store如levelDB、mongoDB、redis,以及SQL的,如sqlite或者xxSQL

    本文说明:除开ES,Solr,sphinx系列的其他开源搜索引擎汇总于此.   A search engine based on Node.js and LevelDB A persistent, n ...

  2. Sina App Engine(SAE)入门教程(3)-KVDB使用

    简介 因为传统关系型数据库在分布式环境下表现的扩展性不足等缺点,近年来NoSQL的概念渐渐成为业界关注的焦点,越来越多的技术人员也习惯于使用NoSQL数据库进行日常开发,SAE为了应对这种新需求,也进 ...

  3. 优秀it博客和文章

    优秀博客 综合 杨文博(供职于百度公司,任复合搜索部资深研发工程师,目前作为tech lead,负责垂直行业搜索后端架构研发.) 杨远骋 徐宥(Google 软件工程师. 这个中文博客是我的思考记录, ...

  4. 广告频次控制(frequency capping)

    频次控制介绍 广告中的频次控制是指控制一个用户最多在指定时间内看到一个广告(或相似广告)的次数,比如广告主可以限制一个用户最多只能一天看到一个广告3次(频次控制也可以让publisher来指定,但本文 ...

  5. ledisdb:支持类redis接口的嵌入式nosql

    ledisdb现在可以支持嵌入式使用.你可以将其作为一个独立的lib(类似leveldb)直接嵌入到你自己的应用中去,而无需在启动单独的服务. ledisdb提供的API仍然类似redis接口.首先, ...

  6. kv_storage.go

    package storage //kv 存储引擎实现 import (     "github.com/cznic/kv"     "io" ) //kv 存 ...

  7. MIT-6.824 Lab 3: Fault-tolerant Key/Value Service

    概述 lab2中实现了raft协议,本lab将在raft之上实现一个可容错的k/v存储服务,第一部分是实现一个不带日志压缩的版本,第二部分是实现日志压缩.时间原因我只完成了第一部分. 设计思路 如上图 ...

  8. 根据已经commit的数据,进行leader和peon之间的同步

    Leader Election基本设计 按照rank表示优先级解决冲突问题,为每个monitor预先分配了一个rank 只会接受优先级(rank)比自己高.epoch比上次已接受的epoch大的选举请 ...

  9. Storage,Memcache,KVDB都是存储服务,如何区分何时用何种服务

    Storage :是SAE为开发者提供的分布式文件存储服务,用来存放用户的持久化存储的文件.用户需要先在在线管理平台创建Domain(相当于一级子目录).    Storage为开发者提供分布式文件存 ...

随机推荐

  1. 记一次sql server 2005访问http接口,并解析json的过程

    记一次sql server 2005访问http接口,并解析json的过程  JSON解析官方网站:https://www.red-gate.com/simple-talk/sql/t-sql-pro ...

  2. 算法实践--最小生成树(Prim算法)

    前一篇介绍了一种最小生成树的算法--Kruskal算法,本篇介绍另一种Prim算法 算法描述 定义V为端点的集合,A为最小生成树,初始为空.对于每个端点v初始的Key[v]=∞, Parent[v]= ...

  3. 涨姿势:深入 foreach循环

    我们知道集合中的遍历都是通过迭代(iterator)完成的. 也许有人说,不一定非要使用迭代,如: List<String> list = new LinkedList<String ...

  4. Pillow《转载》

    Pillow https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/001432002 ...

  5. psi

    purchase 采购sales 销售inventory 库存 outstock/instock/inventory taking outstock/instock/inventory 出库 入库 盘 ...

  6. 普通PC机支持内存128G,单条32G内存

    以前,不管是英特尔还是AMD的消费级平台支持内存容量大多都是64GB,这一现状被英特尔公司去年推出的第九代酷睿而改变.第九代酷睿最大支持128GB内存,虽然只是简单的提高了内存容量,对大多数电脑用户而 ...

  7. leetcode每日刷题计划-简单篇day3

    收到swe提前批面试hhh算是ep挂了的后续 努力刷题呀争取今年冲进去! Num 21 合并两个有序链表 Merge Two Sorted Lists 注意新开的链表用来输出结果的是ListNode ...

  8. leetcode136

    public class Solution { public int SingleNumber(int[] nums) { Dictionary<int, int> dic = new D ...

  9. javascript权威指南第1章Js概述js语言核心

    <html> <head> <script> function Point(x,y){ this.x=x; this.y=y; } ,); console.log( ...

  10. Java编写串口程序

    用Java编写串口程序一般都会用到这个 http://fizzed.com/oss/rxtx-for-java 根据电脑的情况下载 解压以后有安装文档 For a JDK installation: ...