数据库连接池DBPool分析(七):Redis连接控制 RedisObj

因为这个连接控制的class当中使用了大量的引用,所以设置一个宏IN和OUT,仅仅只是一个标志,标记是输出还是输入。
这个class的设计和MysqlObj的设计非常像,但是不同的是这里并不需要一个对象来专门保存查询值,就因为Redis是key-value的,查询是直接返回一个字符串或者数字。
所以这里只需要一个成员变量来保存查询值,就是redisReply* r_pResult;
redisReply是定义在hiredis.h头文件当中的。
另外一个设计上的需求是这里还没有加上登陆密码。Redis是可以设置密码的。

和MysqlObj相比的大差距是这些函数:

public:
    // 从redis当中获取返回值
    int IntegerResult(OUT long long &result);
    int StringResult(OUT string &result);
    int StatusResult(OUT string &result);
    int StringArrayResult(OUT vector<string> &result);
    int ArrayResult(OUT vector<redisReply*> &result);

同样也是因为Redis不是关系型数据库,所以需要对返回值的pResult的type进行检查。检查之后再执行对应的函数。


#ifndef _REDIS_OBJ_H
#define _REDIS_OBJ_H

#include <hiredis/hiredis.h>
#include <string>
#include <vector>
#include "debug.h"

using std::string;
using std::vector;

// 设置一个标志,函数参数列表当中带有OUT的就是输出引用,带有IN的就是输入参数
#define OUT
#define IN

class RedisObj
{
 public:
    RedisObj(string HostIP, string pPassword, unsigned iPort);
    virtual ~RedisObj();
    // Dump指的是把m_pRedis的指针指向的值打印出来
    void Dump() const;

    string ErrorMessage();

    // 根据成员变量来建立Redis连接
    bool Connect();
    void Close();

    int ExecuteCmd(const char* pCmd);

    //返回Redis的指针
    redisContext* get() const;

 public:
    // 从redis当中获取返回值
    int IntegerResult(OUT long long &result);
    int StringResult(OUT string &result);
    int StatusResult(OUT string &result);
    int StringArrayResult(OUT vector<string> &result);
    int ArrayResult(OUT vector<redisReply*> &result);

 private:
    // 从redis当中获取返回值
    int IntegerResult(OUT long long &result, IN redisReply* reply);
    int StringResult(OUT string &result, IN redisReply* reply);
    int StatusResult(OUT string &result, IN redisReply* reply);
    int StringArrayResult(OUT vector<std::string> &result, IN redisReply* reply);
    int ArrayResult(OUT vector<redisReply*> &result, IN redisReply* reply);

 private:
    // 代表了一条数据库连接
    redisContext* r_pRedis;
    redisReply* r_pResult;
 private:
    // 连接必备的参数:IP地址,用户,密码,数据库名称,端口号
    string r_strHost;
    string r_strPassword;
    unsigned r_iPort;

    //错误信息
    string r_strErrorMessage;
};

#endif /* REDIS_OBJ_H */

#include "../include/redis_obj.h"
#include <assert.h>
#include <cstring>

RedisObj::RedisObj(string host, string password, unsigned port)
: r_strHost(host), r_strPassword(password), r_iPort(port)
{
    r_pRedis = NULL;
}

RedisObj::~RedisObj()
{
    Close();
}

void RedisObj::Dump() const
{
    printf("r_pRedis=%p", r_pRedis);
}

string RedisObj::ErrorMessage()
{
    return "";
}

bool RedisObj::Connect()
{
    r_pRedis = redisConnect(r_strHost.c_str(), r_iPort);
    if ( r_pRedis->err )
    {
        return false;
    }
    return true;
}

void RedisObj::Close()
{
    if ( r_pRedis )
    {
        redisFree(r_pRedis);
        r_pRedis = NULL;
    }
}

int RedisObj::ExecuteCmd(IN const char* pCmd)
{
    r_pResult = (redisReply*)redisCommand(r_pRedis, pCmd);
    if( r_pResult == NULL)
    {
        return -1;
    }
    return 0;
}

