最简单的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. eclipse 安装配置

    https://blog.csdn.net/jklinux/article/details/77861450 JAVA环境配置 https://jingyan.baidu.com/article/db ...

  2. buffers和cached的区别

    原文:https://www.cnblogs.com/kevingrace/p/5991604.html buffers和cached解释 ============================== ...

  3. G2( bizCharts ) React 绘制混合图例

    G2( bizCharts ) React 绘制混合图例, // data-set 可以按需引入,除此之外不要引入别的包 import React from 'react'; import { Cha ...

  4. C++Primer第五版——习题答案详解(五)

    习题答案目录:https://www.cnblogs.com/Mered1th/p/10485695.html 第6章 函数 练习6.4 #include<iostream> using ...

  5. Percona XtraDB Cluster Strict Mode(PXC 5.7)

    在Percona XtraDB Cluster集群架构中,为了避免多主节点导致的数据异常,或者说一些不被支持的特性引发的数据不一致的情形,PXC集群可以通过配置pxc_strict_mode这个变量来 ...

  6. 第25课 可变参数模板(6)_function_traits和ScopeGuard的实现

    1. function_traits (1)function_traits的作用:获取函数的实际类型.返回值类型.参数个数和具体类型等.它能获取所有函数语义类型信息.可以获取普通函数.函数指针.std ...

  7. [UnityAPI]DataUtility类

    测试环境: 准备三张图片a,b,c,其中a,b打在同一图集,c不打图集,a,b如下: 测试脚本: using UnityEngine; using UnityEngine.Sprites; publi ...

  8. 在BootStrap的modal中使用Select2搜索框无法输入

    用modal来show一个对话框 dialog.modal({ backdrop:true, keyboard:true, show:true }); 1 2 3 4 5 然后再modal中初始化se ...

  9. 03 字符串常用操作方法及For 循环

    字符串常用操作 s = 'alexWUsir' s1 = s.capitalize() #首字母大写 print(s1) #Alexwusir s2 = s.upper() #全部大写 print(s ...

  10. python使用细节

    python的函数位置参数在调用时可以直接传参,也可以a=5,b=7的形式传参,原以为kw参数才可以. >>> def f(a,b): print a+b >>> ...