最简单的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. No input file specified.

    no input file specified 解决方法 2018年02月23日 14:25:07 tiramisuer8023 阅读数:36607   版权声明:本文为博主原创文章,未经博主允许不得 ...

  2. Ubuntu 16.04 安装 JDK 1.8

    系统环境 Ubuntu 16.04; JDK 1.8 配置安装 1.首先从oracle下载jdk 1.8,我下载的版本是jdk-8u131-linux-x64.tar.gz,运行tar zvxf jd ...

  3. 使用Tensorflow操作MNIST数据

    MNIST是一个非常有名的手写体数字识别数据集,在很多资料中,这个数据集都会被用作深度学习的入门样例.而TensorFlow的封装让使用MNIST数据集变得更加方便.MNIST数据集是NIST数据集的 ...

  4. 错误 CS0006 Metadata file 'E:\项目名称\xxxx.dll'

    错误 CS0006 Metadata file 'E:\桌面临时文件\Pos\xxxx.dll' 1.找到这个类库在当前类库右键发生 找到 应用程序-->把程序集名称改成提示错误 的名称 2.找 ...

  5. MYSQL SQL语句技巧初探(一)

    MYSQL SQL语句技巧初探(一) 本文是我最近了解到的sql某些方法()组合实现一些功能的总结以后还会更新: rand与rand(n)实现提取随机行及order by原理的探讨. Bit_and, ...

  6. PyQt5系列教程(六)如何让界面和逻辑分离

    软硬件环境 OS X EI Capitan Python 3.5.1 PyQt 5.5.1 PyCharm 5.0.3 前言 前面的内容我们介绍了利用QtDesigner来设计界面,再通过命令行工具p ...

  7. OS与Internet

    1 操作系统 操作系统(Operating System,简称OS)是管理和控制计算机硬件与软件资源的计算机程序,是直接运行在“裸机”上的最基本的系统软件,任何其他软件都必须在操作系统的支持下才能运行 ...

  8. leetcode239

    class Solution: def maxSlidingWindow(self, nums: 'List[int]', k: int) -> 'List[int]': n = len(num ...

  9. <记录> PHP监控进程状态,完成掉线自动重启

    1. 利用Shell脚本实现 #!/bin/bash PORT= while [ true ];do read -p "please enter the port that you want ...

  10. IO密集型和计算密集型

    我们常说的多任务或者单任务分为两种: IO密集型的任务  计算密集型的任务   IO密集型的任务或:有阻塞的状态,就是不一直会运行CPU(中间就一个等待状态,就告诉CPU 等待状态,这个就叫IO密集型 ...