
redis c++接口
发布日期:2021-05-14 06:38:13
浏览次数:16
分类:原创文章
本文共 110052 字,大约阅读时间需要 366 分钟。
redis 接口
redis是c语言写的,有c接口,无c++接口。在一个负载均衡服务器项目中,用过一个redis的c++接口类。简单粗暴上代码吧,需要的自行移植一下。
/** redis_interface.cpp* Author: jacky* Data: 2019-4-12**/#include <stdio.h>#include <sstream>#include <string.h>#include <assert.h>#include <pthread.h>#include <hiredis/hiredis.h>#include <stdlib.h>#include <hiredis/sds.h>#include <unistd.h>#include <netinet/in.h>#include <arpa/inet.h>#include <sys/types.h>#include <sys/socket.h>#include <netdb.h>#include <iostream>#include <fstream>#include "varstr.h"#include "redis_interface.h"#include <sys/syslog.h>#include <linux/limits.h>using namespace ws_redis;using namespace std;RedisManager *RedisManager::_instance = 0;enum LogLevel { Fatal = LOG_EMERG, //0 最高级,致命的 Alert = LOG_ALERT, //1 最高级,必须采取措施 Crit = LOG_CRIT, //2 最高级,临界状态 Error = LOG_ERR, //3 高级,错误 Warn = LOG_WARNING, //4 高级,警告 Notice = LOG_NOTICE, //5 高级,正常但重要 Info = LOG_INFO, //6 高级,一般信息 Debug = LOG_DEBUG, //7 一般,调试信息};#define MAXLOGLINE 1024std::ofstream fileout; // 日志文件句柄//static long __log_lock = 0; // 加锁计数器char * pDevLevel = getenv("DEV_LOG_LEVEL"); // 获取环境变量,系统默认日志等级int syslogDevLevel = (NULL == pDevLevel) ? Debug : atol(pDevLevel);// 等级名称const char * levelnames[] = { "Fatal - ", "Alert - ", "Crit - ", "Error - ", "Warn - ", "Notice - ", "Info - ", "Debug - ", " - " };const char * LevelToName(int l) { return levelnames[l];}std::string Get_Current_Date(void){ time_t nowtime; nowtime = time(NULL); //获取日历时间 char tmp[64]; //strftime(tmp,sizeof(tmp),"%Y-%m-%d %H:%M:%S",localtime(&nowtime)); strftime(tmp,sizeof(tmp),"%Y-%m-%d",localtime(&nowtime)); return tmp;}std::string Get_Current_Date_All(void){ time_t nowtime; nowtime = time(NULL); //获取日历时间 char tmp[64]; strftime(tmp,sizeof(tmp),"%Y-%m-%d %H:%M:%S",localtime(&nowtime)); return tmp;}// 获取当前时间std::string safe_time(){ time_t t = time(NULL); char *ct = ctime(&t); if(ct){ size_t len = strlen(ct); if(len > 0){ ct[len - 1] = '\0'; return std::string(ct, len - 1); } } return "empty time";}//初始化日志,打开日志文件流void initLog(void) { char buffer[PATH_MAX * 2]; //ZeroMemory(buffer, sizeof(char) * PATH_MAX * 2); memset(buffer, 0, sizeof(char) * PATH_MAX * 2); sprintf(buffer, "./log/%sprotocol.log", Get_Current_Date().c_str()); fileout.open(buffer, std::ios_base::app); fileout << "program start: " << Get_Current_Date_All() << std::endl;}// 获取日志等级int getLogLevel(){ return syslogDevLevel;}// 设置日志等级,返回旧的等级(这里不修改环境变量,防止更改所有进程的输出等级)int setLogLevel(int l){ int old_level = syslogDevLevel; syslogDevLevel = l; return old_level;}void logxxx(int l, char *file, int line, const char *fmt, ...){ va_list param; va_start(param, fmt); // 锁 /*while (true) { if (InterlockedIncrement(&__log_lock) == 1) { break; } InterlockedDecrement(&__log_lock); }*/ if (l <= syslogDevLevel) { char buf[MAXLOGLINE * 4]; vsnprintf(buf, MAXLOGLINE * 4, fmt, param); fileout << Get_Current_Date_All() << " " << file << line << ":" << LevelToName(l) << buf << std::endl; fileout.flush(); } //InterlockedDecrement(&__log_lock); va_end(param);}//#define log(...)#define log(l, ...) do{logxxx(l, (char *)__FILE__, __LINE__, __VA_ARGS__); }while(0)//--------------------------------------------------------// reids命令实行时间检测器//--------------------------------------------------------RedisCmdTimeTesting::RedisCmdTimeTesting(){ gettimeofday(&m_begin, NULL);}RedisCmdTimeTesting::~RedisCmdTimeTesting(){ gettimeofday(&m_end, NULL); uint64_t ucost = 1000000 * (m_end.tv_sec - m_begin.tv_sec) + (m_end.tv_usec - m_begin.tv_usec); // 秒*1 000 000 + 微秒 (高精度) log(Info,"redis_cmd_time! log:%s, ucost:%lu ", m_log.c_str(), ucost); // 输出日志 //std::cout << m_log.c_str() << ucost << std::endl;}void RedisCmdTimeTesting::Log(PRedisContext pRD, const char* fmt, ...){ static char buf[WS_REDIS_LOG_LENGTH_MAX]; va_list ap; va_start(ap, fmt); int len = vsnprintf(buf, sizeof(buf), fmt, ap); va_end(ap); if (len > 0) { len = WS_REDIS_LOG_LENGTH_MAX > len ? len : WS_REDIS_LOG_LENGTH_MAX; // 长度检查 m_log.assign(buf, len); // 赋值 //len = snprintf(buf, sizeof(buf), "%s:%d:%d", pRD->tag.ip, pRD->tag.port, pRD->tag.dbIndex); // 写入相关信息 //len = WS_REDIS_LOG_LENGTH_MAX > len ? len : WS_REDIS_LOG_LENGTH_MAX; // 长度验证 //m_log.append(buf, len); }}static PRedisContext redisContextInit(void) { PRedisContext c; c = (PRedisContext)calloc(1,sizeof(redisContext)); if (c == NULL) return NULL; c->err = 0; c->errstr[0] = '\0'; //c->obuf = sdsempty(); c->reader = redisReaderCreate();#ifdef TRACE_EAGLE_EYE // for trace c->tag.trace = (kitty::TraceSimulate *) new kitty::TraceSimulate;#endif return c;}void __redisSetError(redisContext *c, int type, const char *str) { size_t len; c->err = type; if (str != NULL) { len = strlen(str); len = len < (sizeof(c->errstr)-1) ? len : (sizeof(c->errstr)-1); memcpy(c->errstr,str,len); c->errstr[len] = '\0'; } else { /* Only REDIS_ERR_IO may lack a description! */ assert(type == REDIS_ERR_IO); strerror_r(errno,c->errstr,sizeof(c->errstr)); }}int redisContextConnectTcp(redisContext *c, const char *addr, int port, struct timeval *timeout) { #if 0 int s, rv; char _port[6]; /* strlen("65535"); */ struct addrinfo hints, *servinfo, *p; int blocking = (c->flags & REDIS_BLOCK); snprintf(_port, 6, "%d", port); memset(&hints,0,sizeof(hints)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; if ((rv = getaddrinfo(addr,_port,&hints,&servinfo)) != 0) { __redisSetError(c,REDIS_ERR_OTHER,gai_strerror(rv)); return REDIS_ERR; } for (p = servinfo; p != NULL; p = p->ai_next) { if ((s = socket(p->ai_family,p->ai_socktype,p->ai_protocol)) == -1) continue; if (redisSetBlocking(c,s,0) != REDIS_OK) goto error; if (connect(s,p->ai_addr,p->ai_addrlen) == -1) { if (errno == EHOSTUNREACH) { close(s); continue; } else if (errno == EINPROGRESS && !blocking) { /* This is ok. */ } else { if (redisContextWaitReady(c,s,timeout) != REDIS_OK) goto error; } } if (blocking && redisSetBlocking(c,s,1) != REDIS_OK) goto error; if (redisSetTcpNoDelay(c,s) != REDIS_OK) goto error; c->fd = s; c->flags |= REDIS_CONNECTED; rv = REDIS_OK; // modified by xwz, add the socket information into mapi tag for tracing // in case of redis using ipV6, it is safe to call getsockname again struct sockaddr_in localAddr; socklen_t addrLen = sizeof(struct sockaddr_in); if (getsockname(c->fd, (struct sockaddr *)&localAddr, &addrLen) == 0) { c->tag.localPort = ntohs(localAddr.sin_port); c->tag.localHost = ntohl(localAddr.sin_addr.s_addr);// fprintf(stderr, "get sockname sucess, localHost = %s, localPort = %u\n",// inet_ntoa(localAddr.sin_addr),// c->tag.localPort); } else { c->tag.localHost = 0; c->tag.localPort = 0;// fprintf(stderr, "get sockname failed"); } addrLen = sizeof(struct sockaddr_in); if (getpeername(c->fd, (struct sockaddr *)&localAddr, &addrLen) == 0) { c->tag.peerPort = ntohs(localAddr.sin_port); c->tag.peerHost = ntohl(localAddr.sin_addr.s_addr);// fprintf(stderr, "get sockname sucess, peerHost = %s, peerPort = %u\n",// inet_ntoa(localAddr.sin_addr),// c->tag.peerPort); } else { c->tag.peerHost = 0; c->tag.peerPort = 0;// fprintf(stderr, "get peername failed"); } goto end; } if (p == NULL) { char buf[128]; snprintf(buf,sizeof(buf),"Can't create socket: %s",strerror(errno)); __redisSetError(c,REDIS_ERR_OTHER,buf); goto error; }error: rv = REDIS_ERR;end: freeaddrinfo(servinfo); return rv; // Need to return REDIS_OK if alright#endif return 0;}RedisManager * RedisManager::singleton(){ if(!_instance) { _instance = new RedisManager(); } return _instance;}//--------------------------------------------------------// reids 连接管理器//--------------------------------------------------------// -----------------redis连接相关---------------------// 创建链接uint32_t RedisManager::CreateContext(std::string ip, uint32_t port){ std::lock_guard<std::mutex> lock(m_RedisLock); // 加锁 // 遍历查找该id是否已经建立了链接 PRedisContext_ext pRDEXT; PRedisContext pRD = NULL; uint32_t key_num = 0; map<uint32_t, PRedisContext_ext>::iterator it = m_allRedisConn.begin(); for (; it != m_allRedisConn.end(); ++it) { pRDEXT = it->second; pRD = pRDEXT.pRD; if (NULL != pRD) { if (ip.compare(pRDEXT.str_ip.c_str()) == 0) { if (port == (uint32_t)pRDEXT.port) { key_num = it->first; log(Info, "RedisManager::CreateContext this ip&port have create !"); return key_num; } } } } if (0 == key_num) // 该ip没有建立链接 { pRD = redisConnect(ip.c_str(), (int)port); if (NULL != pRD && !pRD->err) { pRDEXT.pRD = pRD; pRDEXT.str_ip = ip; pRDEXT.port = port; key_num = ++m_MaxRedisContext; // 获取key m_allRedisConn.insert(make_pair(key_num, pRDEXT)); log(Info, "RedisManager::CreateContext Success to restore redis connection."); std::cout << "RedisManager::CreateContext Success to restore redis connection." << std::endl; } else { log(Error, "RedisManager::CreateContext fail! ip: %s, port: %u, err: %d, desc: %s", ip.c_str(), port, pRD->err, pRD->errstr); std::cout << ip.c_str() << port << pRD->err << pRD->errstr << std::endl; } } return key_num;}int redisContextSetTimeout(redisContext *c, struct timeval tv){ if (setsockopt(c->fd,SOL_SOCKET,SO_RCVTIMEO,&tv,sizeof(tv)) == -1) { //__redisSetErrorFromErrno(c,REDIS_ERR_IO,"setsockopt(SO_RCVTIMEO)"); return REDIS_ERR; } if (setsockopt(c->fd,SOL_SOCKET,SO_SNDTIMEO,&tv,sizeof(tv)) == -1) { //__redisSetErrorFromErrno(c,REDIS_ERR_IO,"setsockopt(SO_SNDTIMEO)"); return REDIS_ERR; } return REDIS_OK;}PRedisContext my_redisConnectWithTimeout(const char *ip, int port, struct timeval tv){ PRedisContext c = redisContextInit(); c->flags |= REDIS_BLOCK; //redisContextConnectTcp(c,ip,port,&tv); return c;}#if 0// 建立链接,带超时时间uint32_t RedisManager::CreateContextWithOutTime(std::string ip, uint32_t port, uint32_t time){ std::lock_guard<std::mutex> lock(m_RedisLock); // 加锁 // 遍历查找该id是否已经建立了链接 PRedisContext pRD = NULL; uint32_t key_num = 0; map<uint32_t, PRedisContext>::iterator it = m_allRedisConn.begin(); for (; it != m_allRedisConn.end(); ++it) { pRD = it->second; if (NULL != pRD) { std::string str_ip; str_ip.assign(&(pRD->tag.ip[0]), sizeof(char)*32); if (ip.compare(str_ip.c_str()) == 0) { if (port == (uint32_t)pRD->tag.port) { key_num = it->first; log(Info, "RedisManager::CreateContext this ip&port have create !"); return key_num; } } } } if (0 == key_num) // 该ip没有建立链接 { struct timeval timeout = { (long)time, 500000 }; // 1.5 seconds pRD = my_redisConnectWithTimeout(ip.c_str(), (int)port, timeout); if (NULL != pRD && 0 == pRD->err) { key_num = ++m_MaxRedisContext; // 获取key timeout.tv_sec = 6; redisContextSetTimeout(pRD, timeout); // 设置超时时间 m_allRedisConn.insert(make_pair(key_num, pRD)); log(Info, "RedisManager::CreateContext Success to restore redis connection."); } else { log(Error, "RedisManager::CreateContext fail! ip: %s, port: %u, err: %d, desc: %s", ip.c_str(), port, pRD->err, pRD->errstr); } } return key_num;}#endif// 指定管理某个链接bool RedisManager::CloseContext(uint32_t index_link){ std::lock_guard<std::mutex> lock(m_RedisLock); // 加锁 // 遍历查找该id是否已经建立了链接 PRedisContext_ext pRDEXT; PRedisContext pRD = NULL; map<uint32_t, PRedisContext_ext>::iterator it = m_allRedisConn.find(index_link); if (it != m_allRedisConn.end()) { pRDEXT = it->second; pRD = pRDEXT.pRD; redisFree(&(*pRD)); pRD = NULL; } log(Warn, "CloseContext: index_link %u ", index_link); return true;}// 关闭所有链接bool RedisManager::CloseAllContext(){ std::lock_guard<std::mutex> lock(m_RedisLock); // 加锁 // 遍历查找该id是否已经建立了链接 PRedisContext_ext pRDEXT; PRedisContext pRD = NULL; map<uint32_t, PRedisContext_ext>::iterator it = m_allRedisConn.begin(); for (; it != m_allRedisConn.end(); ++it) { pRDEXT = it->second; pRD = pRDEXT.pRD; redisFree(&(*pRD)); } m_allRedisConn.clear(); log(Warn, "CloseAllContext: "); return true;}// 根据key获取redis连接(每个连接DB个数由配置决定)// (多连接情况下)通过hash key找到该key存储的redis连接,并发情况下可以提高并发率PRedisContext RedisManager::getRedis(std::string key){ // hash 找出对应的redis连接 const char* ckey = key.c_str(); uint32_t hash = WS_REDIS_CONTEXT_HASH_MARK; for (uint32_t i = 0; i < key.length(); i++) { hash = ((hash << 5) + hash) + ckey[i]; hash = hash & 0xFFFFFFFFl; } std::lock_guard<std::mutex> lock(m_RedisLock); // 加锁 // 获取第n个 uint32_t index = (uint32_t)hash % (m_MaxRedisContext + 1); if (index == m_MaxRedisContext) { --index; } PRedisContext_ext pRDEXT; map<uint32_t, PRedisContext_ext>::iterator pRD_it = m_allRedisConn.find(index); if (pRD_it != m_allRedisConn.end()) { pRDEXT = pRD_it->second; return pRDEXT.pRD; } return NULL;}// 直接指明hashmap中第几个redis连接PRedisContext RedisManager::getRedis(uint32_t index_link){ std::lock_guard<std::mutex> lock(m_RedisLock); // 加锁 PRedisContext_ext pRDEXT; map<uint32_t, PRedisContext_ext>::iterator pRD_it = m_allRedisConn.find(index_link); if (pRD_it != m_allRedisConn.end()) { /*if (pRD_it->second != NULL) { log(Warn, "getRedis: index_link %u have break off ! ", index_link); }*/ pRDEXT = pRD_it->second; return pRDEXT.pRD; } return NULL;}// 获取指定redis连接中的第N个DBbool RedisManager::selectDB(PRedisContext& pRD, uint32_t index_db){ std::string cmd("SELECT %d"); RedisCmdTimeTesting cTime; redisReply* reply = (redisReply*)redisCommand(pRD, cmd.c_str(), index_db); cTime.Log(pRD, "SELECT %u ; reply:%u, pRD:%u", index_db, reply, pRD); // 打印地址 if (reply) { //pRD->tag.dbIndex = index_db; freeReplyObject(reply); // 释放空间 } else { log(Warn, "err: redis select db %u failed! Error:%d, err_info:%s", index_db, pRD->err, pRD->errstr); return false; } return true;}// -----------------tool工具--------------------------// 链接信息std::string RedisManager::contextAddrInfo(PRedisContext& pRD){ if (pRD == NULL) { return "NULL"; } char ip[32] = "0.0.0.0"; int port = 0; struct sockaddr_in guest; unsigned int guest_len = sizeof(guest); // 获取链接的对方的socket地址 if (0 == getpeername(pRD->fd, (struct sockaddr *)&guest, &guest_len)) { // 将地址转换成10进制字符串 inet_ntop(AF_INET, &guest.sin_addr, ip, sizeof(ip)); port = ntohs(guest.sin_port); } std::stringstream os; os << "redis_info:[" << ip << ":" << port << "]"; os << "context_info:[" << pRD->err << ":" << pRD->errstr << "]"; return os.str();}// 报告信息std::string RedisManager::replayInfo(redisReply* pReply){ if (pReply == NULL) { return "NULL"; } const char * type = "NaN"; const char * strval = ""; long long int intval = 0; switch (pReply->type) { case REDIS_REPLY_STRING: { type = "std::string"; strval = pReply->str; break; } case REDIS_REPLY_ARRAY: { type = "ARRAY"; break; } case REDIS_REPLY_INTEGER: { type = "INTEGER"; intval = pReply->integer; break; } case REDIS_REPLY_NIL: { type = "NIL"; break; } case REDIS_REPLY_STATUS: { type = "STATUS"; strval = pReply->str; break; } case REDIS_REPLY_ERROR: { type = "ERROR"; strval = pReply->str; break; } default: { } } if (strval == 0) strval = "NULL"; char tmp[100] = { 0 }; snprintf(tmp, sizeof(tmp), "type(%s),int(%lld),str(%s)", type, intval, strval); return tmp;}// -----------------redis命令相关---------------------redisReply* RedisManager::redisCommand(PRedisContext& pRD, const char *format, ...){ va_list ap; struct timeval tBeginTime, tEndTime; gettimeofday(&tBeginTime, NULL); // 初始化执行时间 // 执行命令 va_start(ap, format); void *reply = redisvCommand(&(*pRD), format, ap); va_end(ap); gettimeofday(&tEndTime, NULL); // 执行结束时间 // 获取命令key std::string strKey; strKey = format; strKey = strKey.substr(0, 10); buildReport(strKey, tBeginTime, tEndTime); // 生成报告 // log redisReply * rreply = (redisReply*)reply; if (rreply == NULL || pRD == NULL || pRD->err != 0 || rreply->type == REDIS_REPLY_ERROR) { //log(Warn, "err REDIS_REPLY %s ! redis_info:%s, reply_info:%s, format:`%s`", __func__, contextAddrInfo(pRD).c_str(), replayInfo(rreply).c_str(), replaceCmdCrlf(format).c_str()); return NULL; } else { //log(Debug, "REDIS_REPLY %s ! redis_info:%s, reply_info:%s, format:`%s`", __func__, contextAddrInfo(pRD).c_str(), replayInfo(rreply).c_str(), replaceCmdCrlf(format).c_str()); } return rreply;}// key// 获取数据库中所有的key; value: 为返回的所有key集合, strMatching:为查找匹配,默认为"*"所有,可以为如"t[w]*"表达式bool RedisManager::getAllKeys(PRedisContext& pRD, set<std::string>& value, std::string strMatching){ RedisCmdTimeTesting cTime; // 记录 // 执行命令 redisReply* reply = redisCommand(pRD, "KEYS %s", strMatching.c_str()); if (reply) { if (reply->type == REDIS_REPLY_ARRAY) { for (unsigned int j = 0; j < reply->elements; ++j) { value.insert(reply->element[j]->str); } cTime.Log(pRD, "getAllKeys KEYS %s! reply:%u, size:%d", strMatching.c_str(), reply, value.size()); freeReplyObject(reply); return true; } else { cTime.Log(pRD, "ERROR KEYS %s ! repl: %u, size:0", strMatching.c_str(), reply); freeReplyObject(reply); return false; } } log(Warn, "err: getAllKeys! SMEMBERS reply is NULL!"); return false;}// 检查key是否存在bool RedisManager::isKeyExist(PRedisContext& pRD, const string& key, bool& keyExist){ RedisCmdTimeTesting cTime; redisReply* reply = redisCommand(pRD, "EXISTS %s", key.c_str()); cTime.Log(pRD, "IsKeyExist EXISTS %s! reply:%u", key.c_str(), reply); if (reply) { if (reply->type == REDIS_REPLY_INTEGER) { if (reply->integer == 1) { keyExist = true; freeReplyObject(reply); return true; } else if (reply->integer == 0) { keyExist = false; freeReplyObject(reply); return false; } else { keyExist = false; log(Error, "IsKeyExist: unexpected integer:%lld", reply->integer); freeReplyObject(reply); return false; } } else { log(Error, "IsKeyExist: unexpected reply type:%u", reply->type); freeReplyObject(reply); return false; } } log(Error, "IsKeyExist: EXISTS reply is NULL! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// 删除指定的keybool RedisManager::delKey(PRedisContext& pRD, const std::string& key){ RedisCmdTimeTesting cTime; redisReply* reply = redisCommand(pRD, "DEL %s", key.c_str()); cTime.Log(pRD, "delKey DEL %s! reply:%u", key.c_str(), reply); if (reply) { freeReplyObject(reply); return true; } log(Warn, "err: delKey: reply is NULL! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// 事务模式:删除指定的key, 返回0表示失败,1表示成功,2表示存入队列(因为有事务处理)uint32_t RedisManager::delKey_T(PRedisContext& pRD, const std::string& key){ RedisCmdTimeTesting cTime; redisReply* reply = redisCommand(pRD, "DEL %s", key.c_str()); cTime.Log(pRD, "delKey DEL %s! reply:%u", key.c_str(), reply); if (reply) { if (REDIS_REPLY_STATUS == reply->type) { if (strcmp(reply->str, "QUEUED") == 0) { freeReplyObject(reply); return 2; } } freeReplyObject(reply); return 1; } log(Warn, "err: delKey: reply is NULL! error:%d, error_info:%s", pRD->err, pRD->errstr); return 0;}// 获取key的类型;返回值:none(key不存在),std::string(字符串),list(列表),set(集合),zset(有序集),hash(哈希表)bool RedisManager::keyType(PRedisContext& pRD, const std::string& key, std::string& type){ RedisCmdTimeTesting cTime; redisReply* reply = redisCommand(pRD, "TYPE %s", key.c_str()); cTime.Log(pRD, "keyType TYPE %s! reply:%u", key.c_str(), reply); if (reply) { if (reply->type == REDIS_REPLY_STATUS) { type.assign(reply->str, reply->len); freeReplyObject(reply); return true; } } log(Warn, "err: Wrong reply type received! key:%s, type:%d, error:%d, error_info:%s,", key.c_str(), reply->type, pRD->err, pRD->errstr); return false;}// 设置key的生存时间,单位sbool RedisManager::setKeyTTL(PRedisContext& pRD, const std::string& key, uint32_t time){ RedisCmdTimeTesting cTime; redisReply* reply = redisCommand(pRD, "expire %s %s", key.c_str(), ws::toString(time).c_str()); cTime.Log(pRD, "setKeyTTL key %s! time:%u, reply:%u", key.c_str(), time, reply); if (reply) { freeReplyObject(reply); return true; } log(Warn, "err: setKeyTTL: reply is NULL! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// 更新key的生存时间, 单位s;覆盖旧的生存时间bool RedisManager::expireAt(PRedisContext& pRD, const std::string& key, time_t calTime){ RedisCmdTimeTesting cTime; redisReply* reply = (redisReply*)redisCommand(pRD, "EXPIREAT %s %s", key.c_str(), ws::toString(calTime).c_str()); cTime.Log(pRD, "expireAt EXPIREAT %s ! time:%s, reply:%u", key.c_str(), ws::toString(calTime).c_str(), reply); if (reply) { bool retCode; if (reply->type == REDIS_REPLY_INTEGER) { retCode = (reply->integer != 0); } else { log(Warn, "expireAt: reply is NULL! error:%d, error_info:%s", pRD->err, pRD->errstr); retCode = false; } freeReplyObject(reply); return retCode; } log(Warn, "expireAt: reply is NULL! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// lockbool RedisManager::lock(PRedisContext& pRD, const std::string &key, uint32_t ttl){ // 限制在第一个db if (!pRD || !selectDB(pRD, 0)) { log(Error, "%s, select db failed ,key:%s ", __FUNCTION__, key.c_str()); return false; } long long int ret; uint32_t sleepTimes = 101;// 最多睡两秒 do { if (incrValue(pRD, key, ret, 1) && 1 == ret) { setKeyTTL(pRD, key, ttl); return true; } if (0 == --sleepTimes) { break; } usleep(200); } while (true); return false;}bool RedisManager::unlock(PRedisContext& pRD, const std::string &key){ if (!pRD || !selectDB(pRD, 0)) { log(Warn, "%s, select db failed ,key:%s ", __FUNCTION__, key.c_str()); return false; } if (!delKey(pRD, key)) { return false; } return true;}//--- std::stringbool RedisManager::setStrValue(PRedisContext& pRD, const std::string& key, const std::string& value){ RedisCmdTimeTesting cTime; redisReply* reply = redisCommand(pRD, "SET %s %b", key.c_str(), value.data(), value.size()); cTime.Log(pRD, "setStrValue SET %s ! reply:%u", key.c_str(), reply); if (reply) { freeReplyObject(reply); return true; } log(Warn, "err: setStrValue: reply is NULL! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}bool RedisManager::setStrValue(PRedisContext& pRD, const std::string& key, const std::string& value, const uint32_t& time){ RedisCmdTimeTesting cTime; bool retCode = false; redisReply* reply = redisCommand(pRD, "SETEX %s %s %s", key.c_str(), ws::toString(time).c_str(), value.c_str()); cTime.Log(pRD, "setStrValue SETEX %s %u %s ! reply:%u", key.c_str(), time, value.c_str(), reply); if (reply) { if (REDIS_REPLY_STATUS == reply->type) { if (strcmp(reply->str, "OK") == 0) { retCode = true; } else { log(Error, "SETEX return failure"); } } else { log(Error, "SETEX return error type"); } freeReplyObject(reply); } else { log(Warn, "err: setStrValue: reply is NULL! error:%d, error_info:%s", pRD->err, pRD->errstr); } return retCode;}bool RedisManager::getStrValue(PRedisContext& pRD, const std::string& key, std::string& value){ RedisCmdTimeTesting cTime; redisReply* reply = redisCommand(pRD, "GET %s", key.c_str()); cTime.Log(pRD, "getStrValue GET %s ! reply:%u", key.c_str(), reply); if (reply) { if (reply->type == REDIS_REPLY_STRING) { value.assign(reply->str, reply->len); } freeReplyObject(reply); return true; } log(Warn, "err: getStrValue: reply is NULL! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}bool RedisManager::setAnyValue(PRedisContext &pRD, map<std::string, std::string> value){ if (value.empty()) { return false; } string command("MSET"); for (map<string, string>::iterator it = value.begin(); it != value.end(); ++it) { command += " " + it->first + " " + it->second; } RedisCmdTimeTesting cTime; redisReply* reply = redisCommand(pRD, command.c_str()); cTime.Log(pRD, "setBatchStrValue %s ! reply:%u", command.c_str(), reply); if (reply) { freeReplyObject(reply); return true; } log(Warn, "err: setBatchStrValue: reply is NULL! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}bool RedisManager::getAnyValue(PRedisContext& pRD, const set<std::string>& setKeys, map<std::string, std::string>& outMapInfo){ if (setKeys.empty()) { return false; } string command("MGET "); uint32_t count = 0; set<string>::const_iterator itSet; for (itSet = setKeys.begin(); itSet != setKeys.end(); ++itSet) { command += *itSet + " "; count++; } RedisCmdTimeTesting cTime; redisReply* reply = redisCommand(pRD, command.c_str()); cTime.Log(pRD, "getBatchStrValue %s ! reply:%u", command.c_str(), reply); if (reply) { if (reply->type == REDIS_REPLY_ARRAY) { assert(count == reply->elements); uint32_t i = 0; for (itSet = setKeys.begin(); itSet != setKeys.end(); ++itSet) { if (reply->element[i]->type == REDIS_REPLY_STRING) { outMapInfo[*itSet] = reply->element[i]->str; } ++i; } } freeReplyObject(reply); } return true;}//std::string incr// 每次增加指定值,默认为1bool RedisManager::incrValue(PRedisContext& pRD, const std::string& key, int incrNum){ RedisCmdTimeTesting cTime; redisReply* reply = NULL; if (1 == incrNum) { reply = redisCommand(pRD, "INCR %s %d", key.c_str()); } else { reply = redisCommand(pRD, "INCRBY %s %d", key.c_str(), incrNum); } cTime.Log(pRD, "incrByValue INCRBY %s %d ! reply:%u", key.c_str(), incrNum, reply); if (reply) { if (REDIS_REPLY_INTEGER == reply->type) { freeReplyObject(reply); return true; } else { log(Error, "err: INCRBY return error type"); freeReplyObject(reply); return false; } } log(Warn, "err: incrByValue: reply is NULL! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// 每次增加指定值,默认为1,返回增加后的值bool RedisManager::incrValue(PRedisContext& pRD, const std::string& key, long long &outValue, int incrNum){ RedisCmdTimeTesting cTime; redisReply* reply = NULL; if (1 == incrNum) { reply = redisCommand(pRD, "INCR %s %d", key.c_str()); } else { reply = redisCommand(pRD, "INCRBY %s %d", key.c_str(), incrNum); } cTime.Log(pRD, "incrByValue INCRBY %s %d ! reply:%u", key.c_str(), incrNum, reply); if (reply) { if (REDIS_REPLY_INTEGER == reply->type) { outValue = reply->integer; freeReplyObject(reply); return true; } else { log(Error, "err: INCRBY return error type"); freeReplyObject(reply); return false; } } log(Warn, "err: incrByValue: reply is NULL! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}//std::string decr// 每次减去指定值,默认为1bool RedisManager::decrValue(PRedisContext& pRD, const std::string& key, int decrNum){ RedisCmdTimeTesting cTime; redisReply* reply = NULL; if (1 == decrNum) { reply = redisCommand(pRD, "DECR %s", key.c_str()); } else { reply = redisCommand(pRD, "DECRBY %s %s", key.c_str(), ws::toString(decrNum).c_str()); } cTime.Log(pRD, "DECR %s %d ! reply:%u retCode %d", key.c_str(), decrNum, reply); if (reply) { if (REDIS_REPLY_INTEGER == reply->type) { freeReplyObject(reply); return true; } else { log(Error, "DECR return error type"); freeReplyObject(reply); return false; } } log(Warn, "decrValue: reply is NULL ! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// 每次减去指定值,默认为1,返回增加后的值bool RedisManager::decrValue(PRedisContext& pRD, const std::string& key, long long &outValue, int decrNum){ RedisCmdTimeTesting cTime; redisReply* reply = NULL; if (1 == decrNum) { reply = redisCommand(pRD, "DECR %s", key.c_str()); } else { reply = redisCommand(pRD, "DECRBY %s %s", key.c_str(), ws::toString(decrNum).c_str()); } cTime.Log(pRD, "DECR %s %d ! reply:%u retCode %d", key.c_str(), decrNum, reply); if (reply) { if (REDIS_REPLY_INTEGER == reply->type) { outValue = reply->integer; freeReplyObject(reply); return true; } else { log(Error, "DECR return error type"); freeReplyObject(reply); return false; } } log(Warn, "decrValue: reply is NULL ! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}//--- list// 获取list长度bool RedisManager::getListLen(PRedisContext& pRD, const std::string& key, uint32_t& len){ len = 0; bool keyExist = false; if (false == isKeyExist(pRD, key, keyExist)) { return false; } if (keyExist == false) { return true; } RedisCmdTimeTesting cTime; redisReply* reply = redisCommand(pRD, "LLEN %s", key.c_str()); cTime.Log(pRD, "getListLen LLEN %s ! reply:%u", key.c_str(), reply); if (reply) { if (reply->type == REDIS_REPLY_STRING) { len = strtoul(reply->str, 0, 0); } else if (reply->type == REDIS_REPLY_INTEGER) { len = reply->integer; } else { log(Warn, "getListLen: LLEN reply is unexpected!"); } freeReplyObject(reply); return true; } log(Warn, "getListLen: reply is NULL! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// 插入表头,表为空创建bool RedisManager::lPushList(PRedisContext& pRD, const std::string& key, std::string& value){ RedisCmdTimeTesting cTime; redisReply* reply = redisCommand(pRD, "LPUSH %s %s", key.c_str(), value.c_str()); cTime.Log(pRD, "LPUSHList LPUSH %s %s ! reply:%u", key.c_str(), value.c_str(), reply); if (reply) { freeReplyObject(reply); return true; } log(Error, "LPUSHList: reply is NULL! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// 插入表尾,表为空创建bool RedisManager::rPushList(PRedisContext& pRD, const std::string& key, std::string& value){ RedisCmdTimeTesting cTime; redisReply* reply = redisCommand(pRD, "RPUSH %s %s", key.c_str(), value.c_str()); cTime.Log(pRD,"RPUSHList RPUSH %s %s ! reply:%u", key.c_str(), value.c_str(), reply); if (reply) { freeReplyObject(reply); return true; } log(Warn, "RPUSHList: reply is NULL! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// 插入表头,表为空不创建bool RedisManager::lPushXList(PRedisContext& pRD, const std::string& key, std::string& value){ RedisCmdTimeTesting cTime; redisReply* reply = redisCommand(pRD, "LPUSHX %s %s", key.c_str(), value.c_str()); cTime.Log(pRD, "LPUSHXList LPUSHX %s %s ! reply:%u", key.c_str(), value.c_str(), reply); if (reply) { freeReplyObject(reply); return true; } log(Warn, "LPUSHXList: reply is NULL! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// 插入表尾,表为空创建bool RedisManager::rPushXList(PRedisContext& pRD, const std::string& key, std::string& value){ RedisCmdTimeTesting cTime; redisReply* reply = redisCommand(pRD, "RPUSHX %s %s", key.c_str(), value.c_str()); cTime.Log(pRD, "RPUSHXList RPUSHX %s %s ! reply:%u", key.c_str(), value.c_str(), reply); if (reply) { freeReplyObject(reply); return true; } log(Warn, "RPUSHXList: reply is NULL! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// 插入多个值到表头, 先插入数据在表尾bool RedisManager::lPushAnyList(PRedisContext& pRD, const std::string& key, vector<std::string>& values){ if (values.empty()) { return true; } string command(""); for (uint32_t i = 0; i < values.size(); ++i) { command += " " + values[i]; } RedisCmdTimeTesting cTime; redisReply* reply = redisCommand(pRD, "LPUSH %s %s", key.c_str(), command.c_str()); cTime.Log(pRD, "LPUSHList LPUSH %s %s ! reply:%u", key.c_str(), command.c_str(), reply); if (reply) { freeReplyObject(reply); return true; } log(Warn, "LPUSHList: reply is NULL! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// 插入多个值到表尾, 先插入数据在表头bool RedisManager::rPushAnyList(PRedisContext& pRD, const std::string& key, vector<std::string>& values){ if (values.empty()) { return true; } string command(""); for (uint32_t i = 0; i < values.size(); ++i) { command += " " + values[i]; } RedisCmdTimeTesting cTime; redisReply* reply = redisCommand(pRD, "RPUSH %s %s", key.c_str(), command.c_str()); cTime.Log(pRD, "RPUSHList RPUSH %s %s ! reply:%u", key.c_str(), command.c_str(), reply); if (reply) { freeReplyObject(reply); return true; } log(Warn, "RPUSHList: reply is NULL! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// 插入表头并获取长度bool RedisManager::lPushGetLen(PRedisContext& pRD, const std::string& key, std::string& value, uint32_t& len){ len = 0; RedisCmdTimeTesting cTime; redisReply* reply = redisCommand(pRD, "LPUSH %s %s", key.c_str(), value.c_str()); cTime.Log(pRD, "lPushGetLen LPUSH %s %s reply %u", key.c_str(), value.c_str(), reply); if (reply) { if (reply->type == REDIS_REPLY_INTEGER) { len = reply->integer; freeReplyObject(reply); return true; } else { log(Error, "lPushGetLen: reply is not INTEGER. reply->type:%u", reply->type); freeReplyObject(reply); return false; } } log(Warn, "lPushGetLen: reply is NULL! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// 插入表尾并获取长度bool RedisManager::rPushGetLen(PRedisContext& pRD, const std::string& key, std::string& value, uint32_t& len){ len = 0; RedisCmdTimeTesting cTime; redisReply* reply = redisCommand(pRD, "RPUSH %s %s", key.c_str(), value.c_str()); cTime.Log(pRD, "rPushGetLen RPUSH %s %s reply %u", key.c_str(), value.c_str(), reply); if (reply) { if (reply->type == REDIS_REPLY_INTEGER) { len = reply->integer; freeReplyObject(reply); return true; } else { log(Error, "rPushGetLen: reply is not INTEGER. reply->type:%u", reply->type); freeReplyObject(reply); return false; } } log(Warn, "rPushGetLen: reply is NULL! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// 插入单个字符列到list尾部,如"a b c"bool RedisManager::rPushListBit(PRedisContext& pRD, const std::string& key, std::string& binMem){ RedisCmdTimeTesting cTime; redisReply* reply = redisCommand(pRD, "RPUSH %s %b", key.c_str(), binMem.c_str(), binMem.size()); cTime.Log(pRD, "rPushListBit RPUSH %s ! size:%d,reply:%u", key.c_str(), binMem.size(), reply); if (reply) { if (REDIS_REPLY_INTEGER == reply->type) { freeReplyObject(reply); return true; } else if (REDIS_REPLY_ERROR == reply->type) { log(Error, "RPUSH return error, list name: %u", key.c_str()); } else { log(Error, "Not expected reply type received for RPUSH: %u", reply->type); } freeReplyObject(reply); return false; } log(Warn, "RPUSHList: reply is NULL! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// 移除字符列bool RedisManager::lPopListBit(PRedisContext& pRD, const std::string& key, std::string& binMem, bool& keyExist){ keyExist = false; RedisCmdTimeTesting cTime; redisReply* reply = redisCommand(pRD, "LPOP %s", key.c_str()); cTime.Log(pRD, "lPopListBit LPOP %s ! reply:%u", key.c_str(), reply); if (reply) { if (reply->type == REDIS_REPLY_STRING) { binMem.assign(reply->str, reply->len); keyExist = true; freeReplyObject(reply); return true; } else if (reply->type == REDIS_REPLY_NIL) { // 值不存在 freeReplyObject(reply); return true; } freeReplyObject(reply); return false; } log(Warn, "lPopListBit: reply is NULL! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// 移除表尾的元素bool RedisManager::rPopList(PRedisContext& pRD, const std::string& key, std::string& value, bool& keyExist){ keyExist = false; RedisCmdTimeTesting cTime; redisReply* reply = redisCommand(pRD, "RPOP %s", key.c_str()); cTime.Log(pRD, "rPopList RPOP %s ! reply:%u", key.c_str(), reply); if (reply) { if (reply->type == REDIS_REPLY_STRING) { value.assign(reply->str, reply->len); keyExist = true; freeReplyObject(reply); return true; } else if (reply->type == REDIS_REPLY_NIL) { // 值不存在 freeReplyObject(reply); return true; } freeReplyObject(reply); return false; } log(Warn, "rPopList: reply is NULL! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// 移除表头的元素bool RedisManager::lPopList(PRedisContext& pRD, const std::string& key, std::string& value, bool& keyExist){ keyExist = false; RedisCmdTimeTesting cTime; redisReply* reply = redisCommand(pRD, "LPOP %s", key.c_str()); cTime.Log(pRD, "lPopList LPOP %s ! reply:%u", key.c_str(), reply); if (reply) { if (reply->type == REDIS_REPLY_STRING) { value.assign(reply->str, reply->len); keyExist = true; freeReplyObject(reply); return true; } else if (reply->type == REDIS_REPLY_NIL) { // 值不存在 freeReplyObject(reply); return true; } freeReplyObject(reply); return false; } log(Warn, "lPopList: reply is NULL! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// 移除与value值相同的元素,count为移除个数(正数表示从前到后移除n个,负数表示从后往前移除n个,0表示移除所有)bool RedisManager::lremList(PRedisContext& pRD, const std::string& key, std::string& value, std::string count){ RedisCmdTimeTesting cTime; redisReply* reply = redisCommand(pRD, "LREM %s %s %s", key.c_str(), count.c_str(), value.c_str()); cTime.Log(pRD, "lremList LREM %s %s %s ! reply:%u", key.c_str(), count.c_str(), value.c_str(), reply); if (reply) { freeReplyObject(reply); return true; } log(Warn, "lremList: reply is NULL! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// 返回指定区域内的元素列表bool RedisManager::lrangeList(PRedisContext& pRD, const std::string& key, std::vector<std::string>& result, uint32_t startPos, uint32_t endPos){ RedisCmdTimeTesting cTime; redisReply* reply = redisCommand(pRD, "LRANGE %s %s %s", key.c_str(), ws::toString(startPos).c_str(), ws::toString(endPos).c_str()); cTime.Log(pRD, "lrangeList LRANGE %s %s %s ! reply:%u", key.c_str(), ws::toString(startPos).c_str(), ws::toString(endPos).c_str(), reply); if (reply) { if (reply->type == REDIS_REPLY_ARRAY) { for (unsigned int j = 0; j < reply->elements; j++) { result.push_back(reply->element[j]->str); } } freeReplyObject(reply); return true; } log(Warn, "lrangeList: reply is NULL! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}//--- hash// 设置hash值bool RedisManager::setHashValue(PRedisContext& pRD, const std::string& key, std::string field, std::string strValue){ RedisCmdTimeTesting cTime; redisReply* reply = redisCommand(pRD, "HSET %s %s %s", key.c_str(), field.c_str(), strValue.c_str()); cTime.Log(pRD, "setHashValue HSET %s %s %s ! reply:%u", key.c_str(), field.c_str(), strValue.c_str(), reply); if (reply) { freeReplyObject(reply); return true; } log(Warn, "setHashValue: reply is NULL! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// 获取hash值bool RedisManager::getHashValue(PRedisContext& pRD, const std::string& key, std::string field, std::string& strValue){ RedisCmdTimeTesting cTime; redisReply* reply = redisCommand(pRD, "HGET %s %s", key.c_str(), field.c_str()); cTime.Log(pRD, "getHashValue HGET %s %s ! reply:%u", key.c_str(), field.c_str(), reply); if (reply) { if (reply->type == REDIS_REPLY_STRING) { strValue.assign(reply->str, reply->len); freeReplyObject(reply); return true; } else { log(Error, "getHashValue: reply is not STRING. reply->type:%u", reply->type); freeReplyObject(reply); return false; } } log(Warn, "getHashValue: SMEMBERS reply is NULL! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// 设置多个值bool RedisManager::setAnyHashValue(PRedisContext& pRD, const std::string& key, map<std::string, std::string>& values){ std::vector<const char *> argv(values.size() * 2 + 2); std::vector<size_t> argvlen(values.size() * 2 + 2); uint32_t j = 0; static char msethash[] = "HMSET"; argv[j] = msethash; argvlen[j] = sizeof(msethash) - 1; ++j; argv[j] = key.c_str(); argvlen[j] = key.size(); ++j; for (std::map<string, string>::const_iterator i = values.begin(); i != values.end(); i++, j++) { argv[j] = i->first.c_str(); argvlen[j] = i->first.size(); j++; argv[j] = i->second.c_str(); argvlen[j] = i->second.size(); } RedisCmdTimeTesting cTime; redisReply* reply = (redisReply*)redisCommandArgv(pRD, argv.size(), &(argv[0]), &(argvlen[0])); cTime.Log(pRD, "setAnyHashValue HMSET size %d ! reply:%u", argv.size(), reply); if (reply) { if (REDIS_REPLY_STATUS == reply->type) { if (strcmp(reply->str, "OK") == 0) { freeReplyObject(reply); return true; } else { log(Error, "setAnyHashValue: reply is not INTEGER. reply->type:%u, reply->str: %s",reply->type, reply->str); freeReplyObject(reply); return false; } } else { log(Error, "setAnyHashValue: return error type"); freeReplyObject(reply); return false; } } log(Warn, "setAnyHashValue: reply is NULL! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// 获取多个值bool RedisManager::getAnyHashValue(PRedisContext& pRD, const std::string& key, vector<std::string>& fields, map<std::string, std::string>& values){ stringstream cmd; cmd << "HMGET " << key; for (vector<string>::iterator it = fields.begin(); it != fields.end(); ++it) { cmd << " " << *it; } RedisCmdTimeTesting cTime; redisReply* reply = redisCommand(pRD, cmd.str().c_str()); cTime.Log(pRD, "getAnyHashValue %s ! reply %u", cmd.str().c_str(), reply); if (reply) { if (REDIS_REPLY_ARRAY == reply->type) { for (unsigned int j = 0; j < reply->elements; ++j) { if (REDIS_REPLY_NIL != reply->element[j]->type) { values[fields[j]] = reply->element[j]->str; } else { values[fields[j]] = ""; // 获取失败 } } freeReplyObject(reply); return true; } else { log(Error, "getAnyHashValue: reply is not ARRAY. reply->type:%u", reply->type); freeReplyObject(reply); return false; } } log(Warn, "getAnyHashValue: HMGET reply is NULL! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// 获取所有hash值对bool RedisManager::getHashAllValue(PRedisContext& pRD, const std::string& key, map<std::string, std::string>& valueMap){ string strField; RedisCmdTimeTesting cTime; redisReply* reply = redisCommand(pRD, "HGETALL %s", key.c_str()); cTime.Log(pRD, "getHashAllBinValue HGETALL %s ! reply:%u", key.c_str(), reply); if (reply) { if (reply->type == REDIS_REPLY_ARRAY) { for (unsigned int j = 0; j < reply->elements; ++j) { strField = reply->element[j]->str; if (j < reply->elements) { j++; valueMap[strField].assign(reply->element[j]->str, reply->element[j]->len); } } freeReplyObject(reply); return true; } else { log(Error, "getHashAllValue: reply is not ARRAY. reply->type:%u", reply->type); freeReplyObject(reply); return false; } } log(Warn, "getHashAllValue: SMEMBERS reply is NULL! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// 获取目标key的所有fieldbool RedisManager::getHashAllFields(PRedisContext& pRD, const std::string& key, vector<std::string>& fields){ RedisCmdTimeTesting cTime; redisReply* reply = redisCommand(pRD, "HKEYS %s", key.c_str()); cTime.Log(pRD, "getHashAllFields HKEYS %s ! reply:%u", key.c_str(), reply); if (reply) { if (reply->type == REDIS_REPLY_ARRAY) { for (unsigned int j = 0; j < reply->elements; ++j) { fields.push_back(reply->element[j]->str); } freeReplyObject(reply); return true; } else { log(Error, "getHashAllFields: reply is not ARRAY. reply->type:%u", reply->type); freeReplyObject(reply); return false; } } log(Warn, "getHashAllFields: HKEYS reply is NULL! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// (二进制)设置hash值bool RedisManager::setHashValueBit(PRedisContext& pRD, const std::string& key, std::string field, std::string binValue){ RedisCmdTimeTesting cTime; redisReply* reply = redisCommand(pRD, "HSET %s %s %b", key.c_str(), field.c_str(), binValue.c_str(), binValue.size()); cTime.Log(pRD, "setHashValueBit HSET %s %s size %d ! reply:%u", key.c_str(), field.c_str(), binValue.size(), reply); if (reply) { freeReplyObject(reply); return true; } log(Warn, "setHashValueBit: reply is NULL! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// (二进制)获取所有键值对bool RedisManager::getAnyHashValueBit(PRedisContext& pRD, const std::string& key, map<std::string, std::string>& valueMap){ RedisCmdTimeTesting cTime; redisReply* reply = redisCommand(pRD, "HGETALL %s", key.c_str()); cTime.Log(pRD, "getAnyHashValueBit HGETALL %s reply %u", key.c_str(), reply); if (reply) { if (reply->type == REDIS_REPLY_ARRAY) { for (unsigned int j = 0; j < reply->elements; ++j) { std::string strField = reply->element[j]->str; if (j < reply->elements) { j++; valueMap[strField].assign(reply->element[j]->str, reply->element[j]->len); } } freeReplyObject(reply); return true; } else { log(Error, "getAnyHashValueBit: reply is not ARRAY. reply->type:%u", reply->type); freeReplyObject(reply); return false; } } log(Warn, "getAnyHashValueBit: SMEMBERS reply is NULL ! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// 删除hash值bool RedisManager::delHashValue(PRedisContext& pRD, const std::string& key, std::string field){ RedisCmdTimeTesting cTime; redisReply* reply = redisCommand(pRD, "HDEL %s %s ", key.c_str(), field.c_str()); cTime.Log(pRD, "delHashValue HDEL %s %s ! reply:%u", key.c_str(), field.c_str(), reply); if (reply) { freeReplyObject(reply); return true; } log(Warn, "delHashValue: reply is NULL! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// 删除多个hash值bool RedisManager::delHashValue(PRedisContext& pRD, const std::string& key, const set<std::string> & fields, int64_t& rmCount){ stringstream cmd; cmd << "HDEL " << key <<" "; set<std::string>::iterator it = fields.begin(); for (; it != fields.end(); ++it) { cmd << *it << " "; } RedisCmdTimeTesting cTime; redisReply* reply = redisCommand(pRD, cmd.str().c_str()); cTime.Log(pRD, "%s ! reply:%u", cmd.str().c_str(), reply); if (reply) { if (REDIS_REPLY_INTEGER == reply->type && rmCount != 0) { rmCount = reply->integer; } else { log(Error, "delHashValue: Unexpected reply type %d", reply->type); } freeReplyObject(reply); return true; } log(Warn, "delHashValue: reply is NULL! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// 判断是不是hash成员bool RedisManager::isMemInHash(PRedisContext& pRD, const std::string& key, std::string field, bool& isMem){ isMem = false; RedisCmdTimeTesting cTime; redisReply* reply = redisCommand(pRD, "HEXISTS %s %s", key.c_str(), field.c_str()); cTime.Log( pRD, "isMemInHash HEXISTS %s %s ! reply:%u", key.c_str(), field.c_str(), reply ); if ( reply ) { if ( reply->type == REDIS_REPLY_INTEGER ) { if ( reply->integer == 1) { isMem = true; freeReplyObject(reply); return true; } else if ( reply->integer == 0) { log( Debug, "isMemInHash: Mem %s not in Hash:%s", field.c_str(), key.c_str() ); } else { log(Error, "isMemInHash: unexpected integer:%lld", reply->integer); } } else { log( Error, "isMemInHash: unexpected reply type:%u", reply->type ); } freeReplyObject(reply); return false; } log(Warn, "isMemInHash: HEXISTS reply is NULL! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// 在原始值上增加指定值bool RedisManager::incrHashValue(PRedisContext& pRD, const std::string& key, std::string field, std::string value){ RedisCmdTimeTesting cTime; redisReply* reply = redisCommand(pRD, "HINCRBY %s %s %s", key.c_str(), field.c_str(), value.c_str()); cTime.Log(pRD, "incrHashValue HINCRBY %s %s %s ! reply:%u", key.c_str(), field.c_str(), value.c_str(), reply); if (reply) { freeReplyObject(reply); return true; } log(Warn, "incrHashValue: reply is NULL! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// (事务) 设置hash值bool RedisManager::setHashValue_T(PRedisContext& pRD, const std::string& key, map<std::string, std::string>& fieldValue){ std::vector<const char *> argv(fieldValue.size() * 2 + 2); std::vector<size_t> argvlen(fieldValue.size() * 2 + 2); uint32_t j = 0; static char msethash[] = "HMSET"; argv[j] = msethash; argvlen[j] = sizeof(msethash) - 1; ++j; argv[j] = key.c_str(); argvlen[j] = key.size(); ++j; for (std::map<string, string>::const_iterator i = fieldValue.begin(); i != fieldValue.end(); i++, j++) { argv[j] = i->first.c_str(); argvlen[j] = i->first.size(); j++; argv[j] = i->second.c_str(); argvlen[j] = i->second.size(); } RedisCmdTimeTesting cTime; redisReply* reply = (redisReply*)redisCommandArgv(pRD, argv.size(), &(argv[0]), &(argvlen[0])); cTime.Log(pRD, "setHashValue_T HMSET size %d ! reply:%u", argv.size(), reply); if (reply) { if (REDIS_REPLY_STATUS == reply->type) { if (strcmp(reply->str, "QUEUED") == 0) { freeReplyObject(reply); return true; } else { log(Error, "setHashValue_T: reply is not INTEGER. reply->type:%u, reply->str: %s",reply->type, reply->str); freeReplyObject(reply); return false; } } else { log(Error, "setHashValue_T return error type"); freeReplyObject(reply); return false; } } log(Warn, "setHashValue_T: reply is NULL! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}//--- set// 判断是不是set成员bool RedisManager::isMemInSet(PRedisContext& pRD, const std::string& key, std::string& value, bool& isMem){ isMem = false; RedisCmdTimeTesting cTime; redisReply* reply = redisCommand(pRD, "SISMEMBER %s %s", key.c_str(), value.c_str()); cTime.Log(pRD, "isMemInSet SISMEMBER %s %s ! reply:%u", key.c_str(), value.c_str(), reply); if (reply) { if (reply->type == REDIS_REPLY_INTEGER) { if (reply->integer == 1) { isMem = true; freeReplyObject(reply); return true; } else if (reply->integer == 0) { log(Debug, "isMemInSet: Mem %s not in set:%s", value.c_str(), key.c_str()); } else { log(Error, "isMemInSet: unexpected integer:%lld", reply->integer); } } else { log(Error, "isMemInSet: unexpected reply type:%u", reply->type); } freeReplyObject(reply); return false; } log(Warn, "isMemInSet: SISMEMBER reply is NULL! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// 获取set元素个数bool RedisManager::getSetCount(PRedisContext& pRD, const std::string& key, uint32_t& count, bool& keyExist){ keyExist = false; RedisCmdTimeTesting cTime; redisReply* reply = redisCommand(pRD, "SCARD %b", key.c_str(), key.size()); cTime.Log(pRD, "getSetCount SCARD key size %d ! reply:%u", key.size(), reply); if (reply) { if (reply->type == REDIS_REPLY_STRING) { count = strtoul(reply->str, 0, 0); keyExist = true; freeReplyObject(reply); return true; } else if (reply->type == REDIS_REPLY_INTEGER) { count = reply->integer; keyExist = true; freeReplyObject(reply); return true; } log(Error, "getSetCount: SACRD reply is unexpected!"); freeReplyObject(reply); return false; } log(Warn, "getSetCount: reply is NULL! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// 添加元素,已经存在的元素被忽略bool RedisManager::setSetValue(PRedisContext& pRD, const std::string& key, std::string& value){ RedisCmdTimeTesting cTime; redisReply* reply = redisCommand(pRD, "SADD %s %s", key.c_str(), value.c_str()); cTime.Log(pRD, "setSetValue SADD %s %s reply %u", key.c_str(), value.c_str(), reply); if (reply) { if (reply->type != REDIS_REPLY_INTEGER) { log(Error, "setSetValue: reply is not INTEGER. reply->type:%u", reply->type); freeReplyObject(reply); return false; } freeReplyObject(reply); return true; } log(Warn, "setSetValue: reply is NULL! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// 添加多个值,已经存在的元素被忽略bool RedisManager::setAnySetValue(PRedisContext& pRD, const std::string& key, set<std::string>& value){ std::vector<const char *> argv(value.size() + 2); std::vector<size_t> argvlen(value.size() + 2); uint32_t j = 0; static char sremcmd[] = "SADD"; argv[j] = sremcmd; argvlen[j] = sizeof(sremcmd) - 1; ++j; argv[j] = key.c_str(); argvlen[j] = key.size(); ++j; for (std::set<string>::const_iterator i = value.begin(); i != value.end(); ++i, ++j) { argv[j] = i->c_str(); argvlen[j] = i->size(); } RedisCmdTimeTesting cTime; redisReply* reply = (redisReply*)redisCommandArgv(pRD, argv.size(), &(argv[0]), &(argvlen[0])); cTime.Log(pRD, "setAnySetValue SADD size %d reply %u", argv.size(), reply); if (reply) { if (reply->type == REDIS_REPLY_INTEGER) { freeReplyObject(reply); return true; } else { freeReplyObject(reply); log(Error, "setAnySetValue: reply is not INTEGER. reply->type:%u", reply->type); return false; } } log(Warn, "setAnySetValue: reply is NULL! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// 获取set集合bool RedisManager::getAnySetValue(PRedisContext& pRD, const std::string& key, set<std::string>& value){ RedisCmdTimeTesting cTime; redisReply* reply = redisCommand(pRD, "SMEMBERS %s", key.c_str()); cTime.Log(pRD, "getAnySetValue str SMEMBERS %s size %d ! reply:%u", key.c_str(), value.size(), reply); if (reply) { if (reply->type == REDIS_REPLY_ARRAY) { for (unsigned int j = 0; j < reply->elements; ++j) { value.insert(reply->element[j]->str); } freeReplyObject(reply); return true; } else { log(Error, "getAnySetValue: reply is not ARRAY. reply->type:%u", reply->type); freeReplyObject(reply); return false; } } log(Warn, "getAnySetValue: SMEMBERS reply is NULL! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// 移除集合中的元素bool RedisManager::remSetValue(PRedisContext& pRD, const std::string& key, std::string& value){ RedisCmdTimeTesting cTime; redisReply* reply = redisCommand(pRD, "SREM %s %s", key.c_str(), value.c_str()); cTime.Log(pRD, "remSetValue SREM %s %s ! reply:%u", key.c_str(), value.c_str(), reply); if (reply) { freeReplyObject(reply); return true; } log(Warn, "remSetValue: reply is NULL! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// 移除多个指定元素bool RedisManager::remAnySetValue(PRedisContext& pRD, const std::string &key, const std::set<std::string> &value){ std::vector<const char *> argv(value.size() + 2); std::vector<size_t> argvlen(value.size() + 2); uint32_t j = 0; static char sremcmd[] = "SREM"; argv[j] = sremcmd; argvlen[j] = sizeof(sremcmd) - 1; ++j; argv[j] = key.c_str(); argvlen[j] = key.size(); ++j; for (std::set<string>::const_iterator i = value.begin(); i != value.end(); ++i, ++j) { argv[j] = i->c_str(); argvlen[j] = i->size(); } RedisCmdTimeTesting cTime; redisReply* reply = (redisReply*)redisCommandArgv(pRD, argv.size(), &(argv[0]), &(argvlen[0])); cTime.Log(pRD, "remAnySetValue SREM size %d ! reply:%u", argv.size(), reply); if (reply) { if (reply->type == REDIS_REPLY_INTEGER) { freeReplyObject(reply); return true; } else { log(Error, "remAnySetValue: reply is not INTEGER. reply->type:%u", reply->type); freeReplyObject(reply); return false; } } log(Warn, "remAnySetValue: reply is NULL! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// 获取多个key的并集bool RedisManager::getSetSunion(PRedisContext& pRD, set<std::string>& keys, set<std::string>& value){ ostringstream cmdStr; cmdStr << "SUNION"; for (set<std::string>::iterator it = keys.begin(); it != keys.end(); ++it) { cmdStr << " " << *it; } RedisCmdTimeTesting cTime; redisReply* reply = redisCommand(pRD, cmdStr.str().c_str()); cTime.Log(pRD, "getSetSunion %s ! reply:%u", cmdStr.str().c_str(), reply); if (reply) { if (reply->type == REDIS_REPLY_ARRAY) { for (unsigned int j = 0; j < reply->elements; ++j) { value.insert(reply->element[j]->str); } freeReplyObject(reply); return true; } else { log(Error, "getSetSunion: reply is not ARRAY. reply->type:%u", reply->type); freeReplyObject(reply); return false; } } log(Warn, "getSetSunion: SUNION reply is NULL! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// 获取多个key的差集bool RedisManager::getSetSdiff(PRedisContext& pRD, set<std::string>& keys, set<std::string>& value){ ostringstream cmdStr; cmdStr << "SDIFF"; for (set<std::string>::iterator it = keys.begin(); it != keys.end(); ++it) { cmdStr << " " << *it; } RedisCmdTimeTesting cTime; redisReply* reply = redisCommand(pRD, cmdStr.str().c_str()); cTime.Log(pRD, "getSetSdiff %s ! reply:%u", cmdStr.str().c_str(), reply); if (reply) { if (reply->type == REDIS_REPLY_ARRAY) { for (unsigned int j = 0; j < reply->elements; ++j) { value.insert(reply->element[j]->str); } freeReplyObject(reply); return true; } else { log(Error, "getSetSdiff: reply is not ARRAY. reply->type:%u", reply->type); freeReplyObject(reply); return false; } } log(Warn, "getSetSdiff: SUNION reply is NULL! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// 获取多个key的交集bool RedisManager::getSetSinter(PRedisContext& pRD, set<std::string>& keys, set<std::string>& value){ ostringstream cmdStr; cmdStr << "SINTER"; for (set<std::string>::iterator it = keys.begin(); it != keys.end(); ++it) { cmdStr << " " << *it; } RedisCmdTimeTesting cTime; redisReply* reply = redisCommand(pRD, cmdStr.str().c_str()); cTime.Log(pRD, "getSetSinter %s ! reply:%u", cmdStr.str().c_str(), reply); if (reply) { if (reply->type == REDIS_REPLY_ARRAY) { for (unsigned int j = 0; j < reply->elements; ++j) { value.insert(reply->element[j]->str); } freeReplyObject(reply); return true; } else { log(Error, "getSetSinter: reply is not ARRAY. reply->type:%u", reply->type); freeReplyObject(reply); return false; } } log(Warn, "getSetSinter: SUNION reply is NULL! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// (事务)添加集合元素bool RedisManager::setSetValue_T(PRedisContext& pRD, const std::string& key, std::string& value){ RedisCmdTimeTesting cTime; redisReply* reply = redisCommand(pRD, "SADD %s %s", key.c_str(), value.c_str()); cTime.Log(pRD, "addSetValue_T SADD %s %s ! reply:%u", key.c_str(), value.c_str(), reply); if (reply) { if (REDIS_REPLY_STATUS == reply->type) { if (strcmp(reply->str, "QUEUED") == 0) { freeReplyObject(reply); return true; } else { log(Error, "setSetValue_T in transaction return failure"); } } else { log(Error, "setSetValue_T Wrong reply type received! Type: %d, key: %s", reply->type, key.c_str()); } freeReplyObject(reply); return false; } log(Warn, "setSetValue_T: reply is NULL! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// --- sortset// 检查目标是不是sortset的资源bool RedisManager::isMemInSortedSet(PRedisContext& pRD, const std::string& key, const std::string& member, bool& isMem){ isMem = false; ostringstream cmdStr; cmdStr << "ZSCORE " << key << " " << member; RedisCmdTimeTesting cTime; redisReply *reply = redisCommand(pRD, cmdStr.str().c_str()); cTime.Log(pRD, "isMemInSortedSet %s reply %u", cmdStr.str().c_str(), reply); if (reply) { if (REDIS_REPLY_NIL == reply->type) { isMem = true; freeReplyObject(reply); return true; } else if (REDIS_REPLY_STRING == reply->type) { isMem = true; freeReplyObject(reply); return true; } else { log(Error, "isMemInSortedSet Wrong reply received. Type: %d,. sortedSet: %s, member: %s", key.c_str(), member.c_str()); } freeReplyObject(reply); return false; } log(Warn, "isMemInSortedSet failed! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// 获取资源个数bool RedisManager::getCountSortedSet(PRedisContext& pRD, const std::string& key, uint32_t& totalCount){ ostringstream cmdStr; cmdStr << "ZCARD " << key; RedisCmdTimeTesting cTime; redisReply *reply = redisCommand(pRD, cmdStr.str().c_str()); cTime.Log(pRD, "getCountSortedSet %s ! reply:%u", cmdStr.str().c_str(), reply); if (reply) { if (REDIS_REPLY_INTEGER == reply->type) { freeReplyObject(reply); return true; } else { log(Warn, "getCountSortedSet Wrong reply received. Type: %d, key: %s", reply->type, key.c_str()); } freeReplyObject(reply); return false; } log(Warn, "getCountSortedSet failed! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// 添加元素到keybool RedisManager::setSortSet(PRedisContext& pRD, const std::string& key, std::string& mem, const uint64_t& score){ ostringstream cmdStr; cmdStr << "ZADD " << key << " " << score << " %s"; RedisCmdTimeTesting cTime; redisReply *reply = redisCommand(pRD, cmdStr.str().c_str(), mem.c_str()); cTime.Log(pRD, "setSortSet key %s, mem %s, score %u ! reply:%u", key.c_str(), mem.c_str(), score, reply); if (reply) { if (REDIS_REPLY_INTEGER == reply->type) { freeReplyObject(reply); return true; } else if (REDIS_REPLY_ERROR == reply->type) { log(Error, "setSortSet return error, sortedSet: %s, score: %u", key.c_str(), score); } else { log(Error, "setSortSet Not expected reply type received for ZADD: %u", reply->type); } freeReplyObject(reply); return false; } log(Warn, "setSortSet failed! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// 添加多个元素到keybool RedisManager::setAnySortSet(PRedisContext& pRD, const std::string& key, const map<std::string, std::string>& scores){ ostringstream cmdStr; cmdStr << "ZADD " << key << " "; for (map<string, string>::const_iterator it = scores.begin(); it != scores.end(); ++it) { if (it->first != "" && it->second != "") { cmdStr << it->second << " " << it->first << " "; } else { log(Warn, "setAnySortSet: Empty mem or score. mem: %s, score: %s", it->first.c_str(), it->second.c_str()); } } RedisCmdTimeTesting cTime; redisReply *reply = redisCommand(pRD, cmdStr.str().c_str()); cTime.Log(pRD, "setAnySortSet key %s scores size %d ! reply:%u", key.c_str(), scores.size(), reply); if (reply) { if (REDIS_REPLY_INTEGER == reply->type) { freeReplyObject(reply); return true; } else if (REDIS_REPLY_ERROR == reply->type) { log(Error, "setAnySortSet return error, sortedSet: %s, size: %u", key.c_str(), scores.size()); } else { log(Error, "setAnySortSet Not expected reply type received for ZADD: %u", reply->type); } freeReplyObject(reply); return false; } log(Warn, "setAnySortSet failed! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// 给指定元素增加incrScore的值bool RedisManager::incrSortSet(PRedisContext& pRD, const std::string& key, const std::string& mem, const uint32_t& incrScore){ ostringstream cmdStr; cmdStr << "ZINCRBY " << key << " " << incrScore << " %s"; RedisCmdTimeTesting cTime; redisReply *reply = redisCommand(pRD, cmdStr.str().c_str(), mem.c_str()); cTime.Log(pRD, "incrSortSet key %s incrScore %u ! reply:%u", key.c_str(), incrScore, reply); if (reply) { if (REDIS_REPLY_STRING == reply->type) { freeReplyObject(reply); return true; } else if (REDIS_REPLY_ERROR == reply->type) { log(Error, "incrSortSet return error, sortedSet: %s, incrScore: %u, member: %s", key.c_str(), incrScore, mem.c_str()); } else { log(Error, "incrSortSet Not expected reply type received for ZINCRBY: %u", reply->type); } freeReplyObject(reply); return false; } log(Warn, "incrSortSet failed! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}//减少资源的排序值bool RedisManager::decrScore(PRedisContext& pRD, const std::string& key, std::string& mem, const uint32_t& decrScore){ ostringstream cmdStr; cmdStr << "ZINCRBY " << key << " -" << decrScore << " %s"; RedisCmdTimeTesting cTime; redisReply *reply = redisCommand(pRD, cmdStr.str().c_str(), mem.c_str()); cTime.Log(pRD, "decrScore key %s ! reply:%u", key.c_str(), reply); if (reply) { if (REDIS_REPLY_STRING == reply->type) { freeReplyObject(reply); return true; } else if (REDIS_REPLY_ERROR == reply->type) { log(Warn, "decrScore return error, sortedSet: %s, decrScore: %u, member: %s", key.c_str(), decrScore, mem.c_str()); } else { log(Warn, "decrScore Not expected reply type received for ZINCRBY: %u", reply->type); } freeReplyObject(reply); return false; } log(Warn, "decrScore failed! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// 删除指定资源bool RedisManager::remMemFromSortedSet(PRedisContext& pRD, const std::string& key, const std::string& mem){ ostringstream cmdStr; cmdStr << "ZREM " << key << " %s"; RedisCmdTimeTesting cTime; redisReply *reply = redisCommand(pRD, cmdStr.str().c_str(), mem.c_str()); cTime.Log(pRD, "remMemFromSortedSet %s ! reply:%u", cmdStr.str().c_str(), reply); if (reply) { if (REDIS_REPLY_INTEGER == reply->type) { freeReplyObject(reply); return true; } else { log(Warn, "remMemFromSortedSet Wrong reply received. Type: %d, key: %s, mem: %s", reply->type, key.c_str(), mem.c_str()); } freeReplyObject(reply); return false; } log(Warn, "remMemFromSortedSet failed! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// 删除资源排序值域的资源bool RedisManager::remRangeByScore(PRedisContext& pRD, const std::string& key, const uint32_t& min, const uint32_t& max){ if (min > max) { log(Warn, "min %u greater than max %u", min, max); return false; } ostringstream cmdStr; cmdStr << "ZREMRANGEBYSCORE " << key << " " << min << " " << max; RedisCmdTimeTesting cTime; redisReply *reply = redisCommand(pRD, cmdStr.str().c_str()); cTime.Log(pRD, "remRangeByScore %s ! reply:%u", key.c_str(), reply); if (reply) { if (REDIS_REPLY_INTEGER == reply->type) { freeReplyObject(reply); return true; } else { log(Warn, "remRangeByScore Wrong reply received. Type: %d, key: %s, min: %u, max: %u", reply->type, key.c_str(), min, max); } freeReplyObject(reply); return false; } log(Warn, "remRangeByScore failed! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// 返回指定资源的排序值bool RedisManager::getScoreByMember(PRedisContext& pRD, const std::string& key, const std::string& member, uint32_t& score){ score = 0; ostringstream cmdStr; cmdStr << "ZSCORE " << key << " " << member; RedisCmdTimeTesting cTime; redisReply *reply = redisCommand(pRD, cmdStr.str().c_str()); cTime.Log(pRD, "getScoreByMember %s ! reply:%u", cmdStr.str().c_str(), reply); if (reply) { if (REDIS_REPLY_NIL == reply->type) { freeReplyObject(reply); return true; } else if (REDIS_REPLY_STRING == reply->type) { score = strtoul(reply->str, 0, 0); freeReplyObject(reply); return true; } else { log(Error, "getScoreByMember Wrong reply received. Type: %d,. sortedSet: %s, member: %s", key.c_str(), member.c_str()); } freeReplyObject(reply); return false; } log(Warn, "getScoreByMember failed! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// 获取资源的降序排名bool RedisManager::getDescRankByMember(PRedisContext& pRD, const std::string& key, const std::string& member, uint32_t& rank){ ostringstream cmdStr; cmdStr << "ZREVRANK " << key << " " << member; RedisCmdTimeTesting cTime; redisReply *reply = redisCommand(pRD, cmdStr.str().c_str()); cTime.Log(pRD, "getDescRankByMember %s ! reply:%u", cmdStr.str().c_str(), reply); if (reply) { if (REDIS_REPLY_NIL == reply->type) { rank = 0; freeReplyObject(reply); return true; } else if (REDIS_REPLY_INTEGER == reply->type) { rank = reply->integer; ++rank; freeReplyObject(reply); return true; } else { log(Warn, "getDescRankByMember Wrong reply received. Type: %d,. sortedSet: %s, member: %s", reply->type, key.c_str(), member.c_str()); } freeReplyObject(reply); return false; } log(Warn, "getDescRankByMember failed! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// 获取资源升序排名bool RedisManager::getAscRankByMember(PRedisContext& pRD, const std::string& key, const std::string& member, uint32_t& rank){ ostringstream cmdStr; cmdStr << "ZRANK " << key << " " << member; RedisCmdTimeTesting cTime; redisReply *reply = (redisReply*)redisCommand(pRD, cmdStr.str().c_str()); cTime.Log(pRD, "getAscRankByMember %s ! reply:%u", cmdStr.str().c_str(), reply); if (reply) { if (REDIS_REPLY_NIL == reply->type) { rank = 0; freeReplyObject(reply); return true; } else if (REDIS_REPLY_INTEGER == reply->type) { rank = reply->integer; ++rank; freeReplyObject(reply); return true; } else { log(Warn, "getAscRankByMember Wrong reply received. Type: %d,. sortedSet: %s, member: %s", reply->type, key.c_str(), member.c_str()); } freeReplyObject(reply); return false; } log(Warn, "getAscRankByMember failed! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// (二进制)给指定元素增加incrScore的值bool RedisManager::incrSortSetBit(PRedisContext& pRD, const std::string& key, std::string& mem, const uint32_t& incrScore){ ostringstream cmdStr; cmdStr << "ZINCRBY " << key << " " << incrScore << " %b"; RedisCmdTimeTesting cTime; redisReply *reply = redisCommand(pRD, cmdStr.str().c_str(), mem.c_str(), mem.size()); cTime.Log(pRD, "incrSortSetBit key %s incrScore %u ! reply:%u", key.c_str(), incrScore, reply); if (reply) { if (REDIS_REPLY_STRING == reply->type) { freeReplyObject(reply); return true; } else if (REDIS_REPLY_ERROR == reply->type) { log(Error, "incrSortSetBit return error, sortedSet: %s, incrScore: %u", key.c_str(), incrScore); } else { log(Error, "incrSortSetBit Not expected reply type received for ZINCRBY: %u", reply->type); } freeReplyObject(reply); return false; } log(Warn, "incrSortSetBit failed! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// 从大到小获取指定段的数据, 0 score 会被过滤掉bool RedisManager::getDescSortedData(PRedisContext& pRD, const std::string& key, const uint32_t& offset, const uint32_t& limit, std::vector<SortData>& datas){ uint32_t stopIndex = offset + limit - 1; ostringstream cmdStr; cmdStr << "ZREVRANGE " << key << " " << offset << " " << stopIndex << " WITHSCORES"; RedisCmdTimeTesting cTime; redisReply *reply = redisCommand(pRD, cmdStr.str().c_str()); cTime.Log(pRD, "getDescSortedData %s ! reply:%u", cmdStr.str().c_str(), reply); if (reply) { if (REDIS_REPLY_NIL == reply->type) { freeReplyObject(reply); return true; } else if (REDIS_REPLY_ARRAY == reply->type) { if (reply->elements > 0) { for (uint32_t i = 0; i < reply->elements - 1; ) { SortData data; data.m_score = reply->element[i++]->str; data.m_number = reply->element[i++]->str; //过滤掉<=0的score #if 0 if (ws::atou32(data.m_number.c_str()) > 0) { datas.push_back(data); } else { log(Info, "getDescSortedData Not accepted score: %d, id: %u", data.m_score.c_str(), data.m_number.c_str()); } #endif } } freeReplyObject(reply); return true; } else { log(Error, "getDescSortedData Wrong reply received. Type: %d, key: %s, offset: %u, limit: %u", reply->type, key.c_str(), offset, limit); } freeReplyObject(reply); return false; } log(Warn, "getDescSortedData failed! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// 从大到小获取指定段的数据, 0 score 不会被过滤掉bool RedisManager::getDescSortedAllData(PRedisContext& pRD, const std::string& key, const uint32_t& offset, const uint32_t& limit, std::vector<SortData>& datas){ uint32_t stopIndex = offset + limit - 1; ostringstream cmdStr; cmdStr << "ZREVRANGE " << key << " " << offset << " " << stopIndex << " WITHSCORES"; RedisCmdTimeTesting cTime; redisReply *reply = redisCommand(pRD, cmdStr.str().c_str()); cTime.Log(pRD, "getDescSortedAllData %s ! reply:%u", cmdStr.str().c_str(), reply); if (reply) { if (REDIS_REPLY_NIL == reply->type) { freeReplyObject(reply); return true; } else if (REDIS_REPLY_ARRAY == reply->type) { if (reply->elements > 0) { for (uint32_t i = 0; i < reply->elements - 1; ) { SortData data; data.m_score = reply->element[i++]->str; data.m_number = reply->element[i++]->str; datas.push_back(data); } } freeReplyObject(reply); return true; } else { log(Error, "getDescSortedAllData Wrong reply received. Type: %d, key: %s, offset: %u, limit: %u", reply->type, key.c_str(), offset, limit); } freeReplyObject(reply); return false; } log(Warn, "getDescSortedAllData failed! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// (升序)从小到大获取指定数据段的数据, 0 score 会被过滤掉bool RedisManager::getAscSortedData(PRedisContext& pRD, const string& key, const uint32_t& start, const uint32_t& end, std::vector<SortData> &datas){ ostringstream cmdStr; cmdStr << "ZRANGE " << key << " " << start << " " << end << " WITHSCORES"; RedisCmdTimeTesting cTime; redisReply *reply = redisCommand(pRD, cmdStr.str().c_str()); cTime.Log(pRD, "getAscSortedData %s ! reply:%u", cmdStr.str().c_str(), reply); if (reply) { if (REDIS_REPLY_NIL == reply->type) { freeReplyObject(reply); return true; } else if (REDIS_REPLY_ARRAY == reply->type) { if (reply->elements > 0) { for (uint32_t i = 0; i < reply->elements - 1; ) { SortData data; data.m_score = reply->element[i++]->str; data.m_number = reply->element[i++]->str; #if 0 //过滤掉<=0的score if (ws::atou32(data.m_number.c_str()) > 0) { datas.push_back(data); } else { log(Info, "getAscSortedData Not accepted score: %s, id: %s", data.m_score.c_str(), data.m_number.c_str()); } #endif } } freeReplyObject(reply); return true; } else { log(Error, "getAscSortedData Wrong reply received. Type: %d, key: %s, offset: %u, limit: %u", reply->type, key.c_str(), start, end); } freeReplyObject(reply); return false; } log(Warn, "getAscSortedData failed! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// (升序)从小到大获取指定数据段的数据, 0 score 不会被过滤掉bool RedisManager::getAscSortedAllData(PRedisContext& pRD, const std::string& key, const uint32_t& start, const uint32_t& end, std::vector<SortData>& datas){ ostringstream cmdStr; cmdStr << "ZRANGE " << key << " " << start << " " << end << " WITHSCORES"; RedisCmdTimeTesting cTime; redisReply *reply = redisCommand(pRD, cmdStr.str().c_str()); cTime.Log(pRD, "getAscSortedAllData %s ! reply:%u", cmdStr.str().c_str(), reply); if (reply) { if (REDIS_REPLY_NIL == reply->type) { freeReplyObject(reply); return true; } else if (REDIS_REPLY_ARRAY == reply->type) { if (reply->elements > 0) { for (uint32_t i = 0; i < reply->elements - 1; ) { SortData data; data.m_score = reply->element[i++]->str; data.m_number = reply->element[i++]->str; datas.push_back(data); } } freeReplyObject(reply); return true; } else { log(Error, "getAscSortedAllData Wrong reply received "); } freeReplyObject(reply); return false; } log(Warn, "getAscSortedAllData failed! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// (事务)添加元素bool RedisManager::setSortedSet_T(PRedisContext& pRD, const std::string& key, std::string& mem, const uint32_t& score){ //bool retCode = true; ostringstream cmdStr; cmdStr << "ZADD " << key << " " << score << " %s"; RedisCmdTimeTesting cTime; redisReply *reply = redisCommand(pRD, cmdStr.str().c_str(), mem.c_str(), mem.size()); cTime.Log(pRD, "setSortedSet_T ZADD key %s score %u size %d reply %u", key.c_str(), score, mem.size(), reply); if (reply) { if (REDIS_REPLY_STATUS == reply->type) { if (strcmp(reply->str, "QUEUED") == 0) { freeReplyObject(reply); return true; } else { log(Error, "setSortedSet_T in transaction return failure, key: %s", key.c_str()); } } else { log(Warn, "setSortedSet_T Wrong reply type received! Type: %d, key: %s", reply->type, key.c_str()); } freeReplyObject(reply); return false; } log(Warn, "setSortedSet_T failed! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// (事务)删除资源bool RedisManager::decrScore_T(PRedisContext& pRD, const std::string& key, std::string& mem, const uint32_t& decrScore){ ostringstream cmdStr; cmdStr << "ZINCRBY " << key << " -" << decrScore << " %s"; RedisCmdTimeTesting cTime; redisReply *reply = redisCommand(pRD, cmdStr.str().c_str(), mem.c_str()); cTime.Log(pRD, "decrScore_T ZINCRBY %s -%u !reply:%u", key.c_str(), decrScore, reply); if (reply) { if (REDIS_REPLY_STATUS == reply->type) { if (strcmp(reply->str, "QUEUED") == 0) { freeReplyObject(reply); return true; } else { log(Error, "decrScore_T in transaction return failure"); } } else { log(Warn, "decrScore_T Wrong reply type received! Type: %d, key: %s", reply->type, key.c_str()); } freeReplyObject(reply); return false; } log(Warn, "decrScore_T failed! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// (事务)添加资源值bool RedisManager::incrMemScore_T(PRedisContext& pRD, const std::string& key, std::string& mem, const uint32_t& incrScore){ ostringstream cmdStr; cmdStr << "ZINCRBY " << key << " " << incrScore << " %s"; RedisCmdTimeTesting cTime; redisReply *reply = redisCommand(pRD, cmdStr.str().c_str(), mem.c_str()); cTime.Log(pRD, "incrMemScore_T key %s mem %s score %u ! reply:%u", key.c_str(), mem.c_str(), incrScore, reply); if (reply) { if (REDIS_REPLY_STATUS == reply->type) { if (strcmp(reply->str, "QUEUED") == 0) { freeReplyObject(reply); return true; } else { log(Error, "incrMemScore_T in transaction return failure, key: %s", key.c_str()); } } else { log(Warn, "incrMemScore_T Wrong reply type received! Type: %d, key: %s", reply->type, key.c_str()); } freeReplyObject(reply); return false; } log(Warn, "incrMemScore_T failed! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// --- Transaction(事务)// 开始事务,标记事务开始bool RedisManager::beginTransaction(PRedisContext& pRD){ RedisCmdTimeTesting cTime; redisReply *reply = redisCommand(pRD, "MULTI"); cTime.Log(pRD, "beginTransaction MULTI reply %u", reply); if (reply) { if (REDIS_REPLY_STATUS == reply->type) { freeReplyObject(reply); return true; } else { log(Warn, "Wrong reply received. Type: %d", reply->type); } freeReplyObject(reply); return false; } log(Warn, "MULTI failed! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// 结束事务,执行所有事务bool RedisManager::endTransaction(PRedisContext& pRD, bool& isAborted){ isAborted = false; RedisCmdTimeTesting cTime; redisReply *reply = redisCommand(pRD, "EXEC"); cTime.Log(pRD, "endTransaction EXEC reply %u", reply); if (reply) { if (REDIS_REPLY_ARRAY == reply->type) { isAborted = true; freeReplyObject(reply); return true; } else if (REDIS_REPLY_NIL == reply->type) { isAborted = true; freeReplyObject(reply); return true; } else { log(Warn, "Wrong reply received. Type: %d", reply->type); } freeReplyObject(reply); return false; } log(Warn, "EXEC failed! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// 事务结束,执行所有事务bool RedisManager::endTransaction(PRedisContext& pRD, bool& isAborted, redisReply** pReply){ isAborted = false; RedisCmdTimeTesting cTime; redisReply *reply = redisCommand(pRD, "EXEC"); cTime.Log(pRD, "endTransaction EXEC reply %u", reply); if (reply) { if (REDIS_REPLY_ARRAY == reply->type) { isAborted = true; *pReply = reply; return true; } else if (REDIS_REPLY_NIL == reply->type) { isAborted = true; freeReplyObject(reply); return true; } else { log(Warn, "Wrong reply received. Type: %d", reply->type); } *pReply = reply; return false; } log(Warn, "EXEC failed! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// 取消事务,取消执行模块内的所有事务bool RedisManager::discardTransaction(PRedisContext& pRD){ RedisCmdTimeTesting cTime; redisReply *reply = redisCommand(pRD, "DISCARD"); cTime.Log(pRD, "discardTransaction DISCARD ! reply:%u", reply); if (reply) { if (REDIS_REPLY_STATUS == reply->type) { freeReplyObject(reply); return true; } else { log(Warn, "Wrong reply received. Type: %d", reply->type); } freeReplyObject(reply); return false; } log(Warn, "DISCARD failed! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// 监控一个keybool RedisManager::watch(PRedisContext& pRD, const std::string& key){ RedisCmdTimeTesting cTime; redisReply *reply = redisCommand(pRD, "WATCH %s", key.c_str()); cTime.Log(pRD, "watch WATCH ! reply:%u", reply); if (reply) { if (REDIS_REPLY_STATUS == reply->type) { freeReplyObject(reply); return true; } else { log(Warn, "Wrong reply received. Type: %d", reply->type); } freeReplyObject(reply); return false; } log(Warn, "Watch key %s failed! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// 监控一些keybool RedisManager::watch(PRedisContext& pRD, const vector<std::string>& keys){ std::vector<const char *> argv(keys.size() + 1); std::vector<size_t> argvlen(keys.size() + 1); uint32_t j = 0; static char sremcmd[] = "WATCH"; argv[j] = sremcmd; argvlen[j] = sizeof(sremcmd) - 1; ++j; for (std::vector<string>::const_iterator i = keys.begin(); i != keys.end(); ++i, ++j) { argv[j] = i->c_str(); argvlen[j] = i->size(); } RedisCmdTimeTesting cTime; redisReply* reply = (redisReply*)redisCommandArgv(pRD, argv.size(), &(argv[0]), &(argvlen[0])); cTime.Log(pRD, "watch WATCH ! reply:%u", reply); if (reply) { if (REDIS_REPLY_STATUS == reply->type) { freeReplyObject(reply); return true; } else { log(Warn, "Wrong reply received. Type: %d", reply->type); } freeReplyObject(reply); return false; } log(Warn, "Watch key failed! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// 取消监控keybool RedisManager::unwatch(PRedisContext& pRD){ RedisCmdTimeTesting cTime; redisReply *reply = redisCommand(pRD, "UNWATCH"); cTime.Log(pRD, "unwatch UNWATCH reply %u", reply); if (reply) { if (REDIS_REPLY_STATUS == reply->type) { freeReplyObject(reply); return true; } else { log(Warn, "Wrong reply received. Type: %d", reply->type); } freeReplyObject(reply); return false; } log(Warn, "UnWatch failed! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// --- lua 脚本控制// 加载脚本,指定脚本对应一个keybool RedisManager::loadScript(PRedisContext& pRD, const std::string& key, const std::string& script){ RedisCmdTimeTesting cTime; redisReply *reply = redisCommand(pRD, "SCRIPT LOAD %s", script.c_str()); cTime.Log(pRD, "loadScript LOAD ! reply:%u", reply); if (reply) { if (REDIS_REPLY_STRING == reply->type) { string checkSum = reply->str; // 获取校验和 setScriptInfo(pRD, key, checkSum); freeReplyObject(reply); log(Info, "loadScript LOAD success! checkNum:%s", checkSum.c_str()); return true; } freeReplyObject(reply); } log(Warn, "loadScript LOAD failed! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// 检查key指定的脚本是不是已经加载bool RedisManager::existsScript(PRedisContext& pRD, const std::string& key){ string checkSum; getScriptInfo(pRD, key, checkSum); if (checkSum.compare("") != 0) { RedisCmdTimeTesting cTime; redisReply *reply = redisCommand(pRD, "SCRIPT EXIST %s", checkSum.c_str()); cTime.Log(pRD, "existsScript SCRIPT EXIST ! reply:%u", reply); if (reply) { if (REDIS_REPLY_INTEGER == reply->type) { if (1 == reply->integer) { freeReplyObject(reply); return true; } } freeReplyObject(reply); return false; } log(Warn, "existsScript SCRIPT EXIST failed! error:%d, error_info:%s", pRD->err, pRD->errstr); return false; } return false;}// 获取已经加载的所有的脚本keybool RedisManager::getAllScriptKeys(PRedisContext& pRD, std::vector<string> &keys){ return getScriptAllKeys(pRD, keys);}// 清理所有已经加载的脚本缓存bool RedisManager::clearAllScript(PRedisContext& pRD){ RedisCmdTimeTesting cTime; redisReply *reply = redisCommand(pRD, "SCRIPT FLUSH"); cTime.Log(pRD, "SCRIPT FLUSH ! reply:%u", reply); if (reply) { clearScriptAllKeys(pRD); freeReplyObject(reply); return true; } log(Warn, "SCRIPT FLUSH failed! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// 执行脚本,outValue表示返回数据bool RedisManager::exceScript(PRedisContext& pRD, const std::string& key, std::vector<std::string> &outValue){ string checkSum; getScriptInfo(pRD, key, checkSum); log(Warn, "exceScript 1 %s ", checkSum.c_str()); if (checkSum.compare("") != 0) { RedisCmdTimeTesting cTime; redisReply *reply = redisCommand(pRD, "EVALSHA %s 0", checkSum.c_str()); cTime.Log(pRD, "exceScript EVALSHA! reply:%u", reply); if (reply) { switch (reply->type) { case REDIS_REPLY_STRING:// 返回值为字符串 { string value = reply->str; // 获取校验和 outValue.push_back(value); break; } case REDIS_REPLY_INTEGER: // 返回的是整数 { string value = ws::toString(reply->integer); outValue.push_back(value); break; } case REDIS_REPLY_ARRAY: // 返回的是数组 { if (reply->elements > 0) { for (uint32_t i = 0; i < reply->elements - 1; ) { outValue.push_back(reply->element[i++]->str); } } break; } } freeReplyObject(reply); return true; } log(Warn, "exceScript failed! error:%d, error_info:%s", pRD->err, pRD->errstr); return false; } return false;}// 终止当前正在执行的脚本(且当该脚本没有执行写操作才能成功)bool RedisManager::stopRuningScript(PRedisContext& pRD){ RedisCmdTimeTesting cTime; redisReply *reply = redisCommand(pRD, "SCRIPT KILL"); cTime.Log(pRD, "SCRIPT KILL ! reply:%u", reply); if (reply) { clearScriptAllKeys(pRD); freeReplyObject(reply); return true; } log(Warn, "SCRIPT KILL failed! error:%d, error_info:%s", pRD->err, pRD->errstr); return false;}// -----------------reids执行报告----------------------// 初始化redis执行报告; pid:为0表示监视所有线程,其他表示单一线程uint32_t RedisManager::startRedisReport(uint32_t pid){ //if (0 == pid) //{ // pid = (uint32_t)pthread_self(); // 当前线程 //} m_RedisReport.m_State = 1; // 开启 m_RedisReport.m_Pid = pid; // 线程id m_RedisReport.m_RunCount = 0; m_RedisReport.m_RunTime = 0; m_RedisReport.m_StartTime = time(NULL); m_RedisReport.m_KeyInfo.clear(); log(Info, "First time init for new reportRedisStruct in thread %u.", pid); return pid;}// 关闭redis报告记录void RedisManager::stopRedisReport(){ m_RedisReport.m_State = 0; // 关闭}// 打印执行报告std::string RedisManager::getRedisReport(){ std::stringstream os; os << "[redis report!]:"; os << "state:%u " << m_RedisReport.m_State; os << "pid:%u " << m_RedisReport.m_Pid; os << "run count:%u " << m_RedisReport.m_RunCount; os << "run time:%lu " << m_RedisReport.m_RunTime; os << "start time:%lu " << m_RedisReport.m_StartTime; os << "cur time:%lu " << (uint64_t)time(NULL); os << "key info:[ "; map<std::string, map<std::string, uint32_t> >::iterator itF = m_RedisReport.m_KeyInfo.begin(); for (; itF != m_RedisReport.m_KeyInfo.end(); ++itF) { os << "(" << itF->first << ":" << itF->second["time"] << ":" << itF->second["count"] << ");"; } os << "] "; return os.str();}// 产生报告void RedisManager::buildReport(std::string key, timeval startTime, timeval endTime){ // 检查是不是开启检测 if (0 == m_RedisReport.m_State) { return; } // 判断是不是全线程 if (0 != m_RedisReport.m_Pid) { uint32_t pid = (uint32_t)pthread_self(); // 当前线程 if (pid != m_RedisReport.m_Pid) { return; // 不检测 } } // 一条记录的执行时间 uint64_t uTime = (endTime.tv_sec - startTime.tv_sec) * 1000 * 1000 + (endTime.tv_usec - startTime.tv_usec); m_RedisReport.m_RunCount++; // 执行语句总数加1 m_RedisReport.m_RunTime += uTime; // 执行时间相加 m_RedisReport.m_KeyInfo[key]["time"] += uTime; m_RedisReport.m_KeyInfo[key]["count"] ++;}// 保存脚本<key,校验和>,已经存在的key不允许更改bool RedisManager::setScriptInfo(PRedisContext& pRD, const std::string& key, const std::string& checkSum){ std::lock_guard<std::mutex> lock(m_RedisLock); // 加锁 // 建立脚本映射关系 map<PRedisContext, map<string, string> >::iterator it_Script = m_Script.find(pRD); if (it_Script == m_Script.end()) { map<string, string> script_map; script_map.insert(make_pair(key, checkSum)); m_Script[pRD] = script_map; } else { map<string, string>::iterator it_second = m_Script[pRD].find(key); if (it_second == m_Script[pRD].end()) { m_Script[pRD][key] = checkSum; } } return true;}// 获取目标脚本校验和bool RedisManager::getScriptInfo(PRedisContext& pRD, const std::string& key, std::string& checkSum){ checkSum =""; std::lock_guard<std::mutex> lock(m_RedisLock); // 加锁 // 建立脚本映射关系 map<PRedisContext, map<string, string> >::iterator it_Script = m_Script.find(pRD); if (it_Script != m_Script.end()) { map<string, string>::iterator it_second = m_Script[pRD].find(key); if (it_second != m_Script[pRD].end()) { checkSum = m_Script[pRD][key]; return true; } } return false;}// 获取所有的keysbool RedisManager::getScriptAllKeys(PRedisContext& pRD, std::vector<string> &keys){ keys.clear(); std::lock_guard<std::mutex> lock(m_RedisLock); // 加锁 map<PRedisContext, map<string, string> >::iterator it_Script = m_Script.find(pRD); if (it_Script != m_Script.end()) { map<string, string>::iterator it_second = m_Script[pRD].begin(); for (; it_second != m_Script[pRD].end(); ++it_second) { keys.push_back(it_second->first); } } return true;}// 清理缓存bool RedisManager::clearScriptAllKeys(PRedisContext& pRD){ std::lock_guard<std::mutex> lock(m_RedisLock); // 加锁 map<PRedisContext, map<string, string> >::iterator it_Script = m_Script.find(pRD); if (it_Script != m_Script.end()) { m_Script[pRD].clear(); } return true;}bool RedisManager::clean_all_server(void){ return true;}bool RedisManager::load_servers(const std::set <std::string> & server_list){ std::lock_guard<std::mutex> lock(server_online_mutex); std::cout << "cfg.json文件,初始化数据代理服务器在线状态:" << std::endl; for(std::set<std::string>::iterator it=server_list.begin (); it!=server_list.end (); it++) { std::string server_ip = *it; server_status ser_status; memset(&ser_status, 0, sizeof(ser_status)); ser_status._since_enpoch = 0; ser_status.gateway_count = 0; proxy_server_online.insert(std::make_pair(server_ip, ser_status)); } //std::cout << "注册服务器" << std::endl; return true;}bool RedisManager::print_serverlist(void){ std::cout << "打印数据代理服务器在线状态:" << std::endl; for(std::map<std::string, RedisManager::server_status>::iterator it=RedisManager::singleton()->proxy_server_online.begin (); it!=RedisManager::singleton()->proxy_server_online.end (); it++) { RedisManager::server_status status; status = it->second; std::cout << it->first << " : " << status._since_enpoch << status.gateway_count << std::endl; } return true;}bool RedisManager::unregister_server(const std::string & server_ip){ //从redis 移除所有属于ip 的网关的注册 RedisManager::server_status status; uint32_t key = RedisManager::singleton()->CreateContext("127.0.0.1",6379); PRedisContext pRD = RedisManager::singleton()->getRedis(key); RedisManager::singleton()->selectDB(pRD, 0); if (pRD != NULL) { std::set<std::string> gateway; if (true == getAnySetValue(pRD, server_ip, gateway)) { for(set<std::string>::iterator it1=gateway.begin (); it1!=gateway.end (); it1++) { delKey(pRD, *it1); } delKey(pRD, server_ip); } } else { return false; } //设置ip离线 status._since_enpoch = 0; status.gateway_count = 0; proxy_server_online[server_ip] = status; return true;}bool RedisManager::unregister_allserver(const std::set <std::string> & server_list){ for(std::set<std::string>::iterator it=server_list.begin (); it!=server_list.end (); it++) { std::string server_ip = *it; unregister_server(server_ip); } return true;}bool RedisManager::manage_server_online(void){ std::lock_guard<std::mutex> lock(server_online_mutex); chrono::time_point<chrono::system_clock, chrono::microseconds> now = chrono::time_point_cast<chrono::microseconds>( chrono::system_clock::now()); int64_t microSeconds = now.time_since_epoch().count(); for(std::map<std::string, RedisManager::server_status>::iterator it=RedisManager::singleton()->proxy_server_online.begin (); it!=RedisManager::singleton()->proxy_server_online.end (); it++) { RedisManager::server_status status = it->second; //std::cout << it->first << " : " << status._since_enpoch << status.gateway_count << std::endl; /* 服务器掉线,则消除属于该服务器的所有网关的注册 */ if ((status._since_enpoch > 0 ) && ((status._since_enpoch + timeout) < microSeconds)) { std::cout << "proxy server : " << it->first << "should offline" << std::endl; //从redis 移除所有属于ip 的网关的注册 uint32_t key = RedisManager::singleton()->CreateContext("127.0.0.1",6379); PRedisContext pRD = RedisManager::singleton()->getRedis(key); RedisManager::singleton()->selectDB(pRD, 0); if (pRD != NULL) { std::set<std::string> gateway; if (true == getAnySetValue(pRD, it->first, gateway)) { for(set<std::string>::iterator it1=gateway.begin (); it1!=gateway.end (); it1++) { delKey(pRD, *it1); } delKey(pRD, it->first); } } //设置ip离线 status._since_enpoch = 0; status.gateway_count = 0; proxy_server_online[it->first] = status; } if ((status._since_enpoch + timeout) > microSeconds) { std::cout << "proxy server : " << it->first << "online" << std::endl; } } return true;}bool RedisManager::update_server_Timestamp(std::string server_ip, int server_port){ std::cout << "刷新合法服务器的心跳时间戳" << std::endl; chrono::time_point<chrono::system_clock, chrono::microseconds> now = chrono::time_point_cast<chrono::microseconds>( chrono::system_clock::now()); int64_t microSeconds = now.time_since_epoch().count(); RedisManager::server_status ser_status = RedisManager::singleton()->proxy_server_online[server_ip + "-" + std::to_string(server_port)]; ser_status._since_enpoch = microSeconds; RedisManager::singleton()->proxy_server_online[server_ip + "-" + std::to_string(server_port)] = ser_status; RedisManager::server_status ser_statusssss = RedisManager::singleton()->proxy_server_online[server_ip + "-" + std::to_string(server_port)]; cout << "代理服务器multi" << server_ip + "-" + std::to_string(server_port) << "心跳时间戳为:" << ser_statusssss._since_enpoch << std::endl; return true;}bool RedisManager::get_server_online(std::string & serve_ip, std::string & id){ std::lock_guard<std::mutex> lock(server_online_mutex); //查询redis,注册则返回老的注册服务器ip port。不存在则新注册。 int server_min_gateway_count = INT_MAX; std::string ip; RedisManager::server_status status; for(std::map<std::string, RedisManager::server_status>::iterator it=RedisManager::singleton()->proxy_server_online.begin (); it!=RedisManager::singleton()->proxy_server_online.end (); it++) { status = it->second; if ((status._since_enpoch > 1000) && (server_min_gateway_count > status.gateway_count) ) { server_min_gateway_count = status.gateway_count; ip = it->first; std::cout << "尝试获取在线ip: " << it->first << std::endl; } else { //std::cout << "时间戳" << status._since_enpoch << "当前连接数量" << server_min_gateway_count << "遍历连接数量" << status.gateway_count << std::endl; } //std::cout << "变量服务器ip" << it->first << "时间戳" << status._since_enpoch << "在线数量" << status.gateway_count << std::endl; } if (server_min_gateway_count == INT_MAX) { return false; } //不存在,则新注册到redis bool if_id_exist; uint32_t key = RedisManager::singleton()->CreateContext("127.0.0.1",6379); PRedisContext pRD = RedisManager::singleton()->getRedis(key); RedisManager::singleton()->selectDB(pRD, 0); if (false == RedisManager::singleton()->isKeyExist(pRD, id, if_id_exist)) { //注册id到服务器,id:ip;ip-id if (true == RedisManager::singleton()->setStrValue(pRD, id, ip)) { if (true == RedisManager::singleton()->setSetValue(pRD, ip, id)) { serve_ip = ip; std::cout << "网关id=[" << id << "]" << "注册成功" <<std::endl; return true; } else { RedisManager::singleton()->delKey(pRD, id); return false; } } else { return false; } } else { std::cout << "网关id=[" << id << "]" << "已注册" <<std::endl; serve_ip = ip; return true; }}
/** redis_interface.h* Author: jacky* Data: 2019-4-12**/#pragma once#include <string>#include <map>#include <set>#include <time.h>#include <vector>#include <mutex>#include <limits.h>#include <condition_variable>#include <hiredis/hiredis.h>using namespace std;namespace ws_redis{ #define WS_REDIS_LOG_LENGTH_MAX 528 // redis log最大长度#define WS_REDIS_CONTEXT_HASH_MARK 5381 // redis连接hash查找掩码 typedef redisContext* PRedisContext; //-------------------------------------------------------- // reids命令执行时间检测器 //-------------------------------------------------------- class RedisCmdTimeTesting { public: RedisCmdTimeTesting(); virtual ~RedisCmdTimeTesting(); void Log(PRedisContext pRD, const char* fmt, ...); // cmd执行命令log private: std::string m_log; // 日志 timeval m_begin; // 起始时间 timeval m_end; // 结束时间 };//--------------------------------------------------------// reids 执行报告记录器//--------------------------------------------------------struct RedisReport_t{ uint32_t m_State; // 报告状态0表示关闭,1表示开启 uint32_t m_Pid; // 监控线程pid uint32_t m_RunCount; // 执行总数 uint64_t m_RunTime; // 执行时间(所有语句执行的时间和) uint64_t m_StartTime; // 起始时间 map<std::string, map<std::string,uint32_t> > m_KeyInfo; // 同一条语句执行的次数和时间<key,<"time"/"count",>> RedisReport_t() :m_State(0), m_Pid(0), m_RunCount(0), m_StartTime(0) { m_KeyInfo.clear(); }};struct SortData{ std::string m_number; //对应sortedSet的member std::string m_score; //对应sortedSet的score};//--------------------------------------------------------// reids 连接管理器//-------------------------------------------------------- class RedisManager { private: static RedisManager *_instance; public: static RedisManager *singleton(); RedisManager() { proxy_server_online.clear(); } ~RedisManager() { }; public: // -----------------redis连接相关--------------------- uint32_t CreateContext(std::string ip, uint32_t port); // 创建链接 uint32_t CreateContextWithOutTime(std::string ip, uint32_t port, uint32_t time); // 建立链接,带超时时间 bool CloseContext(uint32_t index_link); // 指定管理某个链接 bool CloseAllContext(); // 关闭所有链接 PRedisContext getRedis(std::string key); // 根据key获取redis连接(多连接情况下)通过hash key找到该key存储的redis连接,并发情况下可以提高并发率 PRedisContext getRedis(uint32_t index_link); // 直接指明hashmap中第几个redis连接 bool selectDB(PRedisContext& pRD, uint32_t index_db); // 获取指定redis连接中的第N个DB // -----------------tool工具-------------------------- std::string contextAddrInfo(PRedisContext& pRD); // 链接信息 std::string replayInfo(redisReply* pReply); // 报告信息 std::string replaceCmdCrlf(const char* format); // 将命令中的一些符号替换掉 // -----------------redis命令相关--------------------- redisReply* redisCommand(PRedisContext& pRD, const char *format, ...); // key bool getAllKeys(PRedisContext& pRD, set<std::string>& value, std::string strMatching = "*"); // (消耗性能)获取数据库中所有的key; value: 为返回的所有key集合, strMatching:为查找匹配,默认为"*"所有,可以为如"t[w]*"表达式 bool isKeyExist(PRedisContext& pRD, const string& key, bool& keyExist); // 检查key是否存在 bool delKey(PRedisContext& pRD, const std::string& key); // 删除指定的key bool keyType(PRedisContext& pRD, const std::string& key, std::string& type); // 获取key的类型;返回值:none(key不存在),std::string(字符串),list(列表),set(集合),zset(有序集),hash(哈希表) bool setKeyTTL(PRedisContext& pRD, const std::string& key, uint32_t time); // 设置key的生存时间,单位s bool expireAt(PRedisContext& pRD, const std::string& key, time_t calTime); // 更新key的生存时间, 单位time; uint32_t delKey_T(PRedisContext& pRD, const std::string& key); // 事务模式:删除指定的key, 返回0表示失败, 1表示成功, 2表示存入队列(因为有事务处理) // lock 模拟,阻塞(最大阻塞2秒) bool lock(PRedisContext& pRD, const std::string &key, uint32_t ttl); // 加锁 bool unlock(PRedisContext& pRD, const std::string &key); // 解锁 //--- string bool setStrValue(PRedisContext& pRD, const std::string& key, const std::string& value); // 设置key-value bool setStrValue(PRedisContext& pRD, const std::string& key, const std::string& value, const uint32_t& time);// 设置key-value,带时间 bool getStrValue(PRedisContext& pRD, const std::string& key, std::string& value); // 获取key-value bool setAnyValue(PRedisContext &pRD, map<std::string, std::string> value); // 一次插入多个值 bool getAnyValue(PRedisContext& pRD, const set<std::string>& setKeys, map<std::string, std::string>& outMapInfo); // 一次获取多个数据的值 bool incrValue(PRedisContext& pRD, const std::string& key, int incrNum = 1); // 每次增加指定值,默认为1 bool incrValue(PRedisContext& pRD, const std::string& key, long long &outValue, int incrNum = 1); // 每次增加指定值,默认为1,返回增加后的值 bool decrValue(PRedisContext& pRD, const std::string& key, int decrNum = 1); // 每次减去指定值,默认为1 bool decrValue(PRedisContext& pRD, const std::string& key, long long &outValue, int decrNum = 1); // 每次减去指定值,默认为1,返回增加后的值 //--- list bool getListLen(PRedisContext& pRD, const std::string& key, uint32_t& len); // 获取list长度 bool lPushList(PRedisContext& pRD, const std::string& key, std::string& value); // 插入表头,表为空创建 bool rPushList(PRedisContext& pRD, const std::string& key, std::string& value); // 插入表尾,表为空创建 bool lPushXList(PRedisContext& pRD, const std::string& key, std::string& value); // 插入表头,表为空不创建 bool rPushXList(PRedisContext& pRD, const std::string& key, std::string& value); // 插入表尾,表为空创建 bool lPushAnyList(PRedisContext& pRD, const std::string& key, vector<std::string>& values); // 插入多个值到表头,先插入数据在表尾 bool rPushAnyList(PRedisContext& pRD, const std::string& key, vector<std::string>& values); // 插入多个值到表尾,先插入数据在表头 bool lPushGetLen(PRedisContext& pRD, const std::string& key, std::string& value, uint32_t& len); // 插入表头并获取长度 bool rPushGetLen(PRedisContext& pRD, const std::string& key, std::string& value, uint32_t& len); // 插入表尾并获取长度 bool rPushListBit(PRedisContext& pRD, const std::string& key, std::string& binMem); // (二进制)插入单个字符列到list尾部,如"a b c" bool lPopListBit(PRedisContext& pRD, const std::string& key, std::string& binMem, bool& keyExist); // (二进制)移除字符列, keyExist 判断是否获取字符 bool rPopList(PRedisContext& pRD, const std::string& key, std::string& value, bool& keyExist); // 移除表尾的元素 bool lPopList(PRedisContext& pRD, const std::string& key, std::string& value, bool& keyExist); // 移除表头的元素 bool lremList(PRedisContext& pRD, const std::string& key, std::string& value, std::string count = "1"); // 移除与value值相同的元素,count为移除个数(正数表示从前到后移除n个,负数表示从后往前移除n个,0表示移除所有) bool lrangeList(PRedisContext& pRD, const std::string& key, std::vector<std::string>& result, uint32_t startPos = 0, uint32_t endPos = 0); // 返回指定区域内的元素列表 //--- hash bool setHashValue(PRedisContext& pRD, const std::string& key, std::string field, std::string strValue); // 设置hash值 bool getHashValue(PRedisContext& pRD, const std::string& key, std::string field, std::string& strValue);// 获取hash值 bool setAnyHashValue(PRedisContext& pRD, const std::string& key, map<std::string, std::string>& values);// 设置多个值 bool getAnyHashValue(PRedisContext& pRD, const std::string& key, vector<std::string>& fields, map<std::string, std::string>& values); // 获取多个值 bool getHashAllValue(PRedisContext& pRD, const std::string& key, map<std::string, std::string>& valueMap); // 获取所有hash值对 bool getHashAllFields(PRedisContext& pRD, const std::string& key, vector<std::string>& fields); // 获取目标key的所有field bool setHashValueBit(PRedisContext& pRD, const std::string& key, std::string field, std::string binValue);// (二进制)设置hash值 bool getAnyHashValueBit(PRedisContext& pRD, const std::string& key, map<std::string, std::string>& valueMap);// (二进制)获取所有键值对 bool delHashValue(PRedisContext& pRD, const std::string& key, std::string field); // 删除hash值 bool delHashValue(PRedisContext& pRD, const std::string& key, const set<std::string> & fields, int64_t& rmCount);// 删除多个hash值 bool isMemInHash(PRedisContext& pRD, const std::string& key, std::string field, bool& isMem); // 判断是不是hash成员 bool incrHashValue(PRedisContext& pRD,const std::string& key, std::string field,std::string value = "1");// 在原始值上增加指定值 bool setHashValue_T(PRedisContext& pRD, const std::string& key, map<std::string, std::string>& fieldValue); // (事务) 设置hash值 //--- set bool isMemInSet(PRedisContext& pRD, const std::string& key, std::string& value, bool& isMem); // 判断是不是set成员 bool getSetCount(PRedisContext& pRD, const std::string& key, uint32_t& count, bool& keyExist); // 获取set元素个数 bool setSetValue(PRedisContext& pRD, const std::string& key, std::string& value); // 添加元素,已经存在的元素被忽略 bool setAnySetValue(PRedisContext& pRD, const std::string& key, set<std::string>& value); // 添加多个值,已经存在的元素被忽略 bool getAnySetValue(PRedisContext& pRD, const std::string& key, set<std::string>& value); // 获取set集合 bool remSetValue(PRedisContext& pRD, const std::string& key, std::string& value); // 移除集合中的元素 bool remAnySetValue(PRedisContext& pRD, const std::string &key, const std::set<std::string> &value); // 移除多个指定元素 bool getSetSunion(PRedisContext& pRD, set<std::string>& keys, set<std::string>& value); // 获取多个key的并集 bool getSetSdiff(PRedisContext& pRD, set<std::string>& keys, set<std::string>& value); // 获取多个key的差集 bool getSetSinter(PRedisContext& pRD, set<std::string>& keys, set<std::string>& value); // 获取多个key的交集 bool setSetValue_T(PRedisContext& pRD, const std::string& key, std::string& value); // (事务)添加集合元素 // --- sortset bool isMemInSortedSet(PRedisContext& pRD, const std::string& key, const std::string& member, bool& isMem); // 检查目标是不是sortset的资源 bool getCountSortedSet(PRedisContext& pRD, const std::string& key, uint32_t& totalCount); // 获取资源个数 bool setSortSet(PRedisContext& pRD, const std::string& key, std::string& mem, const uint64_t& score); // 添加元素到key bool setAnySortSet(PRedisContext& pRD, const std::string& key, const map<std::string, std::string>& scores);// 添加多个元素到key bool incrSortSet(PRedisContext& pRD, const std::string& key, const std::string& mem, const uint32_t& incrScore);// 给指定元素增加incrScore的值 bool decrScore(PRedisContext& pRD, const std::string& key, std::string& mem, const uint32_t& decrScore); //减少资源的排序值 bool remMemFromSortedSet(PRedisContext& pRD, const std::string& key, const std::string& mem); // 删除指定资源 bool remRangeByScore(PRedisContext& pRD, const std::string& key, const uint32_t& min, const uint32_t& max); // 删除资源排序值域的资源 bool getScoreByMember(PRedisContext& pRD, const std::string& key, const std::string& member, uint32_t& score); // 返回指定资源的排序值(注意是值不是排名) bool getDescRankByMember(PRedisContext& pRD, const std::string& key, const std::string& member, uint32_t& rank); // 获取资源的降序排名 bool getAscRankByMember(PRedisContext& pRD, const std::string& key, const std::string& member, uint32_t& rank); // 获取资源升序排名 bool incrSortSetBit(PRedisContext& pRD, const std::string& key, std::string& mem, const uint32_t& incrScore); // (二进制)给指定元素增加incrScore的值 bool getDescSortedData(PRedisContext& pRD, const std::string& key, const uint32_t& offset, const uint32_t& limit, std::vector<SortData>& datas); // (降序)从大到小获取指定段的数据, 0 score 会被过滤掉 bool getDescSortedAllData(PRedisContext& pRD, const std::string& key, const uint32_t& offset, const uint32_t& limit, std::vector<SortData>& datas); // (降序)从大到小获取指定段的数据, 0 score 不会被过滤掉 bool getAscSortedData(PRedisContext& pRC, const string& key, const uint32_t& start, const uint32_t& end, std::vector<SortData> &datas); // (升序)从小到大获取指定数据段的数据, 0 score 会被过滤掉 bool getAscSortedAllData(PRedisContext& pRD, const std::string& key, const uint32_t& start, const uint32_t& end, std::vector<SortData>& datas); // (升序)从小到大获取指定数据段的数据, 0 score 不会被过滤掉 bool setSortedSet_T(PRedisContext& pRD, const std::string& key, std::string& mem, const uint32_t& score); // (事务)添加元素 bool decrScore_T(PRedisContext& pRD, const std::string& key, std::string& mem, const uint32_t& decrScore); // (事务)删除资源 bool incrMemScore_T(PRedisContext& pRD, const std::string& key, std::string& mem, const uint32_t& incrScore); // (事务)添加资源值 // --- Transaction(事务) bool beginTransaction(PRedisContext& pRD); // 开始事务,标记事务开始 bool endTransaction(PRedisContext& pRD, bool& isAborted); // 结束事务,执行所有事务 bool endTransaction(PRedisContext& pRD, bool& isAborted, redisReply** pReply); // 事务结束,执行所有事务 bool discardTransaction(PRedisContext& pRD); // 取消事务(回滚),取消执行模块内的所有事务 bool watch(PRedisContext& pRD, const std::string& key); // 监控一个key bool watch(PRedisContext& pRD, const vector<std::string>& keys); // 监控一些key bool unwatch(PRedisContext& pRD); // 取消监控key // --- lua 脚本控制 bool loadScript(PRedisContext& pRD, const std::string& key,const std::string& script);// 加载脚本,指定脚本对应一个key bool existsScript(PRedisContext& pRD, const std::string& key); // 检查key指定的脚本是不是已经加载 bool getAllScriptKeys(PRedisContext& pRD, std::vector<string> &keys); // 获取已经加载的所有的脚本key bool clearAllScript(PRedisContext& pRD); // 清理所有已经加载的脚本缓存 bool exceScript(PRedisContext& pRD, const std::string& key, std::vector<std::string> &outValue); // 执行脚本,outValue表示返回数据 bool stopRuningScript(PRedisContext& pRD); // 终止当前正在执行的脚本(且当该脚本没有执行写操作才能成功) // -----------------reids执行报告---------------------- // 初始化redis执行报告; pid:为0表示监视所有线程,其他表示单一线程 uint32_t startRedisReport(uint32_t pid = 0); void stopRedisReport(); // 关闭redis报告记录 std::string getRedisReport(); // 打印执行报告 void buildReport(std::string key, timeval startTime, timeval endTime); // 产生报告 public: typedef struct { PRedisContext pRD; string str_ip; int port; } PRedisContext_ext; map<PRedisContext, map<string, string> > m_Script; // 脚本<key,脚本对应的校验和> map<uint32_t, PRedisContext_ext> m_allRedisConn; // 所有的redis连接 uint32_t m_MaxRedisContext; // redis最大连接个数 RedisReport_t m_RedisReport; // redis执行报告 //mutex m_RedisLock; // 线程锁 std::mutex m_RedisLock; private: bool setScriptInfo(PRedisContext& pRD, const std::string& key, const std::string& checkSum); // 保存脚本<key,校验和>,已经存在的key不允许更改 bool getScriptInfo(PRedisContext& pRD, const std::string& key, std::string& checkSum);// 获取目标脚本校验和 bool getScriptAllKeys(PRedisContext& pRD, std::vector<string> &keys);// 获取所有的keys bool clearScriptAllKeys(PRedisContext& pRD);// 清理缓存 public: bool clean_all_server(void); bool load_servers(const std::set <std::string> & server_list); bool print_serverlist(void); bool unregister_server(const std::string & server_list); bool unregister_allserver(const std::set <std::string> & server_ip); bool manage_server_online(void); bool update_server_Timestamp(std::string server_ip, int server_port); bool get_server_online(std::string & serve_ip, std::string & id); typedef struct server_status { int64_t _since_enpoch; //数据代理服务器最后接收心跳的时间戳 int gateway_count; //数据代理服务器接入的网关数量 }server_status; private: std::mutex server_online_mutex; std::map<std::string, server_status> proxy_server_online; const int64_t timeout = 1000 * 1000 * 120; };}
发表评论
最新留言
很好
[***.229.124.182]2025年05月01日 16时46分52秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
7、回归和特征选择
2021-05-14
pycharm使用(新建工程、字体修改、调试)
2021-05-14
什么是Numpy、Numpy教程
2021-05-14
Python学习笔记——元组
2021-05-14
异常声音检测
2021-05-14
PCB学习笔记——AD17如何添加新的封装
2021-05-14
numpy版本问题
2021-05-14
无法打开文件“opencv_world330d.lib”的解决办法
2021-05-14
maven项目通过Eclipse上传到svn上面,再导入到本地出现指定的类找不到的问题
2021-05-14
maven 项目部署到tomcat下 没有class文件
2021-05-14
算法训练 未名湖边的烦恼(递归,递推)
2021-05-14
算法训练 完数(循环,数学知识)
2021-05-14
什么是接口
2021-05-14
2020版nodejs12.18.3安装配置教程
2021-05-14
iview组件库中,Form组件里的Input,无法正确绑定on-enter事件
2021-05-14
记录-基于springboot+vue.js实现的超大文件分片极速上传及流式下载
2021-05-14
JavaScript高级程序设计第四版学习记录-第九章代理与反射
2021-05-14