【问题背景】
我们的程序是一个基于tuxedo交易中间件发布的服务,以.so方式更新程序,起停serveice。
由于memcached在程序重启之后,已有缓存数据会全部失效,在访问量大且数据变化较小的情况下,会造成顺时延时长。所以用嵌入式轻量级数据库berkeleyDB(以下简称bdb)对其进行改造:
1)存memcached同时,存入bdb;
2)读取memcached时,如果查不到数据,再查一次bdb,bdb存在则存入memcached。
memcaced是用一个daemon service(tuxedo平台下)调用一个起停脚本管理的,打印不出调试信息。遂停止daemon,手动起停,发现只会第一次不命中,而之前是一直不命中。
【版本】
memcached1.4.4
libmemcached4.0.0
berkely db4.7.25
g++4.1.2
【问题描述】
改造完成后,停止daemon,手动起停,程序在第一次读取改造后的memcached(以下称之为bdb_memcached)总是未命中且提示MEMCACHED_UNKOWN_READ_FAILURE,第一次之后完全正常。
【解决历史】
0.memcaced是用一个daemon程序起停的,手动起试试。发现只会第一次不命中,而之前是一直不命中。
1.怀疑是第一次读取时,bdb因为延时还没启动。修改在memcaced启动bdb时,加sleep(20),问题依然存在。
2.bdb数据文件权限。修改为所有人可读,不行。
3.查看libmemcached接口mget和memcached_fetch_result()源码,看MEMCACHED_UNKOWN_READ_FAILURE错误是那个地方报的。由于没深入看,没发现问题。
4.用libmemcached写了一个本地可执行的程序,mget数据,发现第一次会成功。虽编译了一个local版本的程序运行,发现同样的请求,第一会命中。
5.为什么local的就能命中?为什么只第一次不命中?而后者显然是最诡异的问题!!
6.一牛相信看完libmemcached源码之后提醒:有libmemcached是用socket读取memcached的,连接建立后,会保持之,以方便在下次读取的时候,节约socket三次握手的成本。在mget的时候只是把所有请求键发到server端,而不管server是否返回数据。在调用memcached_fetch_result时,会检查都会的数据是否正常,并返回。而mget()之前,只停止memcaced,不停本地服务,本地服务会以为当前socket仍然有效,而实际服务器端已经重启。所以会第一次失败,并重连,之后就会正常。于是,停memcached的同时,停服务,再全部启动。问题解决。
我们的程序是一个基于tuxedo交易中间件发布的服务,以.so方式更新程序,起停serveice。
由于memcached在程序重启之后,已有缓存数据会全部失效,在访问量大且数据变化较小的情况下,会造成顺时延时长。所以用嵌入式轻量级数据库berkeleyDB(以下简称bdb)对其进行改造:
1)存memcached同时,存入bdb;
2)读取memcached时,如果查不到数据,再查一次bdb,bdb存在则存入memcached。
memcaced是用一个daemon service(tuxedo平台下)调用一个起停脚本管理的,打印不出调试信息。遂停止daemon,手动起停,发现只会第一次不命中,而之前是一直不命中。
【版本】
memcached1.4.4
libmemcached4.0.0
berkely db4.7.25
g++4.1.2
【问题描述】
改造完成后,停止daemon,手动起停,程序在第一次读取改造后的memcached(以下称之为bdb_memcached)总是未命中且提示MEMCACHED_UNKOWN_READ_FAILURE,第一次之后完全正常。
【解决历史】
0.memcaced是用一个daemon程序起停的,手动起试试。发现只会第一次不命中,而之前是一直不命中。
1.怀疑是第一次读取时,bdb因为延时还没启动。修改在memcaced启动bdb时,加sleep(20),问题依然存在。
2.bdb数据文件权限。修改为所有人可读,不行。
3.查看libmemcached接口mget和memcached_fetch_result()源码,看MEMCACHED_UNKOWN_READ_FAILURE错误是那个地方报的。由于没深入看,没发现问题。
4.用libmemcached写了一个本地可执行的程序,mget数据,发现第一次会成功。虽编译了一个local版本的程序运行,发现同样的请求,第一会命中。
5.为什么local的就能命中?为什么只第一次不命中?而后者显然是最诡异的问题!!
6.一牛相信看完libmemcached源码之后提醒:有libmemcached是用socket读取memcached的,连接建立后,会保持之,以方便在下次读取的时候,节约socket三次握手的成本。在mget的时候只是把所有请求键发到server端,而不管server是否返回数据。在调用memcached_fetch_result时,会检查都会的数据是否正常,并返回。而mget()之前,只停止memcaced,不停本地服务,本地服务会以为当前socket仍然有效,而实际服务器端已经重启。所以会第一次失败,并重连,之后就会正常。于是,停memcached的同时,停服务,再全部启动。问题解决。
【总结】
这样解决了为什么local版本就能读到数据的问题,因为local建立的是短连接,而非长连接,所以每次都会读到数据。