0
点赞
收藏
分享

微信扫一扫

关于 FoundationDB 的使用 以及 性能压测


安装部署

安装包安装/卸载

这种方式方便快捷,只需要下载自己系统对应的包即可。
卸载的时候需要注意清理掉环境中的 旧版本的数据以及 配置文件:
​​​sudo rm -rf /var/lib/foundationdb /var/log/foundationdb /etc/foundationdb/fdb.cluster ​

Centos

wget https://github.com/apple/foundationdb/releases/download/7.1.0/foundationdb-server-7.1.0-1.el7.x86_64.rpm
wget https://github.com/apple/foundationdb/releases/download/7.1.0/foundationdb-clients-7.1.0-1.el7.x86_64.rpm

# Install
sudo rpm -Uvh foundationdb-clients-7.1.0-1.el7.x86_64.rpm foundationdb-server-7.1.0-1.el7.x86_64.rpm

# Uninstall
sudo rpm -e --nodeps foundationdb-clients foundationdb-server

Ubuntu

wget https://github.com/apple/foundationdb/releases/download/7.1.0/foundationdb-server_7.1.0-1_amd64.deb
wget https://github.com/apple/foundationdb/releases/download/7.1.0/foundationdb-clients_7.1.0-1_amd64.de

# Install
sudo dpkg -i foundationdb-clients_7.1.0-1_amd64.deb foundationdb-server_7.1.0-1_amd64.deb

# Uninstall
sudo dpkg -P foundationdb-clients foundationdb-server

Mac
直接下载一个 pkg 包即可

wget https://github.com/apple/foundationdb/releases/download/7.1.0/FoundationDB-7.1.0.pkg

安装完成之后foundationdb 会直接启动

关于 FoundationDB 的使用 以及 性能压测_#include


可以通过 ​​service foundationdb start/stop/status​​ 来控制当前单机环境的下的foundationdb 的配置。

当然,你可以启动多个fdbserver,对多个server 通过​​/etc/foundationdb/foundationdb.conf​​ 进行不同的角色配置,所有 foundationdb 论文中的 coordinator / log-server / proxy 等 角色都是一个fdbserver 进程,该进程拥有这个角色的配置而已。

源码编译 安装

一般有源码编译的需求是希望能够调试 fdb 内部运行的一些代码,可以在源码场景进行编译,

  1. 下载foundationdb 源码 并 checkout 到指定分支:
    ​​​git clone https://github.com/apple/foundationdb.git && cd foundationdb && git checkout 7.1.0​
  2. 升级环境的 cmake,要求版本大于等于 ​​3.13​
  3. 安装 mono(跨平台开发的工具,在一个平台可以开发其他平台的应用),foundationdb 编译的时候依赖这个东西,
    可以从 ​​​mono-官网​​ 直接进行安装,比较方便。
  4. 安装 ​​Ninja​​​ 或者 不用安装,直接用make。 Ninja 是用 C++ 写的小型的编译工具,非常方便且高性能。
    ​​​sudo apt-get install ninja-build​​​ 其他平台也可以直接搜索安装,或者去​​官网进行安装​​
  5. 编译 FoundationDB

cd foundationdb && mkdir build && cd build
# 之所以关闭掉rocksdb,是因为rocksdb 目前还是试验性的,没有上生产环境
cmake -G Ninja .. -DWITH_ROCKSDB_EXPERIMENTAL=OFF
ninja -j10

  1. 编译后的二进制会放在 ​​bin​​​ 目录下, lib库会放在 ​​lib​​​目录下。
    启动的话直接启动一个 fdbserver 进程就够了,该进程能够和客户端进行交互
    ​​​sudo ./bin/fdbserver --cluster-file /etc/foundationdb/fdb.cluster --datadir /var/lib/foundationdb/data/4500 --listen-address public --logdir /var/log/foundationdb --public-address auto:4500​

对于以上两种安装方式,最后启动了fdbserver 之后,我们可以直接通过​​fdbcli​​ 做一些测试:

