Redis用戶端串連方式Hiredis簡單封裝使用,串連池、屏蔽串連細節

來源:互聯網
上載者:User

工作需要對Hiredis進行了簡單封裝,實現功能:

1、API進行統一,對外只提供一個介面;

2、屏蔽上層應用對串連的細節處理;

3、底層採用隊列的方式保持串連池,儲存串連會話;

4、重連時採用時間戳記進行控制,每隔一定時間(3s)重連一次,防止頻繁重試造成的不必要浪費。

先看一下Hiredis的常用資料結構與API:

//hiredis/hiredis.h/* Context for a connection to Redis */typedef struct redisContext {    int err; /* Error flags, 0 when there is no error */    char errstr[128]; /* String representation of error when applicable */    int fd;     int flags;    char *obuf; /* Write buffer */    redisReader *reader; /* Protocol reader */} redisContext;/* This is the reply object returned by redisCommand() */#define REDIS_REPLY_STRING 1#define REDIS_REPLY_ARRAY 2#define REDIS_REPLY_INTEGER 3#define REDIS_REPLY_NIL 4#define REDIS_REPLY_STATUS 5#define REDIS_REPLY_ERROR 6typedef struct redisReply {    int type; /* REDIS_REPLY_* */    long long integer; /* The integer when type is REDIS_REPLY_INTEGER */    int len; /* Length of string */    char *str; /* Used for both REDIS_REPLY_ERROR and REDIS_REPLY_STRING */    size_t elements; /* number of elements, for REDIS_REPLY_ARRAY */    struct redisReply **element; /* elements vector for REDIS_REPLY_ARRAY */} redisReply;redisContext *redisConnectWithTimeout(const char *ip, int port, struct timeval tv);void redisFree(redisContext *c);

下面直接上封裝後的代碼:

class KGRedisClient{public:    KGRedisClient(string ip, int port, int timeout = 2000);    virtual ~KGRedisClient();    bool ExecuteCmd(const char *cmd, size_t len, string &response);    redisReply* ExecuteCmd(const char *cmd, size_t len);private:    int m_timeout;    int m_serverPort;    string m_setverIp;    CCriticalSection m_lock;    std::queue<redisContext *> m_clients;    time_t m_beginInvalidTime;    static const int m_maxReconnectInterval = 3;    redisContext* CreateContext();    void ReleaseContext(redisContext *ctx, bool active);    bool CheckStatus(redisContext *ctx);};KGRedisClient::KGRedisClient(string ip, int port, int timeout){    m_timeout = timeout;    m_serverPort = port;    m_setverIp = ip;    m_beginInvalidTime = 0;}KGRedisClient::~KGRedisClient(){    CAutoLock autolock(m_lock);    while(!m_clients.empty())    {        redisContext *ctx = m_clients.front();        redisFree(ctx);        m_clients.pop();    }}bool KGRedisClient::ExecuteCmd(const char *cmd, size_t len,string &response){    redisReply *reply = ExecuteCmd(cmd, len);    if(reply == NULL) return false;    boost::shared_ptr<redisReply> autoFree(reply, freeReplyObject);    if(reply->type == REDIS_REPLY_INTEGER)    {        response = _IntToStrA(reply->integer);        return true;    }    else if(reply->type == REDIS_REPLY_STRING)    {        response.assign(reply->str, reply->len);        return true;    }    else if(reply->type == REDIS_REPLY_STATUS)    {        response.assign(reply->str, reply->len);        return true;    }    else if(reply->type == REDIS_REPLY_NIL)    {        response = "";        return true;    }    else if(reply->type == REDIS_REPLY_ERROR)    {        response.assign(reply->str, reply->len);        return false;    }    else if(reply->type == REDIS_REPLY_ARRAY)    {        response = "Not Support Array Result!!!";        return false;    }    else    {        response = "Undefine Reply Type";        return false;    }}redisReply* KGRedisClient::ExecuteCmd(const char *cmd, size_t len){    redisContext *ctx = CreateContext();    if(ctx == NULL) return NULL;    redisReply *reply = (redisReply*)redisCommand(ctx, "%b", cmd, len);    ReleaseContext(ctx, reply != NULL);    return reply;}redisContext* KGRedisClient::CreateContext(){    {        CAutoLock autolock(m_lock);        if(!m_clients.empty())        {            redisContext *ctx = m_clients.front();            m_clients.pop();            return ctx;        }    }    time_t now = time(NULL);    if(now < m_beginInvalidTime + m_maxReconnectInterval) return NULL;    struct timeval tv;    tv.tv_sec = m_timeout / 1000;    tv.tv_usec = (m_timeout % 1000) * 1000;;    redisContext *ctx = redisConnectWithTimeout(m_setverIp.c_str(), m_serverPort, tv);    if(ctx == NULL || ctx->err != 0)    {        if(ctx != NULL) redisFree(ctx);        m_beginInvalidTime = time(NULL);                return NULL;    }    return ctx;}void KGRedisClient::ReleaseContext(redisContext *ctx, bool active){    if(ctx == NULL) return;    if(!active) {redisFree(ctx); return;}    CAutoLock autolock(m_lock);    m_clients.push(ctx);}bool KGRedisClient::CheckStatus(redisContext *ctx){    redisReply *reply = (redisReply*)redisCommand(ctx, "ping");    if(reply == NULL) return false;    boost::shared_ptr<redisReply> autoFree(reply, freeReplyObject);    if(reply->type != REDIS_REPLY_STATUS) return false;    if(strcasecmp(reply->str,"PONG") != 0) return false;    return true;}

稍加解釋:

成員變數:m_clients用於儲存串連池。

成員變數:m_beginInvalidTime、m_maxReconnectInterval 用於控制斷掉時的頻繁串連。

對外API:ExecuteCmd(const char *cmd, string &response);




聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.