最简单的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. Substring方法(C#,JS,Java,SQL)的区别

    C#: substring(第一参数,第二参数)//  第一参数:从第几位开始截,初始是从0位开始  第二参数:截取几位 substring(参数)  如果传入参数为一个长整, 且大于等于0,则以这个 ...

  2. spring4.0之二:@Configuration的使用

    从Spring3.0,@Configuration用于定义配置类,可替换xml配置文件,被注解的类内部包含有一个或多个被@Bean注解的方法,这些方法将会被AnnotationConfigApplic ...

  3. 对pytorch中Tensor的剖析

    不是python层面Tensor的剖析,是C层面的剖析. 看pytorch下lib库中的TH好一阵子了,TH也是torch7下面的一个重要的库. 可以在torch的github上看到相关文档.看了半天 ...

  4. Vue 重点 必须要记住的

    基础知识: vue的生命周期: beforeCreate/created. beforeMount/mounted. beforeUpdate/updated. beforeDestory/desto ...

  5. 一步步实现:springbean的生命周期测试代码

    转载. https://blog.csdn.net/baidu_37107022/article/details/76552052 1. 创建实体SpringBean public class Spr ...

  6. python自带的进程池及线程池

    进程池 """ python自带的进程池 """ from multiprocessing import Pool from time im ...

  7. 中间件weblogic控制台创建数据源报错---根据真实故事改编

    1.在weblogic控制台创建数据源,有报错--不能创建数据源,图免 2.weblogic数据源管理节点所在服务器telnet测试,到数据库1521端口是通的 3.经过请教各路大神,得出结论:由于子 ...

  8. 使用libvirtAPI打快照原理

    参考: https://blog.51cto.com/3646344/2096347 https://blog.51cto.com/3646344/2096351(磁盘外部快照) API接口: htt ...

  9. python_09 文件处理流程,文件操作方法

    文件处理流程 1.打开文件,得到文件句柄并赋值给一个变量 2.通过句柄对文件进行操作 3.关闭文件 f=open('test.txt',encoding='gbk') data = f.read() ...

  10. python爬虫之scrapy

    架构概览 本文档介绍了Scrapy架构及其组件之间的交互. 概述 接下来的图表展现了Scrapy的架构,包括组件及在系统中发生的数据流的概览(绿色箭头所示). 下面对每个组件都做了简单介绍,并给出了详 ...