最新文章专题视频专题问答1问答10问答100问答1000问答2000关键字专题1关键字专题50关键字专题500关键字专题1500TAG最新视频文章推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37视频文章20视频文章30视频文章40视频文章50视频文章60 视频文章70视频文章80视频文章90视频文章100视频文章120视频文章140 视频2关键字专题关键字专题tag2tag3文章专题文章专题2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章专题3
当前位置: 首页 - 科技 - 知识百科 - 正文

memcached优化始末

来源:动视网 责编:小采 时间:2020-11-09 13:25:06
文档

memcached优化始末

memcached优化始末:我们线上服务一直使用memcached作为cache服务器,客户端使用的是libmemcached,示意图如下。 问题现象 我们发现item平均大小仅为10KB左右,结果memcached set的平均延时就有7ms之多。我们之前已经在libmemcached里面设置了TCP_NODELAY。
推荐度:
导读memcached优化始末:我们线上服务一直使用memcached作为cache服务器,客户端使用的是libmemcached,示意图如下。 问题现象 我们发现item平均大小仅为10KB左右,结果memcached set的平均延时就有7ms之多。我们之前已经在libmemcached里面设置了TCP_NODELAY。


我们线上服务一直使用memcached作为cache服务器,客户端使用的是libmemcached,示意图如下。 问题现象 我们发现item平均大小仅为10KB左右,结果memcached set的平均延时就有7ms之多。我们之前已经在libmemcached里面设置了TCP_NODELAY。 libmemcached在set/g

我们线上服务一直使用memcached作为cache服务器,客户端使用的是libmemcached,示意图如下。

问题现象

我们发现item平均大小仅为10KB左右,结果memcached set的平均延时就有7ms之多。我们之前已经在libmemcached里面设置了TCP_NODELAY。

libmemcached在set/get之后会接收服务器返回的数据,如果一次没有收到,就会循环调用poll等待服务器返回数据。

 while (1) 
 { 
 int enable = 1;
 setsockopt( ptr->fd, IPPROTO_TCP, TCP_QUICKACK, (void *)&enable, sizeof(enable));
 data_read= recv(ptr->fd, ptr->read_buffer, MEMCACHED_MAX_BUFFER, 0); 
 setsockopt( ptr->fd, IPPROTO_TCP, TCP_QUICKACK, (void *)&enable, sizeof(enable));
 if (data_read > 0)
 { 
 break;
 } 
 else if (data_read == SOCKET_ERROR)
 { 
 ptr->cached_errno= get_socket_errno();
 memcached_return_t rc= MEMCACHED_ERRNO;
 switch (get_socket_errno())
 { 
 case EWOULDBLOCK:
#ifdef USE_EAGAIN
 case EAGAIN:
#endif
 case EINTR:
#ifdef TARGET_OS_LINUX
 case ERESTART:
#endif
 if ((rc= io_wait(ptr, MEM_READ)) == MEMCACHED_SUCCESS)
 continue;
 /* fall through */
 default:
 { 
 memcached_quit_server(ptr, true);
 *nread= -1; 
 return rc; 
 } 
 } 
 }

剑豪使用systemstap发现经常有超过40ms的poll,这是一个很重要的线索,我使用strace也可以看到很多超过40ms的poll。

经过一系列测试发现,流量越小,延时反而越高。但是为什么延时又随着QPS的波动而波动呢?我想应该是这样的,memcached_st对象池使用stack保存,使用的顺序是后进先出。当流量小的时候,会一直使用栈最上面的一两个memcached_st对象,所以对某个memcached服务器的压力可能不必流量高峰低。

问题缘由

经过来回折腾,我发现客户端和服务器端都存在DELAYACK的情况,客户端会对服务器的响应做DELAYACK,不会影响性能。真正奇怪的是客户端设置了NODELAY,但是有时候它会等待服务器发送ACK,才接着继续发数据。并且由于服务器都开启了TSO、GRO等特性,使用tcpdump看不到网卡做的事情,tcp经常push一个远大于MSS的包出去,似乎也根本不考虑服务端的接收窗口大小。

下图中487、488、4三行在做一个get,没有命中cache之后,从490行开始做set,结果服务器的ack delay了,导致客户端发送第二个包的时候等了40ms。

我甚至怀疑TCP_NODELAY没有设置上,但是在代码中使用getsockopt将TCP_NODELAY的值打印出来,发现确实是1。

NOREPLY

无意中看到memcached支持NOREPLY选项(这个选项libmemcached同样也支持,要不然一个巴掌拍不响),真是如获重宝啊,实际线上的效果如下,现在set的latency已经可以忽略不计了。我想世界上所有非关键的服务都应该支持NOREPLY这个选项。

一点小结

1、TCP_NODELAY之所以没起作用,应该和gro有关系。我做了一个测试,发现关闭gro之后,poll超过40ms的情况减少了很多。如果不能理解其中的奥义,就很难解释为什么流量大,延时反而会降下来这个现象。

2、libmemcached这种每个memcached_st对象对每个memcached服务器都有自己连接的方式,特别容易导致每个连接压力都很小,导致延时变得特别高。这种压力能小到什么程度呢?假设有30台memcached服务器,客户端set的QPS是1K,多线程导致一共有30个memcached_st对象,那么一个socket的set QPS就是1K/(30*30)=1。

淘宝自己的tbnet/anet网络通讯库是复用socket的,每个包通过channel id来标识自己,可以使socket保持高压力,不容易出现上面这个问题。

文档

memcached优化始末

memcached优化始末:我们线上服务一直使用memcached作为cache服务器,客户端使用的是libmemcached,示意图如下。 问题现象 我们发现item平均大小仅为10KB左右,结果memcached set的平均延时就有7ms之多。我们之前已经在libmemcached里面设置了TCP_NODELAY。
推荐度:
标签: 一直 使用 服务
  • 热门焦点

最新推荐

猜你喜欢

热门推荐

专题
Top