DCache 分布式存储系统|List 缓存模块的创建与使用[通俗易懂]

DCache 分布式存储系统|List 缓存模块的创建与使用[通俗易懂]作者|Eaton导语|在之前的系列文章中,我们介绍了DCache及其KV和K-K-Row缓存模块的使用,本文将继续介绍如何使用DCache中的列表类型缓存模块——List缓存模块。系列文章DCache分布式存储系统|安装部署与应用创建DCache分布式存储系统|Key-Value缓存模块的创建与使用DCache分布式存储系统|K-K-Row缓存模块的创建与使用DCache分布式存储系统|List缓存模块的创建与使用目录List模块简介创建.

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

DCache 分布式存储系统|List 缓存模块的创建与使用[通俗易懂]

作者 | Eaton

导语 | 在之前的系列文章中,我们介绍了 DCache 及其 KV 和 K-K-Row 缓存模块的使用,本文将继续介绍如何使用 DCache 中的列表类型缓存模块 —— 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.tarsDCache/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/building-microservice-platforms-with-tars

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

或扫码获取:

QR

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/179123.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • getmethods和getdeclaredmethods_java中的method

    getmethods和getdeclaredmethods_java中的methodMethodgetDeclaredMethod(Stringname,Class…parameterTypes)d返回一个Method对象,该对象反映此Class对象所表示的类或接口的指定已声明方法。Method[]getDeclaredMethods()返回Method对象的一个数组,这些对象反映此Class对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访…

  • scrapy安装教程_玻璃幕墙安装介绍

    scrapy安装教程_玻璃幕墙安装介绍在写之前我们先来了解一下什么是Scrapy?Scrapy是用纯Python实现一个为了爬取网站数据、提取结构性数据而编写的应用框架,用途非常广泛框架的力量,用户只需要定制开发几个模块就可以轻松的实现一个爬虫,用来抓取网页内容以及各种图片,非常之方便Scrapy使用了Twisted[‘twɪstɪd](其主要对手是Tornado)异步网络框架来处理网络通讯,可以加快我们的下载速度,不…

  • 第三章 数据库

    第三章 数据库

  • 【全网首发】言简意赅的Python全套语法,内附详细知识点和思维导图!【强烈建议收藏!】

    【全网首发】言简意赅的Python全套语法,内附详细知识点和思维导图!【强烈建议收藏!】Python是近几年比较火热的编程语言,至于有多火热?偶尔打开微信公众号,页面下面弹出的是《Python训练营》,打开朋友圈发现有推荐学习Python的课程,打开CSDN,发现热榜第一又是Python推荐文章,不得不说Python的影响力在目前还是比较大的,这和Python社区的宣传力度有着密切的关系!目前学习Python的人有多少呢?那些人在学习Python呢?至于这个问题,我认为没有一个准确的答案,因为每一天学习Python的人都在增加,学习Python被越来越多的人注重,所以要回答这个问题,最好的

  • pycharm中debug的使用[通俗易懂]

    pycharm中debug的使用[通俗易懂]1.未打断点运程序,输出全部结果2.打断点后,点击debug,代码执行到断点前停止(断点所在行不执行)3.stepover,是在单步执行时,在函数内遇到子函数时不会进入子函数内单步执行,而是将子函数整个执行完再停止,也就是把子函数整个作为一步4.stepinto,是单步执行,遇到子函数就进入并且继续单步执行5.stepout,当单步执行到子函数内时,用StepOut就可以执行完子函数余下部分,并返回到上一层函数如点击下图中stepout,会直接跳转到test(

  • 基于arduino的光控窗帘_基于Arduino系统的智能窗帘设计与实现.doc

    基于arduino的光控窗帘_基于Arduino系统的智能窗帘设计与实现.doc摘要:跟随社会发展的潮流,现代科学技术正处于快速发展阶段,人们对智能家居的关注度也越来越高,人们开始寻求更加智能和舒适的生活及办公环境。智能遥控属于电子与信息工程的一个重要分支,在现代智能家居中有着良好的发展前景。本设计采用Arduino单片机来控制智能窗帘系统,实时监测室内温湿度情况并在LCD上显示,使用了红外遥控的技术,可以切换不同的工作模式从而来切换其控制方式,实现半自动控制、自动控制以及远…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号