1. 程式人生 > >支援叢集版 redis 的客戶端例子

支援叢集版 redis 的客戶端例子

據 redis 官方網站顯示,支援叢集版的 redis3.0 快要釋出了(現在已經到了redis3.0 rc4 版本),這樣使用者就不需要自己花很大力氣來針對 redis 進行分庫了,之前人們為了使單機版的 redis 能支援叢集方式,往往是在客戶端或通過加一箇中間的代理層(比如使用 tweaproxy)做很多工作,現在有了叢集版的 redis3.0 ,這些額外的操作都不再需要。

為了能夠支援叢集版的 redis 服務,另外增加了兩個主要的重定向指令需要客戶端能夠支援:MOVE, ASK。其中以 MOVE 指令為例,之所以增加此重定向指令,主要是考慮效率的因素,redis-server 叢集以雜湊槽的方式存放資料(目前最大是 16384 個雜湊槽),各個 redis-server 結點都會記錄著每個雜湊槽所在的最終結點的位置,所以當 redis 客戶端訪問一個 redis-server 時,如果該服務結點在計算完雜湊槽後發現該雜湊槽在別的服務結點上,則會給客戶端返回一個重定向指令(如:MOVE hash_slot ip:port),客戶端在獲得此重定向指令後會去連線最終的服務結點;另外,不了儘量減少重定向次數(有利於提高處理效率),官方協議文件中建議客戶端 應該快取住雜湊槽的儲存位置。

雖然叢集版本的 redis3.0 即將釋出,但目前主要的問題是缺乏客戶端的支援(目前據說可以支援的只有少數的幾個客戶端庫:象JAVA版的 jedis,ruby 版本),尤其是 C/C++ 客戶端庫更是匱乏,好訊息是 acl 庫中的 redis 客戶端模組已經很好地支援叢集 redis3.0 了,該庫不僅支援 redis 的重定向指令及雜湊槽的自動快取及自動更新功能,同時還支援 redis 服務結點自動釋出機制,即在初始 acl redis 客戶端庫時只需新增 一個或多個 redis 伺服器結點地址,在執行過程中會根據伺服器返回的重定向資訊動態新增新的 redis 伺服器結點。下面是使用 acl redis 庫叢集版本的例子:

#include "acl_cpp/lib_acl.hpp"

static void test_redis_string(acl::redis_string& cmd, const char* key)
{
    acl::string val("test_value");

    // 向 redis 叢集中新增一條字串型別的資料物件
    // 對應的 redis 命令:SET key value
    if (cmd.set(key, val.c_str()) == false)
    {
        printf("redis set error\r\n");
        return;
    }
    else
        printf("redis set ok\r\n");

    // 清除緩衝區
    val.clear();

    // 重置 redis 客戶端命令的狀態,以便可以複用該操作物件
    cmd.reset();

    // 從 redis 叢集中獲取指定鍵值的資料
    if (cmd.get(key, val) == false)
        printf("get key error\r\n");
    else
        printf("get key ok, value: %s\r\n", val.c_str());

}

static void test_redis_key(acl::redis_key& cmd, const char* key)
{
    // 查詢給定鍵在 redis 服務端是否存在
    if (cmd_key.exists(key) == false)
        printf("key not exists\r\n");
    else
        printf("key exists\r\n");
}

int main(void)
{
    const char* redis_addr = "127.0.0.1:6379";
    int conn_timeout = 10, rw_timeout = 10, max_conns = 100;

    // 定義 redis 客戶端叢集管理物件
    acl::redis_client_cluster cluster;
    // 新增一個 redis 服務結點,可以多次呼叫此函式新增多個服務結點,
    // 因為 acl redis 模組支援 redis 服務結點的自動發現及動態新增
    // 功能,所以新增一個服務結點即可
    cluster.set(redis_addr, max_conns);

    // redis 字串類 (STRING) 操作物件
    acl::redis_string cmd_string;

    // redis 鍵值類(KEY) 操作物件
    acl::redis_key cmd_key;

    // 給 redis 操作物件繫結 redis 客戶端叢集物件
    cmd_string.set_cluster(&cluster, max_conns);
    cmd_key.set_cluster(&cluster, max_conns);

    const char* key = "test_key";

    // redis 叢集命令操作的測試過程

    test_redis_string(cmd_string, key);
    test_redis_key(cmd_key, key);

    return 0;
}

參考:

1、acl 庫地址:https://github.com/zhengshuxin/acl

2、acl redis 標頭檔案地址:https://github.com/zhengshuxin/acl/tree/master/lib_acl_cpp/include/acl_cpp/redis

3、acl redis 原始檔地址:https://github.com/zhengshuxin/acl/tree/master/lib_acl_cpp/src/redis

4、acl redis 示例地址:https://github.com/zhengshuxin/acl/tree/master/lib_acl_cpp/samples/redis

5、acl QQ 群:242722074

6、微博:http://weibo.com/zsxxsz/


FROM: http://zsxxsz.iteye.com/blog/2190387