您现在的位置是:首页 > 文章详情

DCache 分布式存储系统|List 缓存模块的创建与使用

日期:2021-03-11点击:507

在之前的DCache系列文章中,我们介绍了 DCache 及其 KV 和 K-K-Row 缓存模块的使用,本文将继续介绍如何使用 DCache 中的列表类型缓存模块 —— List 缓存模块。

系列文章:
DCache 分布式存储系统|安装部署与应用创建
DCache 分布式存储系统|Key-Value 缓存模块的创建与使用
DCache 分布式存储系统|K-K-Row 缓存模块的创建与使用




  • List 模块简介
  • 创建 List 缓存模块
  • 获取 DCache 接口文件
  • 创建缓存服务代理
  • 调用 List 缓存模块服务
    • List 模块读写操作
    • 实例
  • 其它 List 缓存模块服务接口
  • 总结

DCache 是一个基于 TARS 框架开发的分布式 NoSQL 存储系统,支持多种数据结构,包括了 key-value(键值对),k-k-row(多键值),list(列表),set(集合),zset(有序集合)等,满足多种业务需求。

list 即链表,常用于消息的排列,比如 QQ、微信的聊天消息排序。常用的有单向链表和双向链表,由若干链表节点组成,如下图。

单向链表,每个节点存储该节点的数据和下一个节点的地址;双向链表的每个节点则额外包含上一个节点的地址。
DCache 中的 List 模块是基于双向链表实现的,每一个内存数据单元 Block 包含两个指针,分别指向前一个 Block 和后一个 Block。DCache 还提供了操作 list 中某一段的 API,你可以直接查询、删除、替换和裁剪 list 中某一段的元素。如下图为双向链表的结构及替换操作的原理。

同样地,与其它模块相似,我们完成以下步骤即可在服务中使用 list 缓存服务
  1. 创建 List 缓存模块
  2. 获取 DCache 接口文件
  3. 创建缓存服务代理
  4. 调用 List 缓存模块服务
本文将继续基于 TestDemo 介绍如何创建 List 缓存模块,以及怎么在 TARS 服务中调用该服务来缓存数据。
本文使用的示例可以在 GitHub 仓库 DCacheDemo(文末附链接)  中查看。

前面的文章我们已经介绍过缓存模块的创建,各类型缓存模块创建流程是相似的,这部分不再赘述过程类似,这里命名为 TestDemoList cache 类型 选择 List(MKVCache)

