当前位置:首页 > 日记 > 正文

本地数据库缓存实例MySQL实现价值

本地数据库缓存实例MySQL实现价值
有许多关键值的缓存,其中有许多是Memcached和Redis。它们以独立服务的形式运行。有时他们需要在工作中嵌入本地键值缓存。当然,还有LevelDB,等等,但感觉太重。

本文实现了一个超轻量级缓存,

1,实现代码只需要400行;

2。高性能。价值的测试速度约为每秒200万时长是1K

3、缓存映射到文件,所以没有架空malloc,自由,和内存泄漏,内存碎片,等等。

4,如果服务被挂起,缓存内容将在重启后继续存在。

5,如果缓存映射到磁盘文件,即使机器挂起,内容仍将存在于缓存中,当然,可能存在数据损坏的情况。

6,在一定程度上实现了LRU淘汰算法和LRU不在链的整体,所以它只能在一定的程序实现。

7,稳定,已经在一些项目中使用,在网上部署了几十台机器,运行半年已经不是问题了;

8,常用的缓存键,值是字符串的形式,缓存键,值可以是类,结构对象结构更方便使用;

旧规则直接在代码上:

复制代码代码如下所示:
模板
类Hashtable
{
公共:
哈希表(const char*的表名,uint32_t tablelen,uint32_t nodetotal);
虚拟~ HashTable();

布尔加(K,V值)
{
AutoLock autoLock(m_mutexlock);

检查是否存在
uint32_t NodeID = getidbykey(关键);
如果(NodeID!= m_invalidid)返回false;

节点ID = GetFreeNode();
如果(NodeID = = m_invalidid)返回false;

uint32_t = key.hashcode hashCode();
进入* tmpnode = m_entryaddr + NodeID;
tmpnode -> m_key =关键;
tmpnode -> m_code = hashCode;
tmpnode -> m_value =价值;

uint32_t指数= hashCode % m_headaddr -> m_tablelen;
addnodetohead(索引节点ID);

返回true;
}

Bool Del(K键)
{
AutoLock autoLock(m_mutexlock);

uint32_t NodeID = getidbykey(关键);
如果(NodeID = = m_invalidid)返回false;

key.hashcode uint32_t指数=()% m_headaddr -> m_tablelen;

返回RecycleNode(索引节点ID);
}

布尔集合(K,V值)
{
AutoLock autoLock(m_mutexlock);

uint32_t NodeID = getidbykey(关键);
如果(NodeID = = m_invalidid)返回false;

(m_entryaddr + NodeID)-> m_value =价值;

返回true;
}

布尔得到(k,v值)
{
AutoLock autoLock(m_mutexlock);

uint32_t NodeID = getidbykey(关键);
如果(NodeID = = m_invalidid)返回false;

价值=(m_entryaddr + NodeID)-> m_value;

返回true;
}

布尔的存在(K键)
{
AutoLock autoLock(m_mutexlock);

uint32_t NodeID = getidbykey(关键);
如果(NodeID = = m_invalidid)返回false;

返回true;
}

uint32_t计数()
{
AutoLock autoLock(m_mutexlock);
返回m_headaddr -> m_usedcount;
}

如果存在集其他添加
布尔取代(K键,V值)
{
AutoLock autoLock(m_mutexlock);

如果(存在(key))返回集(键,值);
其他返回加(键,值);
}

/ ***********************************************
* LRU:当访问一个节点,把它的头*
************************************************ /
如果没有空位置,回收尾部
Bool LruAdd(K,V值,K recykey,V recyvalue,bool再生)
{
AutoLock autoLock(m_mutexlock);

如果(存在(key))返回false;

如果(Add(key,value))返回true;

key.hashcode uint32_t指数=()% m_headaddr -> m_tablelen;
uint32_t tailid = gettailnodeid(指数);

如果(tailid = = m_invalidid)返回false;

进入* tmpnode = m_entryaddr + tailid;
recykey = tmpnode -> m_key;
recyvalue = tmpnode -> m_value;
循环=真实;

RecycleNode(索引,tailid);

返回添加(键,值);
}

Bool LruSet(K,V值)
{
AutoLock autoLock(m_mutexlock);

如果(集(键,值))返回movetohead(关键);
否则返回false;
}

Bool LruGet(K,V值)
{
AutoLock autoLock(m_mutexlock);

如果(把(键,值))返回movetohead(关键);
否则返回false;
}

如果存在其他设置,如果添加失败,回收尾;比添加
Bool LruReplace(K,V值,K recykey,V recyvalue,bool再生)
{
AutoLock autoLock(m_mutexlock);

回收=假;

如果(存在(关键))返回lruset(键,值);
否则返回lruadd(键,值,recykey,recyvalue,回收);
}

空清除()
{
AutoLock autoLock(m_mutexlock);

m_headaddr -> m_freebase = 0;
m_headaddr -> m_recyclehead = 0;
m_headaddr -> m_usedcount = 0;
对于(uint32_t i = 0;我m_tablelen;+ +我)
{
(m_arrayaddr +我)-> m_head = m_invalidid;
(m_arrayaddr +我)-> m_tail = m_invalidid;
}
}

Int GetRowKeys(向量键,uint32_t指数)
{
AutoLock autoLock(m_mutexlock);

如果返回1(指数> = m_headaddr -> m_tablelen);

Keys.clear();
(16)keys.reserve;

int计数= 0;
阵列* tmparray = m_arrayaddr +指数;
uint32_t NodeID = tmparray -> m_head;
而(NodeID!= m_invalidid)
{
进入* tmpnode = m_entryaddr + NodeID;
keys.push_back(tmpnode -> m_key);
节点ID = tmpnode -> m_next;
+计数;
}

返回计数;
}

void *垫(uint32_t大小)
{
AutoLock autoLock(m_mutexlock);

如果(大小> m_headsize - sizeof(tablehead))返回null;
否则返回m_headaddr -> m_padding;
}

私人:
静态常量uint32_t m_invalidid = 0xffffffff;
静态常量uint32_t m_headsize = 1024;
结构tablehead
{
uint32_t m_tablelen;
uint32_t m_nodetotal;
uint32_t m_freebase;
uint32_t m_recyclehead;
uint32_t m_usedcount;
焦m_tablename { 256 };
uint32_t m_padding { 0 };
};

结构数组
{
uint32_t m_head;
uint32_t m_tail;
};

结构进入
{
V m_value;
K m_key;
uint32_t m_code;
uint32_t m_next;
uint32_t m_prev;
};

size_t m_memsize;
uint8_t * m_memaddr;
tablehead * m_headaddr;
* m_arrayaddr阵列;
* m_entryaddr入门;

threadmutex m_mutexlock;

Bool MoveToHead(K键);
uint32_t getidbykey(K键);
无效addnodetohead(uint32_t指数,uint32_t NodeID);
布尔movenodetohead(uint32_t指数,uint32_t NodeID);
Bool RecycleNode(uint32_t指数,uint32_t NodeID);
uint32_t gettailnodeid(uint32_t指数);
uint32_t getfreenode();

disable_copy_and_assign(哈希表);
};

