文档章节

再说memcache的multiget hole(无底洞)

旁观者-郑昀
 旁观者-郑昀
发布于 2013/09/13 09:21
字数 1101
阅读 88
收藏 1
关键词:multiget hole,memcache
适用于:java,php
基础知识背景:
1)multiget 是什么:
    multiget 指的是从 memcache(或其他分布式缓存) 一次性获得多个键值,一般由 memcached client 自行实现。如 PHP-memcache-client 提供了  Memcached::getMulti 函数。调用示范如下:
<?php
$items = array(
    'key1' => 'value1',
    'key2' => 'value2',
    'key3' => 'value3'
);
$m->setMulti($items);
$result = $m->getMulti(array('key1', 'key3', 'badkey'), $cas);
var_dump($result, $cas);
?>
2)”multiget hole“详解:
『让我们来模拟一下案发经过,看看到底发生了什么:

我们使用 Multiget 一次性获取100个键对应的数据。

系统最初只有一台 Memcached 服务器,随着访问量的增加,系统负载捉襟见肘,于是我们又增加了一台 Memcached 服务器,数据散列到两台服务器上。

开始那100个键在两台服务器上各有50个。

问题就在这里:原本只要访问一台服务器就能获取的数据,现在要访问两台服务器才能获取;服务器加的越多,需要访问的服务器就越多,所以问题不会改善,甚至还会恶化。

不过,作为被告方,Memcached官方开发人员对此进行了辩护

请求多台服务器并不是问题的症结,真正的原因在于客户端在请求多台服务器时是并行的还是串行的!问题是很多客户端,包括Libmemcached在内,在处理Multiget多服务器请求时,使用的是串行的方式!也就是说,先请求一台服务器,然后等待响应结果,接着请求另一台,结果导致客户端操作时间累加,请求堆积,性能下降

如何解决这个棘手的问题呢?只要保证 Multiget 中的键只出现在一台服务器上即可!(注:事实上这可不容易做到。)

3)以前郑昀在文章里说过,spymemcached 某版本又是如何实现 Multiget(即getBulk)的

  1. 给一组 key,[1,2,3,4,5]。
  2. 先 算一下这些key都落在哪些节点上(通过 KetamaNodeLocator 的 public Iterator<MemcachedNode> getSequence(String k)。Now that we know how many servers it breaks down into.);
  3. 此时,得到一个map:<Node1,[1,3]>;<Node2,[2,4]>;<Node3,[5]>;
  4. 遍历这个map,从每一个 mc node 读出对应的 keys(即单节点的 multiget 操作);一个Node一个Node串行的;
  5. 拼成一个大map<key,value>返回。
这样就是一个 node 复一个 node 串行检索的,虽然做了优化,但是如果涉及的 mc nodes 数量多,线程势必长时间阻塞在等待网络资源返回上。
(注:
spymemcached 后来的版本不再按 node 串行轮询,而是并行:第一步,将本次操作构造成一个针对每个 node 的 Operation 对象,加入连接对象中;第二步,在连接对象中,将所有的 node 操作放入 addedQueue 队列,然后触发 Selector 方式异步非阻塞的执行。)
现象:
    某中心每天很多个读取 memcache 键值超时,报错如下:
Caused by: java.util.concurrent.ExecutionException: net.spy.memcached.internal. CheckedOperationTimeoutException: Operation timed out. - failing node: mcN.domain.name

         at net.spy.memcached.internal.OperationFuture.get(OperationFuture.java:172)

         at net.spy.memcached.internal.GetFuture.get(GetFuture.java:62)

