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

作者 | Eaton
导语 | 随着微服务与云的发展,分布式架构的需求变得越来越普遍,传统的 SQL 结构化存储方案已经跟不上脚步,于是 NoSQL 出现了。DCache 作为基于 TARS 的分布式 NoSQL 缓存系统,完美支持 TARS 服务。在中,我们介绍了 DCache 的特性、如何在 TARS 上部署 DCache 并创建一个应用 。本文将继续介绍如何创建和使用 DCache 中的 KV 缓存模块。
系列文章
- DCache 分布式存储系统|Key-Value 缓存模块的创建与使用
目录
- 简介
- 应用场景
- 创建 KV 缓存模块
- 获取 DCache 接口文件
- 创建缓存服务代理
- 调用缓存模块服务
- 总结
简介
DCache 是一个基于 TARS 框架开发的分布式 NoSQL 存储系统,支持多种数据结构,包括了 (键值对),(多键值),(列表),(集合),(有序集合)等,满足多种业务需求。
其中 是最简单也是最常用的类型,我们只需完成以下步骤即可在服务中使用 缓存服务
DCache 中为 KV 提供了插入、替换、删除和批量操作键值等丰富的操作接口,使用上非常方便。本文将基于 介绍如何创建 Key-Value 缓存模块,以及怎么在 TARS 服务中调用该服务来缓存数据。
应用场景
DCache 的 KV 缓存模块为常规 缓存应用,一个键 key 对应一个值 value。value 一般为字符串类型。适用于结构简单的数据,常用于常规计数,如微博数, 粉丝数等,如下图。

对于一些复杂的结构化数据,比如需要为一个 key 存储多个值,通常有两种实现方式。一种是通过序列化存储实现,将多个字段存储在 中,需要处理多个字段并发读写的问题。另一种是通过将 和字段作为 key 的方式存储多个键值对实现,比如 存储 Jane 的年龄, 存储 Jane 的邮箱,这样 key 中会有大量重复用户 ID。如下图

因此一般会使用其它缓存类型来存储结构化数据,比如 DCache 中的 。该类型我们将在下一篇文章详细介绍。
创建 KV 缓存模块
与 TARS 中相似,一个 DCache 应用中能够创建多个缓存模块服务。每个缓存模块支持一种缓存数据结构,通过在一个应用中创建多个不同数据结构的缓存模块,能够实现多种数据类型的存储,满足多种需求。本文将介绍如何创建 KV 模块,其他数据类型相关内容将在之后的文章中分享。
首先,在 DCache 页面进入 ,选择我们之前创建的应用 ,模块名要求以应用名开头,这里我们因为创建的是 KV 模块,我们命名 ,如下

进入第二步的模块配置, 选择 ,填充备注

第三步服务配置,选好服务 IP 节点,并选择一个 MySQL 实例,在前一篇文章中我们已经添加过一个 MySQL 实例。如果需要使用新的 MySQL 服务,选中下方的 输入实例信息即可。如下,点击

弹出字段配置窗口,保持默认即可,点击

