基于sentinel的redis集群的客戶端:RedisSentinelClient
介紹
sentinel-client使用Redis做單節點的數據存儲,Sentinel做高可用服務的K-V存儲集群。
高可用方案簡介
高可用方案是基于Redis官方提供的Sentinel實現的.Sentinel的作用是對Redis實例的監控、通知、容災備份,是Redis集群的管理工具。在一個Redis集群中Sentinel作為中心監控各個節點的工作狀態,提升系統的高可用性。詳細的官方文檔見:http://redis.io/topics/sentinel
一致性Hash
數據的分布式存儲采用的是一致性Hash算法,這里做了些改動,對于客戶存儲的key,實際在redis中存儲的結構是bid_key bid 是應用程序按照業務來做的邏輯劃分 key 是客戶存儲的key
環境依賴
1.CentOS release 6.5 2.libssl.so 3.依賴的redis的配置項databases的值設置為1024
Log
在程序的執行目錄下會生成log文件(./redis_client_log.txt) 使用libkvdb.so出問題時請先查看./redis_client_log.txt
Install All
```編譯c++, java, python tar -zxvf sentinel-client.tar.gz cd sentinel-client make 完成后在sentinel-client目錄下生成libkvdb.so(c++), kvdb.jar(java) pykvdb.so(python)
## Install c++ ```編譯c++ tar -zxvf sentinel-client.tar.gz cd sentinel-client/cpp make 完成后在sentinel-client/cpp目錄下生成libkvdb.so 將libkvdb.so的目錄加入到環境變量LD_LIBRARY_PATH中
Install java
tar -zxvf sentinel-client.tar.gz cd sentinel-client/cpp && make cd sentinel-client/java/jni && make cd sentinel-client/java && ant 完成后在sentinel-client/java目錄下生成kvdb.jar 由于kvdb.jar需要在/tmp目錄下寫臨時的so文件,因此需要將/tmp目錄加入環境變量LD_LIBRARY_PATH中 export LD_LIBRARY_PATH=/tmp:${LD_LIBRARY_PATH}
Install python
tar -zxvf sentinel-client.tar.gz cd sentinel-client/cpp && make cd sentinel-client/python && make 完成后在sentinel-client/python目錄下生成libkvdb.so和pykvdb.so 將libkvdb.so和pykvdb.so的目錄加入到環境變量LD_LIBRARY_PATH和PYTHON_PATH中
TestAll
```test all cd sentinel-client make test 注:需要將sentinel-client/cpp/3party目錄加入到環境變量LD_LIBRARY_PATH中
## TestC++ ```test c++ cd sentinel-client/cpp make test 注:需要將sentinel-client/cpp/3party目錄加入到環境變量LD_LIBRARY_PATH中
TestJava
```test java cd sentinel-client/java ant -f buildtest.xml java -jar kvdbtest.jar
## C++ Demo ```c++ // 實例化客戶端 #include "RedisClient.h" RedisClient client = RedisClient("{{sentinel ip list}}", "{{business id}}"); // 方法1:使用封裝好的接口 // GET string value = client.get("my_key"); // SET bool valid = client.set("test_key", "test_value") // 方法2:使用自定義命令的接口 Reply reply = client.RedisCommand(Command("GET")("my_key")); if (reply.error()) { // 處理獲取失敗的邏輯 } string value = reply.str();
Member functions of Reply
Reply \_type() #獲取返回值類型 \_str() #獲取字符處返回值 \_integer() #獲取整形返回值 \_elements() #獲取list類型返回值 \_error() #命令是否執行失敗
Python Demo
import pykvdb client = pykvdb.newClient('{{sentinel ip list}}','{{your business id}}') pykvdb.set(client, 'mykey', 'myvalue') print pykvdb.get(client, 'mykey')
備注
ae事件庫中使用的zmalloc和Python的Impot_Module不兼容,使用時需要將zmalloc、zfree替換為malloc和free
Java Demo
import com.redis.sentinel.client.RedisClient; RedisClient client = new RedisClient("127.0.0.1:26379", "item"); boolean ret = client.set("kkk", "vvv"); String v = client.get("kkk");
Proxy
cd sentinel-client/proxy/ make vi etc/kvproxy.ini ./bin/bfdproxy &
備注
1.proxy是基于kvproxy擴展的對redis的支持 2.proxy內部調用redis-sentinel-client的cpp客戶端 3.proxy支持原生的redis協議 4.由于redis-sentinel-client的cpp客戶端的使用了 business_id,所以如果使用proxy訪問以前通過redis-sentinel-client寫入的數據,則需要用戶自己處理business_id. 例:
1.之前通過redis-sentinel-client寫入數據: RedisClient client("127.0.0.1:16379", "item"); client.set("kk", "vv"); 現在通過hiredis訪問proxy獲取數據: string business_id = "item_"; string key = business_id + "kk"; string command = string("GET ") + key; redisReply *reply = (redisReply *)redisCommand(cc,command.c_str()); 2.之前通過redis-sentinel-client寫入數據: RedisClient client("127.0.0.1:16379"); client.set("kk", "vv"); RedisClient 的構造函數的第二個參數的默認值為"item", 訪問proxy時仍然需要對key加上 "item_"前綴