$ fdbcli
Using cluster file `/etc/foundationdb/fdb.cluster'.

The database is available.

Welcome to the fdbcli. For help, type `help'.
fdb> status

Using cluster file `/etc/foundationdb/fdb.cluster'.

Configuration:
Redundancy mode - single
Storage engine - memory-2
Coordinators - 1
Usable Regions - 1
...
fdb> begin
Transaction started
fdb> writemode on
fdb> set a b
fdb> set a c
fdb> get a
`a' is `c'
fdb> commit
Committed (250049167890)
fdb> get a
`a' is `c
...

到此,整个 fdb 集群就是可用的了。

C-API 使用

FDB 将 C++ 接口做了 C 的封装,直接和 fdb-client API 进行交互,我们可以通过 C 接口启动一个类似 fdbcli 的服务和 fdb-client进行交互。

关于 C-API 的使用文档, 可以参考 ​​fdb c-api​​。

可以参考如下测试代码 对基本接口的使用,因为整个fdb 的内部接口(从client->server)都是依赖 Future 异步编程框架实现的,所以使用上还是需要有很多注意的地方。

而且因为异步框架的问题,很多接口调用之后返回,内部只是设置一个标记(fdb_database_set_option/fdb_transaction_set_option 等接口 并不是立即在server层进行设置),所以想要利用gdb 分析fdb 的内部实现复杂度还是挺高的,只能一点点撸代码了。

多租户的实现是fdb 7系版本之后支持的,允许不同的用户指定自己的租户名,不同租户之间的数据是不可见的。

#define FDB_API_VERSION 710

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <fdb_c.h>
#include <unistd.h>

FDBTenant *fdb_tenant = NULL;
FDBTransaction *tr = NULL;
FDBDatabase *db = NULL;
pthread_t netThread;

static void checkError(fdb_error_t errorNum) {
if (errorNum) {
fprintf(stderr, "Error (%d): %s\n", errorNum, fdb_get_error(errorNum));
exit(errorNum);
}
}

static void waitAndCheckError(FDBFuture *future) {
checkError(fdb_future_block_until_ready(future));
if (fdb_future_get_error(future) != 0) {
checkError(fdb_future_get_error(future));
}
}

static void runNetwork() { checkError(fdb_run_network()); }

void createDataInDatabase() {
int committed = 0;
/* Create transaction. */
checkError(fdb_database_create_transaction(db, &tr));

while (!committed) {
/* Create data */
char *key1 = "Test Key1";
char *val1 = "Test Value1";
fdb_transaction_set(tr, key1, (int)strlen(key1), val1, (int)strlen(val1));

/* Commit to database.*/
FDBFuture *commitFuture = fdb_transaction_commit(tr);
checkError(fdb_future_block_until_ready(commitFuture));
if (fdb_future_get_error(commitFuture) != 0) {
waitAndCheckError(
fdb_transaction_on_error(tr, fdb_future_get_error(commitFuture)));
} else {
committed = 1;
}
fdb_future_destroy(commitFuture);
}
/* Destroy transaction. */
fdb_transaction_destroy(tr);
}

void createTenantDataAndReadData() {
char *tenant_name = "example";
FDBTransaction *tr = NULL;
FDBTransaction *tr2 = NULL;
fdb_bool_t valuePresent;
int valueLength;
const uint8_t *value = NULL;
const char *k1 = "tenant key1";
const char *v1 = "tenant value1";

checkError(fdb_database_open_tenant(db, (uint8_t const *)tenant_name,
strlen(tenant_name), &fdb_tenant));
checkError(fdb_tenant_create_transaction(fdb_tenant, &tr));
fdb_transaction_set(tr, k1, (int)strlen(k1), v1, (int)strlen(v1));
FDBFuture *commitFuture = fdb_transaction_commit(tr);
checkError(fdb_future_block_until_ready(commitFuture));
if (fdb_future_get_error(commitFuture) != 0) {
waitAndCheckError(
fdb_transaction_on_error(tr, fdb_future_get_error(commitFuture)));
}
fdb_transaction_destroy(tr);
fdb_future_destroy(commitFuture);

checkError(fdb_tenant_create_transaction(fdb_tenant, &tr2));
FDBFuture *getFuture = fdb_transaction_get(tr2, k1, (int)strlen(k1), 0);
waitAndCheckError(getFuture);
checkError(
fdb_future_get_value(getFuture, &valuePresent, &value, &valueLength));

printf("Get value from tenant , key : %s, value : %s, value-len : %d\n", k1,
value, valueLength);
fdb_transaction_destroy(tr2);
fdb_future_destroy(getFuture);
}

