本地数据库缓存实例MySQL实现价值
本文实现了一个超轻量级缓存,
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;
}