我们提到过,DCache 是基于 TARS 开发的,因此使用上和 TARS 服务一样,也是通过 .tars 接口文件来调用对应缓存服务的接口。不同的是,DCache 的接口文件是固定的,我们只需复制 DCache/src/TarsComm 下的 CacheShare.tars, ProxyShare.tarsDCache/src/Proxy 下的 Proxy.tars到自己项目目录下即可。(文末附链接

例如本文 Demo 获取 DCache 接口文件后的项目文件结构如下

DCacheDemo├── CacheShare.tars├── ProxyShare.tars├── Proxy.tars├── config.conf├── main.cpp└── makefile

前面的文章中我们提到过,创建一个应用后会自动创建一个路由服务和代理服务,并通过 TestDemo 介绍了如何创建缓存服务代理来调用服务。
我们继续使用 TestDemo ,新增一个模块名 ModuleTestDemoList ,值为我们前面创建的模块名 TestDemoList ,用于之后通过代理调用该模块,如下

通过 TestDemo 代理服务的代理对象和模块名 TestDemoList ,我们就能够调用前面创建的 List 缓存模块的接口了。本部分将通过简单示例,介绍 list 类型缓存模块部分接口的使用。关于其它接口的信息,参见 Proxy 接口指南(文末附链接)。
接口调用流程与 TARS 服务接口调用流程一致。如果你还不清楚 TARS 服务的调用方式和流程,可以阅读文章 TARS RPC 通信框架|提供多种远程调用方式 了解 TARS 服务的调用方式。
后面的示例中,会使用到三个工具函数,定义如下

那么接下来,我们来看看怎么使用 DCache 的 List 缓存模块。


List模块读写操作

List 模块即列表缓存模块。这里介绍写接口 pushList 和读接口 getList,其它接口用法类似。

向列表插入数据

接口 pushList 用于向列表头部或者末尾插入数据,定义如下

int pushList(const PushListReq &req)

其中结构 PushList 定义如下

struct PushListReq{    1 require string moduleName; // 模块名    2 require string mainKey; // 主key    3 require vector<InsertKeyValue> data; // 待插入数据    4 require bool atHead = true; // true 表示插入到 list 头部,false 表示插入尾部};

使用示例如下

void testPushList(const string &mainKey, const vector<map<string, string>> &data, DCache::ProxyPrx prx){    // 构造请求    DCache::PushListReq req; req.moduleName = ModuleTestDemoList; req.mainKey = mainKey; req.atHead = false;    
    for
(auto item : data)
{        DCache::InsertKeyValue insertValue; insertValue.mainKey = mainKey; insertValue.expireTimeSecond = 60* 60* 24;         map<string, string>::const_iterator it = item.begin();        while(it != item.end())        {            // 构建 UpdateValue insertValue.mpValue[it->first] = genUpdateValue(DCache::SET, it->second);            ++it;        } req.data.push_back(insertValue);    } prx->pushList(req);}

获取列表数据

接口 getList 用于根据指定的主 key 和索引查询列表的数据,定义如下

int getList(constGetListReq&req, GetListRsp&rsp)

其中请求消息结构 GetListReq 和返回消息结构 GetListRsp 及其嵌套结构 Entry 的定义如下

struct GetListReq{    1 require string moduleName; // 模块名    2 require string mainKey; // 主key    3 require string field; // 需要查询的字段集,多个字段用','分隔如 "a,b", "*"表示所有    4 require long index; //索引    5 require string idcSpecified = ""; //idc区域};struct GetListRsp{    1 require Entry entry; // 查询结果};    struct Entry{    1 require map<string, string> data;};

使用示例如下

void testGetList(const string &mainKey, constlong &index, DCache::ProxyPrx prx){// 构造请求    DCache::GetListReq req; req.moduleName = ModuleTestDemoList; req.mainKey = mainKey; req.field = "*"; req.index = index;    
    DCache
::GetListRsp rsp;
prx->getList(req, rsp);    
    // 打印返回值
printMapData(rsp.entry.data);}

实例

我们来实际运行一下上面的使用示例。完整的使用示例可以在 GitHub 仓库 DCacheDemo (文末附链接)中获取。

我们通过 testList 测试上节提到的两个 List 读写接口,我们向主键为 test 的列表中插入一个值 test,如下

void testList(DCache::ProxyPrx prx){ cout << START << " testList"<< endl;    
    string
mainKey = "test";
vector<map<string, string>> data; map<string, string> item; item["VALUE"] = "test"; data.push_back(item);     testPushList(mainKey, data, prx);    long index = 0; testGetList(mainKey, index, prx);
cout <<
END<< " testList"<< endl;
}

接着,在 main 函数中执行

int main(int argc, char*argv[]){        ...            auto prx = comm->stringToProxy<DCache::ProxyPrx>(DCacheTestDemoObj);            // 调用 DCache 缓存服务      testList(prx);        ...}

除了获取列表数据接口 getList 和读取键值接口 pushList,DCache 中还提供了丰富的 List 操作接口,包括批量插入(insertMKVBatch), 删除(delMKV), 更新(updateMKV) 等,如下

// 获取列表上指定的某一数据int getList(GetListReq req, out GetListRsp rsp);// 获取列表上指定范围的数据int getRangeList(GetRangeListReq req, out BatchEntry rsp);// 向列表头部或尾部插入数据int pushList(PushListReq req);// 弹出列表头部或尾部的数据int popList(PopListReq req, out PopListRsp rsp);// 替换列表中的数据int replaceList(ReplaceListReq req);// 裁剪列表,只保留指定区间,删除区间外的数据int trimList(TrimListReq req);// 从列表头部或者尾部删除一条或多条数据int remList(RemListReq req);

接口的使用方式与前面介绍的 getListpushList 是类似的,关于接口的具体入参和出参结构可以参考 Proxy 接口指南。



本文简要介绍了 DCache 中的 list 缓存模块的原理和使用流程,同时通过具体实例对部分接口的使用进行了详细介绍,帮助读者理解并能够快速上手使用 list 缓存模块。


文中链接:

DCacheDemo:

https://github.com/ETZhangSX/DCacheDemo


CacheShare.tars:

https://github.com/Tencent/DCache/blob/master/src/TarsComm/CacheShare.tars


ProxyShare.tars

https://github.com/Tencent/DCache/blob/master/src/TarsComm/ProxyShare.tars


Proxy.tars:

https://github.com/Tencent/DCache/blob/master/src/Proxy/Proxy.tars


Proxy 接口指南

https://github.com/Tencent/DCache/blob/master/docs/proxy_api_guide.md




TARS基金会是Linux基金会下的非营利性、微服务基金会,致力于建设一个强大而灵活的微服务生态系统。无论你在哪个行业,无论你使用什么技术栈,这里能助你快速实现你的创意。




点“在看”让TARS小姐姐变好看

本文分享自微信公众号 - TARS星球(TarsCloud)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

原文链接:https://my.oschina.net/u/4021301/blog/4982791
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章