DB_PROXY_Server数据库代理是TeamTalk TTServer中负责与数据库交互的代理服务器,在DB server中负责承载TeamTalk所有业务层面和逻辑层面的数据入库和持久化等服务,是TT_Server中比较重要的一环,在设计中采用了很多实用的技术,比如池化技术,数据库代理,单例模式等,收益匪浅,下面对TealTalk的DB_Server作个详细分析,以封面是自己阅读代码后的学习总结,一方面可以给其他学习TT_Server的人提供参考。
可以通过查看DB_Server的配置文件dbproxyserver.conf文件,DB_SERVER主要分为以下几个部分:
1、TeamTalk_Matser 采用了MYSQL数据库
2、TeamTalk_Slave MYSQL数据库 (由于水平有限,对数据库的学习还不够深入,尚不清楚为什么需要部署主从服务器)
-------------------------------------------------------------
3、unread 未读信息实例 redis 数据库
4、group_set 群组设置实例 redis数据库
5、token 实例 redis数据库
6、sync实例 redis数据库 同步功能
7、group_member redis 数据库
每个数据库实例都会预先打开于数据库的两个链接,不需要在每次使用的时候再打开,使用结束后释放,节省了数据打开和释放需要的时间和资源,在当前可用连接数不够的情况下再新增一个数据库链接,动态调节DB_Server的负载,同时限定了每个实例的最大可用连接数,由于系统资源是有限的,当业务比较繁忙时不能无限制创建新的连接,避免耗尽系统资源,这种场景下,当没有可用连接的时候,新的业务请求必须等待,等待可用的连接,然后再执行相应的业务操作。
DB_Server采用了多线程,在DB_Server启动的时候预先分配了配置文件中指定的线程数,用来处理具体的数据库请求,当一个请求到达DB_Server时,DB_Server将该请求封装成DB相关的额任务类,然后随机加入到预先启动的线程的任务列表中,有线程回调函数不停执行具体的任务请求,者就是整个DB_Serve的设计思路。
下面来看代码的流程:
1、CacheManager的初始化
db_proxy_server的main函数中,依次从配置文件中读取各个实例的名称以及初始DB实例个数,最大连接数等信息。
首先获取CacheManager的对象,在获取对象的同时对该对象以及该对象管理的资源进行了初始化。
CacheManager* pCacheManager = CacheManager::getInstance();
需要明确的是,cacheManager维护了一个map,map<string, CachePool*>m_cache_pool_map;这个map的key值就是每个配置文件中每个CacheInstances的名称,对应给每一个cache实例维护了一个连接池CachePool, 在CachePool中有维护了一个list<CacheConn*>m_free_list;,这个list保存了对应cache实例的连接,CacheConn是对每个DB连接的封装。这个类中维护了对应数据库连接的一些基本信息,redis数据的话保存的是数据库连接上下文redisContext,以及操作数据库的Set 和Get方法。
创建CacheManager的对象
CacheManager* CacheManager::getInstance()
{
if (!s_cache_manager) {
s_cache_manager = new CacheManager();
if (s_cache_manager->Init()) {
delete s_cache_manager;
s_cache_manager = NULL;
}
}
return s_cache_manager;
}
调用CacheManager的Init的方法,初始化CacheManager管理的资源,在这里就是读取配置文件,根据配置文件中的CacheInstance名称创建对应的实例,并创建相应的连接池对象,将其插入到Manager管理的Map中。
int CacheManager::Init()
{
CConfigFileReader config_file("dbproxyserver.conf");
char* cache_instances = config_file.GetConfigName("CacheInstances");
if (!cache_instances) {
log("not configure CacheIntance");
return 1;
}
char host[64];
char port[64];
char db[64];
char maxconncnt[64];
CStrExplode instances_name(cache_instances, ',');
for (uint32_t i = 0; i < instances_name.GetItemCnt(); i++) {
char* pool_name = instances_name.GetItem(i);
//printf("%s", pool_name);
snprintf(host, 64, "%s_host", pool_name);
snprintf(port, 64, "%s_port", pool_name);
snprintf(db, 64, "%s_db", pool_name);
snprintf(maxconncnt, 64, "%s_maxconncnt", pool_name);
char* cache_host = config_file.GetConfigName(host);
char* str_cache_port = config_file.GetConfigName(port);
char* str_ca