分析:
    在 memcache 集群节点较多情况下,
    特别是在一次性获取成百上千键值的极端场景面前,
    服务端轻则请求超时,重则宕机
 
    无论是先计算 keys 都散列到哪些 mc nodes 上了,还是直接轮询 memcached::get ,或者说并行提交给各个 mc nodes 然后异步等待,
    假设每个 mc get 耗时2~3毫秒,一次性取 2000 个keys,都将阻塞线程长达2~6秒之久,这是身为服务所不能容忍的。
 
    所以,必须约定,适度使用批量获取键值功能,100个键值就到顶了,别因小失大。
    
    当然,也有业务场景绕不开 multiget,那么,一是按照 facebook 所说,此时需要的是更多的 CPU,把缓存数据复制一份到另一个 memcache 集群上,一个集群负责读一半的 keys;二是按照火丁所说,最好保证批量查的这批键值都在同一个 mc node 上。
 
参考资源:
1)火丁,2012, memcache 二三事儿
3)iteye,2012, 通过NIO实现Memcached multi get
赠图几枚:
死锁分析

 
http://ww1.sinaimg.cn/bmiddle/62532502jw1e8837n50faj20dc0dcjsp.jpg

© 著作权归作者所有

旁观者-郑昀
粉丝 100
博文 77
码字总数 162700
作品 0
朝阳
私信 提问
关于 Multiget hole:spymemcached对此的实现方法

火丁说: 『 Multiget的无底洞问题 Facebook在Memcached的实际应用中,发现了Multiget无底洞问 题,具体表现为:出于效率的考虑,很多Memcached应用都已Multiget操作为主,随着访问量的增加,...

旁观者-郑昀
2013/02/08
127
0
缓存系列文章--7.无底洞问题(multiget hole)

转载请注明出处哈:http://carlosfu.iteye.com/blog/2269678 最近有点忙,一直没更新博客,继续坚持下去。 一、背景 1. 什么是缓存无底洞问题: 他们发现一个问题--memcached的连接效率下降了...

付磊-起扬
2015/12/14
0
0
PHP框架 Yii 1.0.8 发布

该版本修正了大量的bug,增加超过20个新的特性。重构了 yiic 命令脚本使之更容易被扩展。改进缓存组件以支持 multiget ;CCaptcha、CCompareValidator、CActiveRecord 等也得到了改进。 详细...

红薯
2009/08/10
256
0
MultiGet 很久不更新了吧

MultiGet 很久不更新了吧 不知道那个高手可以继续这个项目啊

李永波
2010/09/07
1K
4
memcache client缓存节点分配机制和连接读取缓存机制

//mc client//hashingAlg 默认是0private final long getHash(String key, Integer hashCode) { if (hashCode != null) { if (hashingAlg == CONSISTENT_HASH) return hashCode.longValue() ......

aduan
2014/04/25
668
0

没有更多内容

加载失败,请刷新页面

加载更多

elasticsearch查询20公里以内的数据并按距离升序排序data es写法

NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();BoolQueryBuilder boolQueryBuilder=new BoolQueryBuilder();//这暂wei加入业务查询条件 queryBuilder.withQue......

为何不可1995
13分钟前
1
0
superset在线pip部署

1、安装依赖sudo yum install gcc libffi-devel python-devel python-pip python-wheel openssl-devel libsasl2-devel openldap-devel报错:没有可用软件包 python-pip。没有可用软件包 ......

阿伦哥-
18分钟前
2
0
photoshop简单使用

PS基本操作与图片格式 photoshop工具 组成 菜单项 工具栏 辅助面板 图片格式 jpg png gif 注: psd photoshop CC链接: https://pan.baidu.com/s/1LVa5R_btSjczLBwskCZidQ 提取码:sc3v 快捷...

studywin
20分钟前
1
0
springboot 整合pageHelper

今天跟大家聊聊springboot整合pageHelp,首先pageHelper是一个缓存式分页,分页步骤如下: 1 pom文件添加依赖 <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelp......

gaofei123
20分钟前
3
0
《DNS攻击防范科普系列1》—你的DNS服务器真的安全么?

DNS服务器,即域名服务器,它作为域名和IP地址之间的桥梁,在互联网访问中,起到至关重要的作用。每一个互联网上的域名,背后都至少有一个对应的DNS。对于一个企业来说,如果你的DNS服务器因...

大涛学弟
21分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部