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

来源:互联网 发布:3ds淘宝哪家店没问题 编辑:程序博客网 时间:2024/06/14 02:43

更新完上一篇博客的时候恰逢十一黄金周,回家休息了一会。现在补充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_ptr<RedisObj>RedisObjPtr;

这个池和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 <string.h>#include <mutex>#include <list>#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<RedisObjPtr> 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_ptr<RedisPool>RedisPoolPtr;#endif /* DBPOOL_INCLUDE_REDIS_CONNECTION_POOL_H_ */
#include "DBPool/redis_connection_pool.h"#include <stdlib.h>#include <iostream>#include <unistd.h>#include <boost/property_tree/ptree.hpp>#include <boost/property_tree/xml_parser.hpp>#include <boost/property_tree/json_parser.hpp>#include <boost/typeof/typeof.hpp>#include <boost/foreach.hpp>#include <boost/lexical_cast.hpp>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<poolSize_; ++i) {    // 这里使用智能指针RedisObjPtr    RedisObjPtr conn(new RedisObj(host_, password_, port_));    unique_lock<mutex> 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<mutex> 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; }
1 0
原创粉丝点击