数据库连接池DBPool分析(八):redis连接池 redis_connection_pool

更新完上一篇博客的时候恰逢十一黄金周,回家休息了一会。现在补充DBPool的Redis连接池。
我刚开始写mysql_connnection_pool的时候,用的是map这个数据结构来保存连接,每次从池当中取出连接的时候都需要遍历一边map,根据map的第二个参数的bool值来判断是否可用。这样的话效率很低,所以我在这里改用list来保存。每次取出连接的时候都pop_front出来,没次释放连接的时候都push_back回去。这样就不用遍历了,更有效率。同时,我还使用了shared_ptr来管理redis_obj的指针,让delete和我的程序say goodbye。
在redis_obj.h当中加上了:

typedef boost::shared_ptrRedisObjPtr;

这个池和mysql_connnection_pool很像,同样也是从config里面读取database.xml或者database.json配置文件,从配置文件当中获取到host等等。

当然了,为了线程安全,使用unique_lock来上锁。

// Copyright 
// License
// Author: adairjun
// This is used to construct a redis connection pool 

#ifndef DBPOOL_INCLUDE_REDIS_CONNECTION_POOL_H_
#define DBPOOL_INCLUDE_REDIS_CONNECTION_POOL_H_

#include 
#include 
#include 
#include "redis_obj.h"

using std::string;
using std::vector;
using std::mutex;
using std::unique_lock;
using std::list;

// 这个pool只做了一件事情,那就是创建poolsize个的连接
class RedisPool {
 public:
  // 批量创建连接在构造函数当中进行
  RedisPool();
  // 这里析构函数没有做任何事情
  virtual ~RedisPool();

  // 从list当中选取一个连接,pop出来。使用list的好处是每次需要取连接的时候只要取front,不需要像map一样去遍历,节约了时间
  RedisObjPtr GetConnection();

  // 释放特定的连接就是把连接重新放回到list当中去
  int ReleaseConnection(RedisObjPtr);

  // 构造函数创建poolsize个连接错误时候用来打印错误信息
  string ErrorMessage() const;

 private:
  mutex resource_mutex;

 public:
  // 这里与mysql的连接池不一样,我想尝试使用list来保存连接
  list redis_list;

 private:
  string host_ ;
  string user_ ;
  string password_ ;
  unsigned port_;

  //从database.xml或者database.json当中读取max_connections
  int poolSize_;

  //错误信息
  string m_strErrorMessage;  
};

// 使用shared_ptr来替换RedisPool*
typedef boost::shared_ptrRedisPoolPtr;
#endif /* DBPOOL_INCLUDE_REDIS_CONNECTION_POOL_H_ */
#include "DBPool/redis_connection_pool.h"
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

using std::cout;
using std::endl;

RedisPool::RedisPool() {
  // 从配置文件database.xml当中读入redis的ip, 用户, 密码, 和最大连接数  
  boost::property_tree::ptree pt;   
  const char* xml_path = "../config/database.xml";  
  boost::property_tree::read_xml(xml_path, pt);

  //这段注释的代码是读取json配置文件的
  //const char* json_path = "../config/database.json";
  //boost::property_tree::read_json(json_path, pt);

  BOOST_AUTO(child, pt.get_child("Config.RedisConnection"));
  for (BOOST_AUTO(pos, child.begin()); pos!= child.end(); ++pos) {
    if (pos->first == "IP") host_ = pos->second.data();
    if (pos->first == "Port") port_ = boost::lexical_cast<int>(pos->second.data());
    if (pos->first == "Passwd") password_ = pos->second.data();
    if (pos->first == "max_connections") poolSize_ = boost::lexical_cast<int>(pos->second.data());
  }
  // 构造函数的作用就是根据poolSize的大小来构造多个映射
  // 每个映射的连接都是同样的host,pass,dbname

  for (int i=0; i// 这里使用智能指针RedisObjPtr
    RedisObjPtr conn(new RedisObj(host_, password_, port_));
    unique_lock lk(resource_mutex);
    if (conn->Connect()) {
      redis_list.push_back(conn);
    } else {
      m_strErrorMessage = conn->ErrorMessage();
    }
  }

}

RedisPool::~RedisPool() {
    // 由于使用了智能指针,不需要手动delete,析构函数不需要操作
}

// 从list当中得到一个连接
RedisObjPtr RedisPool::GetConnection() {
  //get connection operation
  unique_lock lk(resource_mutex);
  if (!redis_list.empty()) { 
    RedisObjPtr ret = redis_list.front();
    redis_list.pop_front();
    return ret;
  }
}

// 释放一个连接还给线程池
int RedisPool::ReleaseConnection(RedisObjPtr conn) {
  if (conn) {
    redis_list.push_back(conn);
  }
  return 1;
}

string RedisPool::ErrorMessage() const {
  return m_strErrorMessage; 
}

你可能感兴趣的:(数据库池DBPool)