关于nosql:DCache-分布式存储系统|List-缓存模块的创建与使用

3次阅读

共计 6379 个字符,预计需要花费 16 分钟才能阅读完成。

作者 | Eaton

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

系列文章

  • DCache 分布式存储系统|装置部署与利用创立
  • DCache 分布式存储系统|Key-Value 缓存模块的创立与应用
  • DCache 分布式存储系统|K-K-Row 缓存模块的创立与应用
  • DCache 分布式存储系统|List 缓存模块的创立与应用

目录

  • List 模块简介
  • 创立 List 缓存模块
  • 获取 DCache 接口文件
  • 创立缓存服务代理
  • 调用 List 缓存模块服务

    • List 模块读写操作
    • 实例
  • 其它 List 缓存模块服务接口
  • 总结

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

在后面的文章中,咱们介绍过 key-valuek-k-row 两种类型缓存模块的应用形式,本文将持续介绍 list 类型缓存模块的应用。

List 模块简介

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

单向链表,每个节点存储该节点的数据和下一个节点的地址;双向链表的每个节点则额定蕴含上一个节点的地址。

DCache 中的 List 模块是基于双向链表实现的,每一个内存数据单元 Block 蕴含两个指针,别离指向前一个 Block 和后一个 Block。DCache 还提供了操作 list 中某一段的 API,你能够间接查问、删除、替换和裁剪 list 中某一段的元素。如下图为双向链表的构造及替换操作的原理。

同样地,与其它模块类似,咱们实现以下步骤即可在服务中应用 list 缓存服务

  1. 创立 List 缓存模块
  2. 获取 DCache 接口文件
  3. 创立缓存服务代理
  4. 调用 List 缓存模块服务

本文将持续基于 TestDemo 介绍如何创立 List 缓存模块,以及怎么在 TARS 服务中调用该服务来缓存数据。

本文应用的示例能够在 GitHub 仓库 DCacheDemo 中查看。

创立 List 缓存模块

后面的文章咱们曾经介绍过缓存模块的创立,各类型缓存模块创立流程是类似的,这部分不再赘述
过程相似,这里命名为 TestDemoListcache 类型 抉择 List(MKVCache)

获取 DCache 接口文件

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

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

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

创立缓存服务代理

后面的文章中咱们提到过,创立一个利用后会主动创立一个路由服务和代理服务,并通过 TestDemo 介绍了如何创立缓存服务代理来调用服务。

咱们持续应用 TestDemo,新增一个模块名 ModuleTestDemoList,值为咱们后面创立的模块名 TestDemoList,用于之后通过代理调用该模块,如下。

// main.cpp
#include <iostream>
#include <map>
#include "servant/Communicator.h"
#include "servant/ServantProxy.h"
#include "Proxy.h"

using namespace std;
using namespace tars;

#define START "[\033[32mSTART\033[0m]"
#define END "[\033[31mEND\033[0m]"
#define SUBTEST_PREFIX "\t--"

// TestDemo 代理服务对象名
static string DCacheTestDemoObj = "DCache.TestDemoProxyServer.ProxyObj";

// 缓存模块名
static string ModuleTestDemoKV    = "TestDemoKV";
static string ModuleTestDemoKKRow = "TestDemoKKRow";
static string ModuleTestDemoList  = "TestDemoList";

int main(int argc, char *argv[])
{CommunicatorPtr comm = new Communicator();
    try
    {
        TC_Config conf;
        // 解析配置文件
        conf.parseFile("config.conf");
        // 加载配置
        comm->setProperty(conf);
        // 生成代理
        auto prx = comm->stringToProxy<DCache::ProxyPrx>(DCacheTestDemoObj);

        // TODO: 调用 DCache 缓存服务
    }
    catch (exception &e)
    {cerr << "error:" << e.what() << endl;
    }
    catch (...)
    {cerr << "Unknown Error" << endl;}
}

调用缓存模块服务

通过 TestDemo 代理服务的代理对象和模块名 TestDemoList,咱们就可能调用后面创立的 List 缓存模块的接口了。
本局部将通过简略示例,介绍 list 类型缓存模块局部接口的应用。对于其它接口的信息,参见 Proxy 接口指南。

接口调用流程与 TARS 服务接口调用流程统一。如果你还不分明 TARS 服务的调用形式和流程,能够阅读文章 TARS RPC 通信框架|提供多种近程调用形式 理解 TARS 服务的调用形式。

前面的示例中,会应用到三个工具函数,定义如下

// 构建 UpdateValue
DCache::UpdateValue genUpdateValue(DCache::Op op, const string &value)
{
    DCache::UpdateValue updateValue;
    updateValue.op = op;
    updateValue.value = value;
    return updateValue;
}

// 打印 map<string, string> 类型数据
void printMapData(const map<string, string> &data)
{map<string, string>::const_iterator it = data.begin();
    while (it != data.end())
    {
        cout << "|" << it->first << ":" << it->second;
        ++it;
    }
    cout << endl;
}

// 打印 vector<map> 数据
void printVectorMapData(const vector<map<string, string>> &data)
{for (auto item : data)
    {printMapData(item);
    }
}

那么接下来,咱们来看看怎么应用 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)
{
    cout << SUBTEST_PREFIX << "pushList" << endl;
    // 结构申请
    DCache::PushListReq req;
    req.moduleName = ModuleTestDemoList;
    req.mainKey = mainKey;

    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())
        {insertValue.mpValue[it->first] = genUpdateValue(DCache::SET, it->second);
            ++it;
        }
        req.data.push_back(insertValue);
    }

    int ret = prx->pushList(req);

    if (ret == DCache::ET_SUCC)
    {printVectorMapData(data);
        return;
    }
    cout << "ret:" << ret << endl;
}

获取列表数据

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

int getList(const GetListReq &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, const long &index, DCache::ProxyPrx prx)
{
    cout << SUBTEST_PREFIX << "getList";

    // 结构申请
    DCache::GetListReq req;
    req.moduleName = ModuleTestDemoList;
    req.mainKey = mainKey;
    req.field = "*";
    req.index = index;

    DCache::GetListRsp rsp;
    int ret = prx->getList(req, rsp);

    // 打印返回值
    if (ret == DCache::ET_SUCC)
    {printMapData(rsp.entry.data);
        return;
    }
    cout << "ret:" << ret << endl;
}

实例

咱们来理论运行一下下面的应用示例。残缺的应用示例能够在 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> item1, item2;
    item1["VALUE"] = "test";
    item2["VALUE"] = "hello";
    
    data.push_back(item1);
    data.push_back(item2);

    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 返回的列表头部数据值为 hello。默认状况下,pushList 是从列表头部插入数据的。

其它 List 缓存模块服务接口

除了获取列表数据接口 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 缓存模块。

TARS 能够在思考到易用性和高性能的同时疾速构建零碎并主动生成代码,帮忙开发人员和企业以微服务的形式疾速构建本人稳固牢靠的分布式应用,从而令开发人员只关注业务逻辑,进步经营效率。多语言、麻利研发、高可用和高效经营的个性使 TARS 成为企业级产品。

TARS 微服务助您数字化转型,欢送拜访:

TARS 官网:https://TarsCloud.org

TARS 源码:https://github.com/TarsCloud

Linux 基金会官网微服务收费课程:https://www.edx.org/course/bu…

获取《TARS 官网培训电子书》:https://wj.qq.com/s2/7849909/…

或扫码获取:

正文完
 0