加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > MySql教程 > 正文

Mysql入门mysql实现本地keyvalue数据库缓存示例

发布时间:2020-12-12 01:13:33 所属栏目:MySql教程 来源:网络整理
导读:《Mysql入门mysql实现本地keyvalue数据库缓存示例》要点: 本文介绍了Mysql入门mysql实现本地keyvalue数据库缓存示例,希望对您有用。如果有疑问,可以联系我们。 MYSQL入门 Key-Value缓存有很多,用的较多的是memcache、redis,他们都是以独立服务的形式运行,

《Mysql入门mysql实现本地keyvalue数据库缓存示例》要点:
本文介绍了Mysql入门mysql实现本地keyvalue数据库缓存示例,希望对您有用。如果有疑问,可以联系我们。

MYSQL入门Key-Value缓存有很多,用的较多的是memcache、redis,他们都是以独立服务的形式运行,在工作中有时需要嵌入一个本地的key-value缓存,当然已经有LevelDb等,但感觉还是太重量级了.

MYSQL入门本文实现了一种超级轻量的缓存,

MYSQL入门1、实现代码仅仅需要400行;

MYSQL入门2、性能高效,value长度在1K时测试速度在每秒200万左右

MYSQL入门3、缓存是映射到文件中的,所以没有malloc、free的开销,以及带来的内存泄露、内存碎片等;

MYSQL入门4、如果服务挂掉了,重启后缓存内容继续存在;

MYSQL入门5、如果把缓存映射到磁盘文件就算机器挂了,缓存中内容还是会存在,当然有可能会出现数据损坏的情况;

MYSQL入门6、一定程度上实现了LRU淘汰算法,实现的LRU不是全局的只是一条链上的,所以只能说在一定程序上实现了;

MYSQL入门7、稳定,已经在多个项目中运用,线上部署的机器有几十台,运行了大半年了没出过问题;

MYSQL入门8、普通的缓存key、value都是字符串的形式,此缓存的key、value都可以是class、struct对象结构使用更方便;

MYSQL入门?老规矩直接上代码:

MYSQL入门?