模板
哈希表::HashTable(const char*的表名,uint32_t tablelen,uint32_t nodetotal)
{
AbortAssert(TableName!= NULL);

m_memsize = m_headsize + tablelen * sizeof(数组)+ nodetotal * sizeof(进入);
m_memaddr =(uint8_t *)memfile::Realloc(TableName、m_memsize);
AbortAssert(m_memaddr!= NULL);

M_HeadAddr = (TableHead*) (m_MemAddr);
m_arrayaddr =(数组*)(m_memaddr + m_headsize);
m_entryaddr =(入门)(m_memaddr + m_headsize + tablelen * sizeof(数组));

m_headaddr -> m_tablelen = tablelen;
m_headaddr -> m_nodetotal = nodetotal;
Strncpy(m_headaddr -> m_tablename,表名,sizeof(m_headaddr -> m_tablename));

如果(m_headaddr -> m_usedcount = = 0) / /如果第一次使用初始化数组无效ID
{
对于(uint32_t i = 0;i < tablelen;+ +我)
{
(m_arrayaddr +我)-> m_head = m_invalidid;
(m_arrayaddr +我)-> m_tail = m_invalidid;
}

m_headaddr -> m_freebase = 0;
m_headaddr -> m_recyclehead = 0;
}
}

模板
哈希表::~哈希表()
{
memfile::释放(m_memaddr,m_memsize);
}

模板
Bool HashTable::movetohead(K键)
{
uint32_t NodeID = getidbykey(关键);
key.hashcode uint32_t指数=()% m_headaddr -> m_tablelen;

返回movenodetohead(索引节点ID);
}

模板
uint32_t哈希表::GetIdByKey(K键)
{
uint32_t = key.hashcode hashCode();
uint32_t指数= hashCode % m_headaddr -> m_tablelen;
阵列* tmparray = m_arrayaddr +指数;

uint32_t NodeID = tmparray -> m_head;
而(NodeID!= m_invalidid)
{
进入* tmpnode = m_entryaddr + NodeID;
如果(tmpnode -> m_code = = hashCode的关键。等于(tmpnode -> m_key))打破;

节点ID = tmpnode -> m_next;
}

返回节点ID;
}

