- 本文讨论的是sina的memcachedb,不是memcached
- Memcachedb基于libevent实现,也就是说单线程的。理论上讲所有的IO操作都需要通过信号来处理,先注册信号,系统通知可以读写了再调用具体的读写命令。这主要针对网络,严格意义上来说本地的读写也要这样处理。否则本地阻塞会引起整个服务器阻塞。
- Memcachedb基于实用的原因,读写数据库未作信号处理,但问题也不大:
- 使用嵌入的berkeley db,仅本程序访问。
- 直接调用berkeley db的API操作数据库,相当于直接操作文件的性能。
- 由于不是标准的IO调用,而是berkeley db API,要通过信号来控制也很复杂。
- 但如果启用berkeley db的replication特性,数据库阻塞的机会可能会增大。
为什么考虑这个呢,因为今天考虑在libevent里面调用mysql,情况就复杂一点。
- 调用的MySQL client C API, 通过socket同MySQL沟通,网络可能会阻塞。
- MySQL同时服务多个应用,可能有时候会繁忙响应很慢。
- MySQL C API无法设置event
所以感觉不能用memcachedb的方法。目前想到的办法就是把所有的MySQL操作通过异步去完成,比如把操作放入队列,用另外一个程序或线程去处理。但是这只适合插入和修改,如果是查询需要即时等待返回结果就不适合,很麻烦。
本文分类:高性能服务器
附:memcachedb的存取数据库代码
void complete_nread(conn * c) {
item *it = &(c->item);
int comm = c->item_comm;
int ret;
stats.set_cmds++;
while (1) {
if (strncmp(ITEM_data(it) + it->nbytes - 2, "\r\n", 2) != 0) {
out_string(c, "CLIENT_ERROR bad data chunk");
break;
}
cleanup_dbt();
if (comm == NREAD_ADD || comm == NREAD_REPLACE) {
dbkey.data = ITEM_key(it);
dbkey.size = strlen(ITEM_key(it));
if ((ret = dbp->get(dbp, NULL, &dbkey, &dbdata, 0)) == 0) {
if (comm == NREAD_ADD) {
out_string(c, "NOT_STORED");
break;
}
} else if (comm == NREAD_REPLACE) {
out_string(c, "NOT_STORED");
break;
}
}
cleanup_dbt();
dbkey.data = ITEM_key(it);
dbkey.size = strlen(ITEM_key(it));
dbdata.data = ITEM_data(it);
dbdata.size = it->nbytes;
// 这里直接调用数据库存取
if ((ret = dbp->put(dbp, NULL, &dbkey, &dbdata, 0)) == 0) {
/* some future code? */
out_string(c, "STORED");
} else {
out_string(c, "NOT_STORED");
}
break;
}
return;
}