关键词: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)的
- 给一组 key,[1,2,3,4,5]。
- 先 算一下这些key都落在哪些节点上(通过 KetamaNodeLocator 的 public Iterator<MemcachedNode> getSequence(String k)。Now that we know how many servers it breaks down into.);
- 此时,得到一个map:<Node1,[1,3]>;<Node2,[2,4]>;<Node3,[5]>;
- 遍历这个map,从每一个 mc node 读出对应的 keys(即单节点的 multiget 操作);一个Node一个Node串行的;
- 拼成一个大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.nameat 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 二三事儿;
2)郑昀,2013,关于 Multiget hole:spymemcached对此的实现方法;
3)iteye,2012,通过NIO实现Memcached multi get;
4)facebook,2009,Facebook's Memcached Multiget Hole: More machines != More Capacity ;
赠图几枚:
死锁分析
相关推荐
- 使用`set()`和`get()`方法进行数据的存储和读取,`increment()`和`decrement()`处理计数器,`delete()`移除数据。 **应用场景与最佳实践** 1. **减轻数据库压力**:对于频繁查询但变化不大的数据,如用户登录...
5. **批量操作**:`memcache_set_multi()`和`memcache_get_multi()`支持同时处理多个键值对,提高了效率。 6. **内存管理**:Memcache会自动管理内存,但当内存不足时,使用LRU(Least Recently Used)策略淘汰最不...
**Memcache 深度解析** Memcache 是一个高性能、分布式的内存对象缓存系统,广泛应用于Web应用中,用于缓解数据库的负载压力。它通过将数据存储在内存中,以便快速访问,从而提高应用程序的响应速度。在本文中,...
$out = $memcache->get('key'); ``` 5. **删除数据**: ```php $memcache->delete('key'); ``` 6. **清空所有数据**: ```php $memcache->flush(); ``` 7. **关闭连接**: ```php $memcache->close(); ``...
3. **数据检索**:`memcache_get()`用于根据键获取存储的数据,`memcache_get_multi()`可以一次获取多个键对应的值。 4. **数据删除**:`memcache_delete()`用于删除指定键的缓存数据。 5. **缓存统计**:`memcache_...
- `memcache_get_multi()`和`memcache_set_multi()`用于一次处理多个键值对。 5. **其他操作** - `memcache_increment()`和`memcache_decrement()`用于对整数值进行自增或自减操作,常用于计数场景。 - `...
**Memcache Win版服务器与.NET驱动详解** Memcache是一款高性能的分布式内存缓存系统,它最初是为了解决Web应用程序的数据库负载问题而设计的。通过将数据存储在内存中,Memcache能够快速地提供数据,减少对数据库...
3. **操作缓存**:可以使用`add()`, `set()`, `get()`, `delete()`等方法进行数据的存取和删除。例如,`$memcache->set('key', 'value')`将键为'key'的值设置为'value'。 4. **性能优化**:memcache的性能受到网络...
4. get_multi(keys, key_prefix=''):通过一个操作从 Memcache 中查找多个键。 5. delete(key):删除 Memcache 中的一个键。 6. delete_multi(keys):删除 Memcache 中的多个键。 7. add(key, value, time=0, min_...
$get_value = $memcache->get('key'); //获取数据 echo "Retrieved value: " . $get_value . " "; $memcache->close(); ?> ``` 在Web服务器上运行这个脚本,如果一切正常,你应该能看到成功连接到Memcache...
` 创建一个 Memcache 对象,`$m->connect('localhost', 11211)` 连接到 memcache 服务器,以及 `var_dump($m->get('key'));` 获取缓存的键值。 3. `example.php`:这是一个示例脚本,包含了如何使用 memcache.dll ...
echo $memcache->get('test_key'); // 获取数据 $memcache->close(); ?> ``` 运行这个脚本,如果一切正常,你应该能看到“Hello, Memcache!”的输出。 7. 监控与管理: 在Windows上,你可能需要使用第三方...
$value = $memcache->get('key'); // 如果数据存在,打印出来 if ($value) { echo "Value: " . $value; } // 关闭连接 $memcache->close(); ``` ### 四、性能优化与注意事项 - **持久连接**: 使用`pconnect`...
标题 "php7.2 memcache.dll" 涉及到的是PHP编程语言的一个扩展模块,具体是Memcache的动态链接库(DLL)文件,用于在PHP 7.2...connect()`、`memcache_set()`和`memcache_get()`等,实现数据的缓存操作,优化网站性能。
例如,`memcache_set()`函数用于将键值对存储到缓存中,而`memcache_get()`用于根据键从缓存中获取数据。 在实际应用中,Memcache扩展可以提升网站性能,因为频繁访问的数据可以从内存中快速获取,而不是每次都从...
这个DLL文件是一个预编译的PHP扩展,当加载到PHP解释器中时,它提供了一系列的函数,如`memcache_connect()`、`memcache_set()`、`memcache_get()`等,让开发者能够方便地实现缓存功能。为了在PHP环境中使用Memcache...
面向对象的常用接口包括Memcache::connect(打开连接)、Memcache::pconnect(打开长连接)、Memcache::close(关闭连接)、Memcache::set(保存数据)、Memcache::get(提取数据)、Memcache::replace(替换数据)...
PHP 的 `memcache` 扩展提供了一系列函数,如 `memcache_connect()` 连接 Memcache 服务器,`memcache_set()` 存储数据,`memcache_get()` 获取数据,`memcache_delete()` 删除数据,以及 `memcache_close()` 关闭...
2. **使用Memcache API**:PHP提供了丰富的Memcache函数,如`memcache_connect()`用于连接到Memcache服务器,`memcache_set()`用于存储键值对,`memcache_get()`用于获取数据,`memcache_close()`关闭连接等。...
Memcache是一种广泛使用的分布式内存对象缓存系统,它可以在服务器集群间通过网络共享小块内存,从而提升应用程序的性能,减少数据库负载。在PHP中,我们通常使用php_memcache.dll扩展来与Memcache服务器进行交互。...