模板
无效的哈希表::AddNodeToHead(uint32_t指数,uint32_t NodeID)
{
如果(指数m_headaddr -> m_tablelen NodeID m_headaddr -> m_nodetotal | | > > =回报);

阵列* tmparray = m_arrayaddr +指数;
进入* tmpnode = m_entryaddr + NodeID;
如果(m_invalidid = tmparray -> m_head)
{
tmparray -> m_head = NodeID;
tmparray -> m_tail = NodeID;
}
其他的
{
tmpnode -> m_next = tmparray -> m_head;
(m_entryaddr + tmparray -> m_head)-> m_prev = NodeID;
tmparray -> m_head = NodeID;
}
}

模板
Bool HashTable::movenodetohead(uint32_t指数,uint32_t NodeID)
{
如果(指数m_headaddr -> m_tablelen NodeID | | > > = m_headaddr -> m_nodetotal)返回false;

阵列* tmparray = m_arrayaddr +指数;
进入* tmpnode = m_entryaddr + NodeID;

/ /已经头
如果(tmparray -> m_head = NodeID)
{
返回true;
}

uint32_t nodeprev = tmpnode -> m_prev;
uint32_t nodenext = tmpnode -> m_next;
(m_entryaddr + nodeprev)-> m_next = nodenext;
如果(nodenext!= m_invalidid)
{
(m_entryaddr + nodenext)-> m_prev = nodeprev;
}
其他的
{
tmparray -> m_tail = nodeprev;
}

tmpnode -> m_prev = m_invalidid;
tmpnode -> m_next = tmparray -> m_head;
(m_entryaddr + tmparray -> m_head)-> m_prev = NodeID;
tmparray -> m_head = NodeID;

返回true;
}

模板
Bool HashTable::RecycleNode(uint32_t指数,uint32_t NodeID)
{
如果(指数m_headaddr -> m_tablelen NodeID | | > > = m_headaddr -> m_nodetotal)返回false;

阵列* tmparray = m_arrayaddr +指数;
进入* tmpnode = m_entryaddr + NodeID;

uint32_t nodeprev = tmpnode -> m_prev;
uint32_t nodenext = tmpnode -> m_next;

如果(nodeprev!= m_invalidid)
{
(m_entryaddr + nodeprev)-> m_next = nodenext;
}
其他的
{
tmparray -> m_head = nodenext;
}

如果(nodenext!= m_invalidid)
{
(m_entryaddr + nodenext)-> m_prev = nodeprev;
}
其他的
{
tmparray -> m_tail = nodeprev;
}

(m_entryaddr + NodeID)-> m_next = m_headaddr -> m_recyclehead;
m_headaddr -> m_recyclehead = NodeID;
-(m_headaddr -> m_usedcount);

返回true;
}

模板
uint32_t哈希表::gettailnodeid(uint32_t指数)
{
如果返回m_invalidid(指数> = m_headaddr -> m_tablelen);

阵列* tmparray = m_arrayaddr +指数;

返回tmparray -> m_tail;
}

模板
uint32_t哈希表::GetFreeNode()
{
uint32_t NodeID = m_invalidid;
如果(m_headaddr -> m_usedcount m_freebase) / /获得循环列表
{
节点ID = m_headaddr -> m_recyclehead;
m_headaddr -> m_recyclehead =(m_entryaddr + NodeID)-> m_next;
+ +(m_headaddr -> m_usedcount);
}
如果(m_headaddr -> m_usedcount m_nodetotal) / /获得自由的人
{
节点ID = m_headaddr -> m_freebase;
+ +(m_headaddr -> m_freebase);
+ +(m_headaddr -> m_usedcount);
}
其他的
{
m_invalidid NodeID =;
}

初始化节点
如果(NodeID m_nodetotal)
{
进入* tmpnode = m_entryaddr + NodeID;
memset(tmpnode,0,sizeof(入口));

tmpnode -> m_next = m_invalidid;
tmpnode -> m_prev = m_invalidid;
}

返回节点ID;
}

相关文章

MySQL插入数据时插入无效列的解决

MySQL插入数据时插入无效列的解决

插入数据,解决方案,无效,电脑软件,MySQL,1,错误描述 com。MySQL JDBC。例外:jdbc4 mysqlsyntaxerrorexception:未知column'man'in'field列表。 2,错误的原因 数据库表中的字段名圣人ssex:SnO 当数据被插入:SnO SNAME圣人的人 它最初是用…