代码如下:
?template<typename K,typename V>
class HashTable
{
public:
??? HashTable(const char *tablename,uint32_t tableLen,uint32_t nodeTotal);
??? virtual ~HashTable();

??? bool Add(K &key,V &value)
??? {
??????? AutoLock autoLock(m_MutexLock);

??????? //check is exist
??????? uint32_t nodeId = GetIdByKey(key);
??????? if(nodeId != m_InvalidId) return false;

??????? nodeId = GetFreeNode();
??????? if(nodeId == m_InvalidId) return false;

??????? uint32_t hashCode = key.HashCode();
??????? Entry *tmpNode = m_EntryAddr + nodeId;
??????? tmpNode->m_Key = key;
??????? tmpNode->m_Code = hashCode;
??????? tmpNode->m_Value = value;

??????? uint32_t index = hashCode % m_HeadAddr->m_TableLen;
??????? AddNodeToHead(index,nodeId);

??????? return true;
??? }

??? bool Del(K &key)
??? {
??????? AutoLock autoLock(m_MutexLock);

??????? uint32_t nodeId = GetIdByKey(key);
??????? if(nodeId == m_InvalidId) return false;

??????? uint32_t index = key.HashCode() % m_HeadAddr->m_TableLen;

??????? return RecycleNode(index,nodeId);
??? }

??? bool Set(K &key,V &value)
??? {
??????? AutoLock autoLock(m_MutexLock);

??????? uint32_t nodeId = GetIdByKey(key);
??????? if(nodeId == m_InvalidId) return false;

??????? (m_EntryAddr + nodeId)->m_Value = value;

??????? return true;
??? }

??? bool Get(K &key,V &value)
??? {
??????? AutoLock autoLock(m_MutexLock);

??????? uint32_t nodeId = GetIdByKey(key);
??????? if(nodeId == m_InvalidId) return false;

??????? value = (m_EntryAddr + nodeId)->m_Value;

??????? return true;
??? }

??? bool Exist(K &key)
??? {
??????? AutoLock autoLock(m_MutexLock);

??????? uint32_t nodeId = GetIdByKey(key);
??????? if(nodeId == m_InvalidId) return false;

??????? return true;
??? }

??? uint32_t Count()
??? {
??????? AutoLock autoLock(m_MutexLock);
??????? return m_HeadAddr->m_UsedCount;
??? }

??? //if exist set else add
??? bool Replace(K &key,V &value)
??? {
??????? AutoLock autoLock(m_MutexLock);

??????? if(Exist(key)) return Set(key,value);
??????? else return Add(key,value);
??? }

??? /***********************************************
??? ****LRU: when visit a node,move it to head ****
??? ************************************************/
??? //if no empty place,recycle tail
??? bool LruAdd(K &key,V &value,K &recyKey,V &recyValue,bool &recycled)
??? {
??????? AutoLock autoLock(m_MutexLock);

??????? if(Exist(key)) return false;

??????? if(Add(key,value)) return true;

??????? uint32_t index = key.HashCode() % m_HeadAddr->m_TableLen;
??????? uint32_t tailId = GetTailNodeId(index);

??????? if(tailId == m_InvalidId) return false;

??????? Entry *tmpNode = m_EntryAddr + tailId;
??????? recyKey?? = tmpNode->m_Key;
??????? recyValue = tmpNode->m_Value;
??????? recycled? = true;

??????? RecycleNode(index,tailId);

??????? return Add(key,value);
??? }

??? bool LruSet(K &key,V &value)
??? {
??????? AutoLock autoLock(m_MutexLock);

??????? if(Set(key,value)) return MoveToHead(key);
??????? else return false;
??? }

??? bool LruGet(K &key,V &value)
??? {
??????? AutoLock autoLock(m_MutexLock);

??????? if(Get(key,value)) return MoveToHead(key);
??????? else return false;
??? }

??? //if exist set else add; if add failed recycle tail than add
??? bool LruReplace(K &key,bool &recycled)
??? {
??????? AutoLock autoLock(m_MutexLock);

??????? recycled = false;

??????? if(Exist(key)) return LruSet(key,value);
??????? else return LruAdd(key,value,recyKey,recyValue,recycled);
??? }

??? void Clear()
??? {
??????? AutoLock autoLock(m_MutexLock);

??????? m_HeadAddr->m_FreeBase = 0;
??????? m_HeadAddr->m_RecycleHead = 0;
??????? m_HeadAddr->m_UsedCount = 0;
??????? for(uint32_t i = 0; i < m_HeadAddr->m_TableLen; ++i)
??????? {
??????????? (m_ArrayAddr+i)->m_Head = m_InvalidId;
??????????? (m_ArrayAddr+i)->m_Tail = m_InvalidId;
??????? }
??? }

??? int GetRowKeys(vector<K> &keys,uint32_t index)
??? {
??????? AutoLock autoLock(m_MutexLock);

??????? if(index >= m_HeadAddr->m_TableLen) return -1;

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

??????? int count = 0;
??????? Array *tmpArray = m_ArrayAddr + index;
??????? uint32_t nodeId = tmpArray->m_Head;
??????? while(nodeId != m_InvalidId)
??????? {
??????????? Entry *tmpNode = m_EntryAddr + nodeId;
??????????? keys.push_back(tmpNode->m_Key);
??????????? nodeId = tmpNode->m_Next;
??????????? ++count;
??????? }

??????? return count;
??? }

??? void *Padding(uint32_t size)
??? {
??????? AutoLock autoLock(m_MutexLock);

??????? if(size > m_HeadSize - sizeof(TableHead)) return NULL;
??????? else return m_HeadAddr->m_Padding;
??? }

private:
??? static const uint32_t m_InvalidId = 0xffffffff;
??? static const uint32_t m_HeadSize = 1024;
??? struct TableHead
??? {
??????? uint32_t m_TableLen;
??????? uint32_t m_NodeTotal;
??????? uint32_t m_FreeBase;
??????? uint32_t m_RecycleHead;
??????? uint32_t m_UsedCount;
??????? char???? m_TableName[256];
??????? uint32_t m_Padding[0];
??? };

??? struct Array
??? {
??????? uint32_t m_Head;
??????? uint32_t m_Tail;
??? };

??? struct Entry
??? {
??????? 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;
??? Array???? *m_ArrayAddr;
??? Entry???? *m_EntryAddr;

??? ThreadMutex m_MutexLock;

??? bool MoveToHead(K &key);
??? uint32_t GetIdByKey(K &key);
??? void AddNodeToHead(uint32_t index,uint32_t nodeId);
??? bool MoveNodeToHead(uint32_t index,uint32_t nodeId);
??? bool RecycleNode(uint32_t index,uint32_t nodeId);
??? uint32_t GetTailNodeId(uint32_t index);
??? uint32_t GetFreeNode();

??? DISABLE_COPY_AND_ASSIGN(HashTable);
};

template<typename K,typename V>
HashTable<K,V>::HashTable(const char *tablename,uint32_t nodeTotal)
{
??? AbortAssert(tablename != NULL);

??? m_MemSize = m_HeadSize + tableLen*sizeof(Array) + nodeTotal*sizeof(Entry);
??? m_MemAddr = (uint8_t*)MemFile::Realloc(tablename,m_MemSize);
??? AbortAssert(m_MemAddr != NULL);

??? m_HeadAddr = (TableHead*)(m_MemAddr);
??? m_ArrayAddr = (Array*)(m_MemAddr + m_HeadSize);
??? m_EntryAddr = (Entry*)(m_MemAddr + m_HeadSize + tableLen*sizeof(Array));

??? m_HeadAddr->m_TableLen = tableLen;
??? m_HeadAddr->m_NodeTotal = nodeTotal;
??? strncpy(m_HeadAddr->m_TableName,tablename,sizeof(m_HeadAddr->m_TableName));

??? if(m_HeadAddr->m_UsedCount == 0)//if first use init array to invalid id
??? {
??????? for(uint32_t i = 0; i < tableLen; ++i)
??????? {
??????????? (m_ArrayAddr+i)->m_Head = m_InvalidId;
??????????? (m_ArrayAddr+i)->m_Tail = m_InvalidId;
??????? }

??????? m_HeadAddr->m_FreeBase = 0;
??????? m_HeadAddr->m_RecycleHead = 0;
??? }
}

template<typename K,V>::~HashTable()
{
??? MemFile::Release(m_MemAddr,m_MemSize);
}

template<typename K,typename V>
bool HashTable<K,V>::MoveToHead(K &key)
{
??? uint32_t nodeId = GetIdByKey(key);
??? uint32_t index = key.HashCode() % m_HeadAddr->m_TableLen;

??? return MoveNodeToHead(index,nodeId);
}

template<typename K,typename V>
uint32_t HashTable<K,V>::GetIdByKey(K &key)
{
??? uint32_t hashCode = key.HashCode();
??? uint32_t index = hashCode % m_HeadAddr->m_TableLen;
??? Array *tmpArray = m_ArrayAddr + index;

??? uint32_t nodeId = tmpArray->m_Head;
??? while(nodeId != m_InvalidId)
??? {
??????? Entry *tmpNode = m_EntryAddr + nodeId;
??????? if(tmpNode->m_Code == hashCode && key.Equals(tmpNode->m_Key)) break;

??????? nodeId = tmpNode->m_Next;
??? }

??? return nodeId;
}

template<typename K,typename V>
void HashTable<K,V>::AddNodeToHead(uint32_t index,uint32_t nodeId)
{
??? if(index >= m_HeadAddr->m_TableLen || nodeId >= m_HeadAddr->m_NodeTotal) return;

??? Array *tmpArray = m_ArrayAddr + index;
??? Entry *tmpNode = m_EntryAddr + nodeId;
??? if(m_InvalidId == tmpArray->m_Head)
??? {
??????? tmpArray->m_Head = nodeId;
??????? tmpArray->m_Tail = nodeId;
??? }
??? else
??? {
??????? tmpNode->m_Next = tmpArray->m_Head;
??????? (m_EntryAddr + tmpArray->m_Head)->m_Prev = nodeId;
??????? tmpArray->m_Head = nodeId;
??? }
}

template<typename K,V>::MoveNodeToHead(uint32_t index,uint32_t nodeId)
{
??? if(index >= m_HeadAddr->m_TableLen || nodeId >= m_HeadAddr->m_NodeTotal) return false;

??? Array *tmpArray = m_ArrayAddr + index;
??? Entry *tmpNode = m_EntryAddr + nodeId;

??? //already head
??? if(tmpArray->m_Head == nodeId)
??? {
??????? return true;
??? }

??? uint32_t nodePrev = tmpNode->m_Prev;
??? uint32_t nodeNext = tmpNode->m_Next;
??? (m_EntryAddr+nodePrev)->m_Next = nodeNext;
??? if(nodeNext != m_InvalidId)
??? {
??????? (m_EntryAddr+nodeNext)->m_Prev = nodePrev;
??? }
??? else
??? {
??????? 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;

??? return true;
}

template<typename K,V>::RecycleNode(uint32_t index,uint32_t nodeId)
{
??? if(index >= m_HeadAddr->m_TableLen || nodeId >= m_HeadAddr->m_NodeTotal) return false;

??? Array *tmpArray = m_ArrayAddr + index;
??? Entry *tmpNode = m_EntryAddr + nodeId;

??? uint32_t nodePrev = tmpNode->m_Prev;
??? uint32_t nodeNext = tmpNode->m_Next;

??? if(nodePrev != m_InvalidId)
??? {
??????? (m_EntryAddr + nodePrev)->m_Next = nodeNext;
??? }
??? else
??? {
??????? tmpArray->m_Head = nodeNext;
??? }

??? if(nodeNext != m_InvalidId)
??? {
??????? (m_EntryAddr + nodeNext)->m_Prev = nodePrev;
??? }
??? else
??? {
??????? tmpArray->m_Tail = nodePrev;
??? }

??? (m_EntryAddr+nodeId)->m_Next = m_HeadAddr->m_RecycleHead;
??? m_HeadAddr->m_RecycleHead = nodeId;
??? --(m_HeadAddr->m_UsedCount);

??? return true;
}

template<typename K,V>::GetTailNodeId(uint32_t index)
{
??? if(index >= m_HeadAddr->m_TableLen) return m_InvalidId;

??? Array *tmpArray = m_ArrayAddr + index;

??? return tmpArray->m_Tail;
}

template<typename K,V>::GetFreeNode()
{
??? uint32_t nodeId = m_InvalidId;
??? if(m_HeadAddr->m_UsedCount < m_HeadAddr->m_FreeBase)//get from recycle list
??? {
??????? nodeId = m_HeadAddr->m_RecycleHead;
??????? m_HeadAddr->m_RecycleHead = (m_EntryAddr+nodeId)->m_Next;
??????? ++(m_HeadAddr->m_UsedCount);
??? }
??? else if(m_HeadAddr->m_UsedCount < m_HeadAddr->m_NodeTotal)//get from free mem
??? {
??????? nodeId = m_HeadAddr->m_FreeBase;
??????? ++(m_HeadAddr->m_FreeBase);
??????? ++(m_HeadAddr->m_UsedCount);
??? }
??? else
??? {
??????? nodeId = m_InvalidId;
??? }

??? //init node
??? if(nodeId < m_HeadAddr->m_NodeTotal)
??? {
??????? Entry *tmpNode = m_EntryAddr + nodeId;
??????? memset(tmpNode,sizeof(Entry));

??????? tmpNode->m_Next = m_InvalidId;
??????? tmpNode->m_Prev = m_InvalidId;
??? }

??? return nodeId;
}
?

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读