Skip to content

Commit

Permalink
Merge pull request #25 from Tencent/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
shanbaoyin committed Aug 1, 2019
2 parents a2ab5df + 310f4be commit 3e47650
Show file tree
Hide file tree
Showing 12 changed files with 158 additions and 6 deletions.
23 changes: 23 additions & 0 deletions docs/benchmark.md
@@ -0,0 +1,23 @@
## 测试背景和目标
了解DCache两种数据类型的读写性能,以及对于机器的压力情况(包括CPU、IO、网络)。

## 测试环境
#### 软件环境
> 1. 基于Tars(2019年4月最新版本)
> 2. 单进程服务,Cache是纯内存类型(即后端不带DB)
#### 硬件环境
> 1. CPU 48核(Intel(R) Xeon(R) CPU E5-2670 v3 @2.30GHz),内存128G,万兆网卡
> 2. 测试客户端与服务端同机房
## 测试方法
有两个客户端并发访问DCache的接口(不经过Proxy,直接访问cache),其中每个客户端开启10个进程,每个进程开启20个线程,共有400个线程并发调用DCache的读写接口(先测写接口,再测读接口);DCache服务端开启6个网络线程和12个工作线程。在压测过程中记录机器的各项性能指标。

## 测试结果

数据类型 | 读/写 | 数据长度(Byte) | CPU | 网卡(Mbit/s) | TPS(w/s)
---|---|---|---|---|---
k-v | 读 | 100 | 1400% | 800 | 66
k-v | 写 | 100 | 800% | 450 | 18.5
k-k-row | 读 | 100 | 1600% | 900 | 45
k-k-row | 写 | 100 | 950% | 430 | 16
95 changes: 95 additions & 0 deletions docs/dbaccess.md
@@ -0,0 +1,95 @@
dbaccess是Cache访问持久化服务的代理服务,持久化服务可以是MySQL、SQL Server, PostgreSQL等数据库,针对不同的持久化存储,开发者需要开发不同的dbaccess服务。本篇文档的目标读者是需要实现内存数据持久化存储的相关人员。

Cache通过以下两种方式实现数据持久化:
> 1. 定期将脏数据写入db中
> 2. 在内存不足时,根据lru算法将最‘冷’数据写入到db中
下面以使用MySQL作为持久化存储为例,展示如何开发、部署DbAccess,以及配置DCache开启持久化功能。