redisContext* RedisObj::get() const
{
    return r_pRedis;
}

int RedisObj::IntegerResult(OUT long long &result)
{
    return IntegerResult(result, r_pResult);
}

int RedisObj::StringResult(OUT string &result)
{
    return StringResult(result, r_pResult);
}

int RedisObj::StatusResult(OUT string &result)
{
    return StatusResult(result, r_pResult);
}

int RedisObj::StringArrayResult(OUT vector<string> &result)
{
    return StringArrayResult(result, r_pResult);
}

int RedisObj::ArrayResult(OUT vector<redisReply*> &result)
{
    return ArrayResult(result, r_pResult);
}

// 从redis当中获取返回值
int RedisObj::IntegerResult(OUT long long &result, IN redisReply* reply)
{
    if(reply == NULL)
        return -1;
    if(reply->type != REDIS_REPLY_INTEGER)
        return -1;

    result = reply->integer;
    return 1;
}

int RedisObj::StringResult(OUT std::string &result, IN redisReply* reply)
{
    if(reply == NULL)
        return -1;
    if(reply->type == REDIS_REPLY_NIL)
        return 0;
    if(reply->type != REDIS_REPLY_STRING)
        return -1;

    result.clear();
    result.assign(reply->str, reply->len);
    return 1;
}

int RedisObj::StatusResult(OUT std::string &result, IN redisReply* reply)
{
    if(reply == NULL)
        return -1;
    if(reply->type != REDIS_REPLY_STATUS)
        return -1;

    result.clear();
    result.assign(reply->str, reply->len);
    return 1;
}