Win8安装共享打印机的步骤方法

Win8安装共享打印机的步骤方法

安装,方法,步骤,电脑软件,点评:这篇文章主要介绍了打印机的Win8安装的步骤和方法,需要的朋友可以参考一下。 这是打印在Windows现在容易得多。当你连接一个打印机一台电脑或添加新的打印机,家庭网络,您可以立即开始打印。对大多数人来说,这是所…

如何在使用手机QQ浏览器的过程中关

如何在使用手机QQ浏览器的过程中关

关闭窗口,浏览器,过程中,如何在,电脑软件,如何在使用手机QQ浏览器的过程中关闭窗口 Symbian平台:使用C键(清除键)可以快速关闭窗口;或者选择软件提示下的窗口数,点击X;可以关闭窗口。 其他平台:选择软件提示下的窗口数,点击X;可以关闭窗口。…

Oracle子程序参数模式,,,nocopy

Oracle子程序参数模式,,,nocopy

子程序参数,模式,电脑软件,Oracle,nocopy,在主要用于传入参数,可以是变量,常量,表达式,并且不能改变它们的值在子程序中。 复制代码代码如下所示: 声明 n数=10; 程序(do_something N1数) 开始 dbms_output.put_line(N1);-打印10 ——N1=20;非法赋值。 结…

Windows8关闭切换程序软件运行的方

Windows8关闭切换程序软件运行的方

方法,运行,程序,电脑软件,点评:在Windows8 Metro界面,运行太多软件和资源占用和关闭程序也很烦人。现在我想教你在切换程序中快速关闭软件程序。 当windows8metro软件界面,运行太多的资源和关闭程序是很烦人的,有些人干脆用;结束任务管理器;运行…

对opwarese2.exe-使用opwarese2是

对opwarese2.exe-使用opwarese2是

电脑软件,exe,评论:详细的介绍了opwarese2.exe - opwarese2过程 进程文件:opwarese2或opwarese2.exe 进程名称:ScanSoft omnipage模块 过程类别:安全风险的过程 英文描述: 是一个从opwarese2.exe omnipage ScanSoft相关过程。omnipage,omnipage…

excel三条件函数求解实用方法

excel三条件函数求解实用方法

条件,方法,函数,电脑软件,excel,秋天和冬至一样长,到了年底,在工作中,数据量和总结的操作要比平时多很多,众所周知,数据可以用excel的不同方式计算和汇总。今天,我将介绍三个兄弟,他们的功能是有条件的。他们是COUNTIF,,,sumif,if,和功能,它们有一个共同…

如何禁用DirectDrawwin7下解决停电

如何禁用DirectDrawwin7下解决停电

截图,电脑软件,点评:截图时出现打黑,可以通过禁用directdraw.directdraw解决已经启用Windows XP和Windows 7下,它不能在Windows 7下禁用。这里我们介绍DirectDraw在其他方面。 有两种方法可以解决播放时屏幕发黑的问题。通常有四种方法来解决…

s3tray2是s3tray2.exe-使用

s3tray2是s3tray2.exe-使用

电脑软件,exe,点评:s3tray2.exe是S3显示卡的视频输出设备相关的程序 进程文件:s3tray2或s3tray2.exe 过程名称:S3视频 过程类别:安全风险的过程 英文描述: s3tray2.exe是工具安装在您的S3视频输出设备的驱动程序,并提供额外的配置和诊断。这是…

屏幕文件的存储位置不能自行设置(解

屏幕文件的存储位置不能自行设置(解

存储位置,文件,设置,屏幕,解决方案,问题: 我们上面的截图文件的5版本只能保存,固定到C盘,但是不能保存一个自定义位置,为什么 答案uff1a 我们的新版本的5.8.130为了便于文件的管理是截取的画面,视频,动画截取的同一位置,GIF缩略图保存,并显示在列…

secondarylogon的过程是怎样的

secondarylogon的过程是怎样的

的是,过程,是怎样,电脑软件,secondarylogon,检查:启用替换凭据下的启用过程。如果此服务终止,则将无法使用此类型的登录访问。如果此服务已禁用,则依赖该服务的任何服务都将无法启动。 今天secondarylogon过程是怎样的事实上,没有太多的second…

利用oracle的解码功能进行多值判断

利用oracle的解码功能进行多值判断

解码,功能,电脑软件,oracle,解码函数的语法结构如下所示: 复制代码代码如下所示: 解码(表达search_1,result_1) 解码(表达search_1,result_1,search_2,result_2) 解码(表达search_1,result_1,search_2,result_2,…,search_n,result_n) 解码(表达search_1,resu…