确认好已配置信息后,点击 即可完成发布。
到这里,我们就可以在其它服务中使用该缓存模块来缓存 Key-Value 数据了。
总体来说,创建缓存模块的过程分为三步:模块创建、模块配置和服务配置。模块配置时,大家按需选择缓存类型即可。
获取 DCache 接口文件
我们提到过,DCache 是基于 TARS 开发的,因此使用上和 TARS 服务一样,也是通过 接口文件来调用对应缓存服务的接口。不同的是,DCache 的接口文件是固定的,我们只需复制 下的 , 和 下的 到自己项目目录下即可。
例如本文 Demo 获取 DCache 接口文件后的项目文件结构如下
DCacheDemo
├── CacheShare.tars
├── ProxyShare.tars
├── Proxy.tars
├── config.conf
├── main.cpp
└── makefile
创建缓存服务代理
当我们创建了一个应用,它会自动创建一个路由服务和代理服务。比如我们之前创建的 ,就会自动创建一个路由服务 和一个代理服务 。 下每个缓存模块都是通过代理服务 来访问的。
因此,在 TARS 服务或客户端中,我们只需要创建一个该代理服务的代理对象即可调用 下的缓存模块。
例如,我们在 中通过如下代码创建 的代理对象
// main.cpp
#include
#include
调用 KV 缓存模块服务
通过 代理服务的代理对象,我们就能够调用 中缓存模块的接口了。本部分将通过简单示例,介绍 类型缓存模块部分接口的使用。关于其它接口的信息,参见 。
接口调用流程与 TARS 服务接口调用流程一致。如果你还不清楚 TARS 服务的调用方式和流程,可以阅读文章 。
那么接下来,我们来看看怎么使用 KV 缓存模块。
Key-Value 模块
即键值对模块,这里我们介绍写接口 和读接口 ,其它操作接口的使用类似。
设置键值对
接口 能够设置键值对,定义如下
int setKV(const SetKVReq &req)
其中结构 及其嵌套结构 的定义如下
struct SetKVReq
{
1 require string moduleName; // 模块名
2 require SSetKeyValue data;
};
struct SSetKeyValue
{
1 require string keyItem; // 键
2 require string value; // 值
3 require byte version = 0; // 数据版本,缺省为0
4 require bool dirty = true; // 是否设置为脏数据,缺省为true
5 require int expireTimeSecond = 0; // 过期时间,缺省为0,表示永不过期
};
指缓存模块名,通过它来找到具体调用的模块,键值对信息则存储在 中。使用时先构造键值对数据,然后构造请求结构体,最后发起调用,如下
void testSetKV(const string &key, const string &value, DCache::ProxyPrx prx)
{
// 构造键值对
DCache::SSetKeyValue setReq;
setReq.keyItem = key;
setReq.value = value;
// 构造请求
DCache::SetKVReq setRsp;
setRsp.moduleName = ModuleTestDemoKV;
setRsp.data = setReq;
prx->setKV(setRsp);
}
获取键值
接口 能够读取键值,定义如下
int getKV(const GetKVReq &req, GetKVRsp &rsp)
其中请求消息结构 和返回消息结构 的定义如下
struct GetKVReq
{
1 require string moduleName; // 模块名
2 require string keyItem; // 键
3 require string idcSpecified = ""; // idc区域
};
struct GetKVRsp
{
1 require string value; // 值
2 require byte ver; // 数据版本号
3 require int expireTime = 0; // 过期时间
};
使用示例如下
void testGetKV(const string &key, DCache::ProxyPrx prx)
{
// 构建请求
DCache::GetKVReq getReq;
getReq.moduleName = ModuleTestDemoKV;
getReq.keyItem = key;
// 返回数据结构体
DCache::GetKVRsp getRsp;
prx->getKV(getReq, getRsp);
cout << getRsp.value << endl;
}
运行示例
我们来实际运行一下上面的使用示例。完整的使用示例可以在 GitHub 仓库 中获取。
我们通过 测试上节提到的各模块读写接口,如下
void testKV(DCache::ProxyPrx prx)
{
testSetKV("hello", "world", prx);
testGetKV("hello", prx);
}
接着,在 函数中执行
int main(int argc, char *argv[])
{
...
auto prx = comm->stringToProxy(DCacheTestDemoObj);
// 调用 DCache 缓存服务
testKV(prx);
...
}
编译构建并运行示例,结果如下

通过上述 DCache 缓存模块的具体使用流程,我们成功调用了 DCache 的 KV 缓存服务。
KV 缓存模块服务接口
除了设置键值接口 和读取键值接口 ,DCache 中还提供了丰富的 KV 操作接口,包括插入(), 删除(), 更新() 等,如下
// 根据 key 检测 value 是否存于 hash
int checkKey(CheckKeyReq req, out CheckKeyRsp rsp);
// 根据 key 查询 value
int getKV(GetKVReq req, out GetKVRsp rsp);
// 批量查询
int getKVBatch(GetKVBatchReq req, out GetKVBatchRsp rsp);
// 获取 cache 中所有的 key,不包含落地 DB 的 key
int getAllKeys(GetAllKeysReq req, out GetAllKeysRsp rsp);
// 单条写入
int setKV(SetKVReq req);
// 批量写入
int setKVBatch(SetKVBatchReq req, out SetKVBatchRsp rsp);
// key 不存在则插入一条记录,key 已存在则失败
int insertKV(SetKVReq req);
// 更新记录
int updateKV(UpdateKVReq req, out UpdateKVRsp rsp);
// 删除 key 对应的值,只删除 Cache 的数据,不删 DB 数据
int eraseKV(RemoveKVReq req);
// 批量 erase
int eraseKVBatch(RemoveKVBatchReq req, out RemoveKVBatchRsp rsp);
// 删除 key 对应的值,包括 DB 里的数据
int delKV(RemoveKVReq req);
// 批量删除
int delKVBatch(RemoveKVBatchReq req, out RemoveKVBatchRsp rsp);
接口的使用方式与前面介绍的 和 是类似的,关于接口的具体入参和出参结构可以参考 。
总结
本文基于,通过一系列使用示例,介绍了 DCache 中 KV 缓存模块的创建和使用方式。因为 DCache 基于 TARS 开发,缓存服务的使用上基本和 TARS 服务调用无异,开发者能够快速上手。同时 DCache 支持直接连接 DB 进行数据持久化,无需开发者自行实现 DB 连接持久化的相关逻辑,使开发者能够更加专注于业务。
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/
或扫码获取:
