2014年三月

libmemcached的retry_timeout问题分析

最近在线上中遇到使用libmemcached的svr连接memcached间隔性的出现47错误,每次在2s的时间内大量出现,

其宏定义为MEMCACHED_SERVER_TEMPORARILY_DISABLED,表示memcached临时性不可用.

libmecached的版本是0.53
刚开始以为是网络间隔性异常导致,但是在排查无果的情况,只能深入看下libmemcached的源代码,发现了其内部实现的
retry_timeout的机制:
  • 当某个时刻,某台memcached机器出现连接超时情况时,会将server的状态标识为MEMCACHED_SERVER_STATE_IN_TIMEOUT
  • 在接下来的retry_timeout(默认为2s)的时间内,libmemcached将不会重新连接该memcached,总是直接返回47错误码,表示服务临时不可用

我们遇到的情况就是当某个时刻网络抖动(这个在跨机房通信应该比较常见),可能会是在ms级的,但是libmemcached会直接将该server不可用,并且在2s内不再重试。这里就是所谓的“快隔离、慢恢复”的理念,会在2s内导致该memcached不可用,出现大量47错误的原因。

可以通过MEMCACHED_BEHAVIOR_RETRY_TIMEOUT将retry_timeout设置为1s来减少网络抖动的影响,但是不能设置为0,最少是1s.



snprintf函数的返回值问题

平时在程序设计中,我们推荐使用snprintf, 主要是为了避免str写越界的情况发生,但是对snprintf的返回值理解有个误区,

今天特别记录下。

snprintf的函数原型为:

int snprintf(char *str, size_t size, const char *format, …);

说明:

之前以为snprintf的返回值是实际写入到str字符串的长度,其实不然

case 1 : 如果要输出的字符串的长度< size, 主要这里不包括=, 因为snprintf会自动将\0加入到str中,

snprintf的返回值是实际str的长度

case 2 : 如果要输出的字符串长度>= size, 则表明str的长度不够写入原有的长度,则snprintf的返回值

在理想情况下(即str的长度足够长)的字符串长度,所以其返回值可能会出现>= size的情况。

另外需要说明的snprintf会自动将’\0′追加到str的末尾,而snprintf的返回值是不包括’\0′的

这个在官方的manual里写的比较清楚:

If the output was truncated due to this limit then the return
value is the number of characters (not including the trailing ’\0’) which would have been written to the final string if  enough  space  had  been  available.
Thus,  a  return value of size or more means that the output was truncated. (See also below under NOTES.)  If an output error is encountered, a negative value
is returned.