int RedisObj::StringArrayResult(OUT std::vector<std::string> &result, IN redisReply* reply)
{
    if(reply == NULL)
        return -1;
    if(reply->type == REDIS_REPLY_NIL)
        return 0;
    if(reply->type != REDIS_REPLY_ARRAY)
        return -1;

    result.clear();
    for(size_t i=0; i<reply->elements; i++)
    {
        redisReply* r = reply->element[i];
        if(r->type == REDIS_REPLY_STRING)
        {
            result.emplace_back(r->str, r->len);
        }
    }
    if(result.size() == 0)
        return 0;
    return 1;
}
int RedisObj::ArrayResult(OUT std::vector<redisReply*> &result, IN redisReply* reply)
{
    if(reply == NULL)
        return -1;
    if(reply->type != REDIS_REPLY_ARRAY)
        return -1;

    result.clear();
    for(size_t i=0; i<reply->elements; i++)
    {
        redisReply* r = reply->element[i];
        result.emplace_back(r);
    }
    if(result.size() == 0)
        return 0;
    return 1;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-18 13:04:24

数据库连接池DBPool分析(七):Redis连接控制 RedisObj的相关文章

DBCP数据库连接池原理分析

在比较大的项目中,需要不断的从数据库中获取数据,Java中则使用JDBC连接数据库,但是获取数据库的连接可是相当耗时的操作,每次连接数据库都获得 .销毁数据库连接,将是很大的一个开销.为了解决这种开销,则使用了对象池的技术.程序启动时,先创建一定数量的数据库连接对象,然后只要一用到就直接从对象池中取出连接对象,然后使用完成后不对其销毁,而是再返回到对象池中,这样使连接池对象能反复使用,虽然增加了启动时所需要的时间但是提高了响应速度,对象池也相当于是一个缓存. 这里有DBCP的一些配置参数,通过这

Java第三方数据库连接池库-DBCP-C3P0-Tomcat内置连接池

连接池原理 数据库连接池的基本思想就是为数据库连接建立一个“缓冲池”.预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从“缓冲池”中取出一个,使用完毕之后再放回去.我们可以通过设定连接池最大连接数来防止系统无尽的与数据库连接. 现在流行的第三方Java数据库连接池库 DBCP 它是Apache推出的Database Connection Pool,属于Apache Commons开源项目,官网:http://commons.apache.org/components.html.Co

Nginx反向代理与后端服务采用连接池参数分析,长连接减少TIME_WAIT

前面已经讲过,在使用locust直连后端服务器时,可以通过设置HTTP头部为keep-alive,并在客户端断开连接,减少服务器的连接压力.因为由客户端断开连接,客户端的连接会变为TIME_WAIT状态,从而有效的节省了服务器的资源. 但通常,我们的服务器并不是简单的一个服务器端程序,一般还会有cache服务器,反向代理服务器,负载均衡服务器等等很多的中间部分,而这些模块之间都是通过新的连接相连,如果频繁的新建断开他们之间的连接,不仅会导致服务器端出现大量TIME_WAIT连接,还会导致性能的下

数据库连接池原理详解与自定义连接池实现

实现原理 数据库连接池在初始化时将创建一定数量的数据库连接放到连接池中,这些数据库连接的数量是由最小数据库连接数制约.无论这些数据库连接是否被使用,连接池都将一直保证至少拥有这么多的连接数量.连接池的最大数据库连接数量限定了这个连接池能占有的最大连接数,当应用程序向连接池请求的连接数超过最大连接数量时,这些请求将被加入到等待队列中. 连接池基本的思想是在系统初始化的时候,将数据库连接作为对象存储在内存中,当用户需要访问数据库时,并非建立一个新的连接,而是从连接池中取出一个已建立的空闲连接对象.使

怎样建立稳定的长连接的数据库连接池

数据库连接池里面会保留许多数据库连接对象. 这些连接对象对数据库的连接,可以是长连接,也可以是短连接. 长连接:在初始化数据库连接池的时候,建立连接对象后,让连接对象连接上数据库,在以后的时间里面都一直保持同数据库之间的连接. 这样做的好处是:不必每次执行数据库操作,都要建立同数据库的连接,可以节省许多连接所花费的时间(相比短连接). 但有一个问题需要解决: 因为同数据库的物理网络断线,或者数据库超时踢掉连接,会造成连接池中的连接对象掉线,默认状态下会抛出异常框,程序可能会罢工. 对于DELPH

在Java中开源的数据库连接池

在Java中开源的数据库连接池有以下几种 : 1, C3P0 C3P0是一个开放源代码的JDBC连接池,它在lib目录中与Hibernate一起发布,包括了实现jdbc3和jdbc2扩展规范说明的Connection 和Statement 池的DataSources 对象. https://github.com/swaldman/c3p0 2,Proxool 这是一个Java SQL Driver驱动程序,提供了对你选择的其它类型的驱动程序的连接池封装.可以非常简单的移植到现存的代码中.完全可配

开源数据库连接池之C3P0

本篇介绍几种开源数据库连接池,同时重点讲述如何使用C3P0数据库连接池. 之前的博客已经重点讲述了使用数据库连接池的好处,即是将多次创建连接转变为一次创建而使用长连接模式.这样能减少数据库创建连接的消耗.正是由于数据库连接池的思想非常重要,所以市面上也有很多开源的数据库连接池供我们使用.主要有以下三个: DBCP数据库连接池 C3P0 数据库连接池 Tomcat内置的数据库连接池(DBCP) 本篇主要讲述C3P0数据库连接池的使用,关于另外两个数据库连接池的用法请看<开源数据库连接池之DBCP>

JDBC整合c3p0数据库连接池 解决Too many connections错误

前段时间,接手一个项目使用的是原始的jdbc作为数据库的访问,发布到服务器上在运行了一段时间之后总是会出现无法访问的情况,登录到服务器,查看tomcat日志发现总是报如下的错误. Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Data source rejected establishment of connection, message from server: "Too man

c#与oracle数据库连接池

c#与oracle数据库连接池 在做一个项目,中间要使用webservice和oracle数据库.我在服务端做了用户身份认证,也就是使用session传递用户的登陆信息.在测试时,当用户少的时候,没有问题,但是当大量用户同时访问时,就报错,起初以为是自己的oracle连接部分有问题,几经确认,终于发现了是连接池的问题. 以下是从别人的博客中摘抄的,不敢造次,收录如下: "连接根据连接字符串以及用户标识来建立池连接.因此,如果使用网站上的基本身份验证或 Windows 身份验证以及集成的安全登录,