void readDataFromDatabase() {
FDBTransaction *tr = NULL;
const uint8_t *value = NULL;
fdb_bool_t valuePresent;
int valueLength;
char *key = "Test Key1";

checkError(fdb_database_create_transaction(db, &tr));
FDBFuture *getFuture = fdb_transaction_get(tr, key, (int)strlen(key), 0);
waitAndCheckError(getFuture);

checkError(
fdb_future_get_value(getFuture, &valuePresent, &value, &valueLength));

printf("Got Value from db. %s: '%.*s'\n", key, valueLength, value);
fdb_transaction_destroy(tr);
fdb_future_destroy(getFuture);
}

int main() {
/* Default fdb cluster file. */
char *cluster_file = "/etc/foundationdb/fdb.cluster";

/* Setup network. */
checkError(fdb_select_api_version(FDB_API_VERSION));
checkError(fdb_setup_network());
puts("Created network.");

pthread_create(&netThread, NULL, (void *)runNetwork, NULL);

checkError(fdb_create_database(cluster_file, &db));
puts("Created database.");

/*Create tenant and do nothing.*/
createDataInDatabase();
readDataFromDatabase();

createTenantDataAndReadData();

puts("Program done. Now exiting...");
fdb_tenant_destroy(fdb_tenant);
fdb_tenant = NULL;
fdb_database_destroy(db);
db = NULL;
checkError(fdb_stop_network());
int rc = pthread_join(netThread, NULL);
if (rc)
fprintf(stderr, "ERROR: network thread failed to join\n");
exit(0);
}

​gcc test_fdb.c -lfdb_c -lpthread -I /usr/include/foundationdb/ -ggdb3 -O0 -g3 -o test_fdb ​

$ ./test_fdb
Created network.
Created database.
committing key/value.
Got Value : Test Key1: 'Test Value1'
Get value from tenant , key : tenant key1, value : tenant value1, value-len : 13
Program done. Now exiting...

性能测试

在前面的源码编译过程中,会编译出来一个叫做​​mako​​​ 的binary,它会被放在​​bin/mako​​​中。是fdb 官方提供的 C 接口实现的小型性能测试工具,能够对当前部署的fdb 环境做一些基本的性能测试,​​更多细节可以参考描述文档​​:

关于 FoundationDB 的使用 以及 性能压测_github_02

灌数据:

​./mako --cluster /etc/foundationdb/fdb.cluster --mode build --rows 10000000 --procs 4​

关于 FoundationDB 的使用 以及 性能压测_linux_03


灌数据结束之后,接下来可以在已有的数据集的基础上做一些组合性能的测试:

启动两个worker,每一个worker 8个线程, workload是:​​g8ui​​,表示 80%的get + 10% 的updates + 10%的inserts

​./mako --cluster /etc/foundationdb/fdb.cluster --mode run --rows 1000000 --procs 2 --threads 8 --transaction "g8ui" --seconds 60​

其中主要指定的workload 是通过 ​​--transaction ​​指定的:

  • 100% 读,​​g100​
  • 100% updates. ​​u100​
  • 100% insert. ​​i100​
  • range 读写 以及 控制读写比例,可以参考

需要注意的是,对于fdb 集群性能测试,如果不更改配置的情况下都是使用默认的配置,同样,默认的storage-engine 使用的是 ​​sqlite​​​。fdb支持动态修改集群配置,可以在fdbcli中,通过​​configure​​ 修改不同的存储引擎来做性能测试。


举报

相关推荐

0 条评论