Memcached调优

Memcached调优项目中有一个对实时响应性比较高的服务,引入了Memcached以减少延迟和减少数据库压力。但是期间遇到了一些问题,这里记录一些调优细节。 

客户端选择

  • 最开始我使用的是Memcached Java Client,但是最后放弃了,放弃原因包括:
    • 有时会出现的“No Thread For Socket”异常,我记录在这里
    • 它不支持NOREPLY模式(在这种模式下,更新缓存的set操作可以不需要Memcached服务端响应,这使得set操作非常非常快)。
  • 现在我使用的是XMemcached

统计信息

可以通过nc命令向Memcached服务端发送消息来获取统计信息,例如:

echo "stats settings" | nc localhost 20200 | sort

但是,我更需要客户端的统计信息,尤其是缓存命中率,set操作成功率等等。所以在客户端添加了一个简单的统计模块。每次处理用户请求的过程中,通常有两次向Cache服务端的提交get请求,很多情况下还有两次set请求,合计消耗17ms,在把set请求改成NOREPLY模式以后,这个数减少到10ms以内。因此,对于实时性要求比较高的情形,请打开这个模式,或者干脆使用异步的set。

服务端参数

  • 可以使用-U来使用UDP传输,但是收效不大。
  • -k参数可以阻止换页操作发生,在内存足够的情况下对提高性能有益。
  • -C参数可以禁用CAS。
  • -t指定使用的线程数,如果你是多CPU、多核CPU,可以把这个值配成和总CPU核数一致。
  • -f参数,增长因子,存储大对象把它配大一点可以提高效率,配小一点可以减少浪费。

客户端参数

  • 在使用Memcached Java Client的时候:
    • 由于它会使用direct memory,一定不能加上DisableExplicitGC这个参数,否则就等着OOM吧;
    • 配置大一些的heap size可以提高L1 cache的命中率;
    • 把alive check置为false。
  • 对于实时性和响应性要求比较高的项目,需要做GC调优,主要是GC时延,比如配置MaxGCPauseMillis参数到一个可以接受的值,但是不是越小越好,减低时延的同时会降低吞吐量。
  • 有同事提了个建议,在客户端存放一个cache key的集合,可以在去cache server查询之前,先在本地查看一下是否有缓存记录(比如用Bloom filter来实现),如果有,再去cache server查询。这个集合可以和实际的cache key有出入,也许一个小时同步一次就可以。但是实际上实现起来比较困难,本身key set的总量非常大,而且Memcached最初提供获取key iterator的接口返回的是一个限定大小key set的iterator,缺乏实际意义(这个接口在后来Memcached的版本中已经被废弃)。至于stats方法,它会把所有cache对象dump出来,只能小规模调试的时候使用。
  • 关于Nagle算法:Nagle的好处是可以批量处理请求,提高TCP包有效部分的大小,从而提高网络利用率,但是如果对每个请求处理时延要求很高的话请关闭。
  • 一定要指定socket timeout或者get/set timeout。

最后,有人做了一个几个Memcached客户端的综合的性能试验:链接

文章未经特殊标明皆为本人原创,未经许可不得用于任何商业用途,转载请保持完整性并注明来源链接《四火的唠叨》

分享到:

发表评论

电子邮件地址不会被公开。

您可以使用这些 HTML 标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>


Preview on Feedage: