天天看點

關于 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 的使用 以及 性能壓測

可以通過 ​

​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 的使用 以及 性能壓測

灌資料:

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

關于 FoundationDB 的使用 以及 性能壓測

灌資料結束之後,接下來可以在已有的資料集的基礎上做一些組合性能的測試:

啟動兩個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​

  • 100% 讀,​

    ​g100​

  • 100% updates. ​

    ​u100​

  • 100% insert. ​

    ​i100​

  • range 讀寫 以及 控制讀寫比例,可以參考

繼續閱讀