> * [提供MySQL DB实例和数据表](#1)
> * [开发一个基于tars的dbaccess服务](#2)
> * [相关配置](#3)
> * [部署dbaccess服务](#4)
## <a id = "1"></a> 1. 提供MySQL DB实例和数据表

**step1: 提供MySQL DB实例**

如果没有,请参考官方文档安装。

**step2:建表**

一个模块对应一张表。

假设你有一个key-value模块,其中key是身份ID,value是地址信息,那么建表时就要创建3个字段:person_ID,person_Address,sDCacheExpireTime,其中字段“sDCacheExpireTime”是DCache要求增加的一个额外字段,表示过期时间。


假设你有一个k-k-row模块,其中主key是身份ID,联合key是课程ID,value是成绩,那么建表时就要指定4个字段:person_ID,course_ID,score,sDCacheExpireTime,其中字段“sDCacheExpireTime”是DCache要求增加的一个额外字段,表示过期时间。


## <a id = "2"></a> 2. 开发一个基于tars的dbaccess服务

dbaccess服务是DCache访问MySQL的代理,在dbaccess服务中通过访问MySQL从而实现数据的持久化。要求阅读本节的读者已经掌握开发一个tars服务的基本流程。

在DCache的源码中已经提供了一个简洁版的[dbaccess服务](https://github.com/Tencent/DCache/tree/master/src/DbAccess/example),读者可参考并完善(接口声明文件[DbAccess.tars](https://github.com/Tencent/DCache/blob/master/src/DbAccess/example/DbAccess.tars)请勿修改,DbAccess服务必须实现该文件中的接口),然后编译生成发布包。




## <a id = "3"></a> 3. 相关配置

发布dbaccess服务前,需要作一些相应的配置,修改配置后需重启服务才能生效。

#### 3.1. 配置dbaccess服务
dbaccess服务的配置可参考库中的[DbAccess.conf文件](https://github.com/Tencent/DCache/blob/master/src/DbAccess/example/DbAccess.conf),主要包括MySQL实例的用户名,密码和端口等信息。

#### 3.2. 配置Cache服务

配置Cache服务分两种场景:**新建模块**接入dbaccess和**已有模块**接入dbaccess。

##### 3.2.1 新模块接入dbaccess服务
在新建模块时,应用场景选择“cache + 持久化”,并填写相应的Obj信息,如下图所示:

![新模块接入dbaccess](images/newModuleWithDbaccess.png)

ObjName可以通过点击“管理Servant”获取,如下图所示:

![获取Obj信息](images/getDbaccessObj.png)


##### 3.2.2 已有模块接入dbaccess服务

修改Cache模块的Main/DbAccess 配置项:

```
1. DBFlag = Y,
2. ReadDbFlag = Y,
3. ObjName = 已部署的DbAccess服务的obj信息,例如StoreData.dbaccess.DbAccessObj
```


##### 3.2.3 其他配置项
以下几个配置(包括但不限于)和数据持久化相关

```
1. Main/Cache<EnableErase> = Y/N // 当容量达到阈值时,是否允许自动淘汰旧的数据
2. Main/Cache<EraseInterval> = 5 // 每次淘汰数据的时间间隔(秒)
3. Main/Cache<SyncThreadNum> = 1 // 回写脏数据的线程数,线程越大,回写越快,DB压力越大
4. Main/Cache<SyncTime> = 300 // 回写时间(秒),即回写多久以前的数据,时间越大,保留脏数据越多
5. Main/Cache<SyncInterval> = 100 // 回写操作的时间间隔(秒),即频率
```



## <a id = "4"></a> 4. 部署dbaccess服务
生成dbaccess服务的发布包和做好相关配置后,就可以在tars管理平台部署该服务了。

**step1:** 服务部署

![部署dbaccess服务](images/deployDbaccess.png)

**step2:** 发布服务

![发布dbaccess服务](images/releaseDbaccess.png)

上传在[开发一个基于tars的dbaccess服务](#2)生成的发布包。
Binary file added docs/images/deployDbaccess.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/getDbaccessObj.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/newModuleWithDbaccess.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/releaseDbaccess.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions src/KVCacheServer/BackUp.tars
Expand Up @@ -17,8 +17,8 @@ interface BackUp
{
/*
* dump内存数据到指定路径文件
* dumpPath: 存放镜像文件的绝对路径,如果为空则dump到默认路径
* mirrorName: 镜像名
* dumpPath: 存放镜像文件的绝对路径,如果为空则dump到默认路径:/data/dcache/dump_binlog/
* mirrorName: 镜像文件名, 如果为空则使用组名和当前时间生成文件名,例如:TestModuleKVGroup1_dump_binlog_20190701120101.log.gz
*/
int dump(string dumpPath, string mirrorName, out string errmsg);

Expand Down
1 change: 1 addition & 0 deletions src/KVCacheServer/BackUpImp.cpp
Expand Up @@ -34,6 +34,7 @@ tars::Int32 BackUpImp::dump(const std::string &dumpPath, const std::string &mirr
return 0;
}
g_app.dumpThread()->start();
return 0;
}
catch (const TarsException & ex)
{
Expand Down
17 changes: 17 additions & 0 deletions src/KVCacheServer/DumpThread.cpp
Expand Up @@ -40,6 +40,23 @@ int DumpThread::init(const string &dumpPath, const string &mirrorName, const str
_dumpPath = "/data/dcache/dump_binlog/"; //使用默认dump路径
FDLOG(_dumpDayLog) << "[DumpThread::init] dumpPath:" << dumpPath << " is not absolute path, use default path: /data/dcache/dump_binlog/" << endl;
}
else
{
_dumpPath = dumpPath;
}

if (mirrorName.empty())
{
// using default mirror name
_mirrorName = g_app.gstat()->groupName() + string("_dump_binlog_") + TC_Common::now2str() + string(".log.gz");
FDLOG(_dumpDayLog) << "[DumpThread::init] mirrorName is empty, use default mirror name: groupname_dump_binlog_nowtime.log.gz" << endl;
}
else
{
_mirrorName = mirrorName;
}

FDLOG(_dumpDayLog) << "[DumpThread::init] finish" << endl;

return 0;
}
Expand Down
18 changes: 16 additions & 2 deletions src/MKVCacheServer/DumpThread.cpp
Expand Up @@ -34,14 +34,28 @@ int DumpThread::init(const string &dumpPath, const string &mirrorName, const str
_config = sConf;
_tcConf.parseFile(_config);

_dumpDayLog = _tcConf.get("/Main/<BackupDayLog>", "dumpAndRecover");

if (!TC_File::isAbsolute(dumpPath))
{
_dumpPath = "/data/dcache/dump_binlog/"; //使用默认dump路径
FDLOG(_dumpDayLog) << "[DumpThread::init] dumpPath:" << dumpPath << " is not absolute path, use default path: /data/dcache/dump_binlog/" << endl;
}
else
{
_dumpPath = dumpPath;
}

_dumpPath = dumpPath;
_mirrorName = mirrorName;
if (mirrorName.empty())
{
// using default mirror name
_mirrorName = g_app.gstat()->groupName() + string("_dump_binlog_") + TC_Common::now2str() + string(".log.gz");
FDLOG(_dumpDayLog) << "[DumpThread::init] mirrorName is empty, use default mirror name: groupname_dump_binlog_nowtime.log.gz" << endl;
}
else
{
_mirrorName = mirrorName;
}

FDLOG(_dumpDayLog) << "[DumpThread::init] finish" << endl;

Expand Down
4 changes: 2 additions & 2 deletions src/MKVCacheServer/MKBackUp.tars
Expand Up @@ -17,8 +17,8 @@ interface MKBackUp
{
/*
* dump内存数据到指定路径文件
* dumpPath: 存放镜像文件的绝对路径,如果为空则dump到默认路径
* mirrorName: 镜像名
* dumpPath: 存放镜像文件的绝对路径,如果为空则dump到默认路径:/data/dcache/dump_binlog/
* mirrorName: 镜像文件名, 如果为空则使用组名和当前时间生成文件名,例如:TestModuleMKVGroup1_dump_binlog_20190701120101.log.gz
*/
int dump(string dumpPath, string mirrorName, out string errmsg);

Expand Down
2 changes: 2 additions & 0 deletions test/Proxy/RouterTableTest.cpp
Expand Up @@ -216,6 +216,8 @@ string getRandString()
"0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz";

srand(time(0));

string randString = "";
size_t randLen = rand() % 100;
Expand Down

0 comments on commit 3e47650

Please sign in to comment.