`
carlosfu
  • 浏览: 582552 次
  • 性别: Icon_minigender_1
  • 来自: 北京
博客专栏
Ba8b5055-9c58-3ab0-8a1c-e710f0495d2c
BigMemory实战与理...
浏览量:31248
53b2087e-c637-34d2-b61d-257846f73ade
RedisCluster开...
浏览量:151060
C9f66038-7478-3388-8086-d20c1f535495
缓存的使用与设计
浏览量:125265
社区版块
存档分类
最新评论

缓存系列文章--7.无底洞问题(multiget hole)

阅读更多
更多Redis的开发、运维、架构以及新动态,欢迎关注微信公众号:

 

 

转载请注明出处哈:http://carlosfu.iteye.com/blog/2269678


  最近有点忙,一直没更新博客,继续坚持下去。大笑

 

一、背景 

  1. 什么是缓存无底洞问题:

Facebook的工作人员反应2010年已达到3000个memcached节点,储存数千G的缓存。
他们发现一个问题--memcached的连接效率下降了,于是添加memcached节点,添加完之后,并没有好转。称为“无底洞”现象

      

 2. 缓存无底洞产生的原因:

   键值数据库或者缓存系统,由于通常采用hash函数将key映射到对应的实例,造成key的分布与业务无关,但是由于数据量、访问量的需求,需要使用分布式后(无论是客户端一致性哈性、redis-cluster、codis),批量操作比如批量获取多个key(例如redis的mget操作),通常需要从不同实例获取key值,相比于单机批量操作只涉及到一次网络操作,分布式批量操作会涉及到多次网络io。

    

    

    

 

3. 无底洞问题带来的危害:

  (1) 客户端一次批量操作会涉及多次网络操作,也就意味着批量操作会随着实例的增多,耗时会不断增大。

  (2) 服务端网络连接次数变多,对实例的性能也有一定影响。

 
4. 结论:

  用一句通俗的话总结:更多的机器不代表更多的性能,所谓“无底洞”就是说投入越多不一定产出越多。

  分布式又是不可以避免的,因为我们的网站访问量和数据量越来越大,一个实例根本坑不住,所以如何高效的在分布式缓存和存储批量获取数据是一个难点。

 

二、哈希存储与顺序存储

   在分布式存储产品中,哈希存储与顺序存储是两种重要的数据存储和分布方式,这两种方式不同也直接决定了批量获取数据的不同,所以这里需要对这两种数据的分布式方式进行简要说明:

   1. hash分布:

   hash分布应用于大部分key-value系统中,例如memcache, redis-cluster, twemproxy,即使像mysql在分库分表时候,也经常会用user%100这样的方式。

   hash分布的主要作用是将key均匀的分布到各个机器,所以它的一个特点就是数据分散度较高,实现方式通常是hash(key)得到的整数再和分布式节点的某台机器做映射,以redis-cluster为例子:

    

   问题:和业务没什么关系,不支持范围查询。

  2. 顺序分布

  

 

 3. 两种分布方式的比较:

分布方式 特点 典型产品
哈希分布

1. 数据分散度高

2.键值分布与业务无关

3.无法顺序访问

4.支持批量操作

一致性哈希memcache

redisCluster

其他缓存产品

顺序分布

1.数据分散度易倾斜

2.键值分布与业务相关

3.可以顺序访问

4.支持批量操作

BigTable

Hbase

 

 

 

三、分布式缓存/存储四种Mget解决方案

 

1. IO的优化思路:

  (1) 命令本身的效率:例如sql优化,命令优化

  (2) 网络次数:减少通信次数

  (3) 降低接入成本:长连/连接池,NIO等。

  (4) IO访问合并:O(n)到O(1)过程:批量接口(mget),

 

2.  如果只考虑减少网络次数的话,mget会有如下模型

 

 

3. 四种解决方案:

(1).串行mget

将Mget操作(n个key)拆分为逐次执行N次get操作, 很明显这种操作时间复杂度较高,它的操作时间=n次网络时间+n次命令时间,网络次数是n,很显然这种方案不是最优的,但是足够简单。

 

 

(2). 串行IO

    将Mget操作(n个key),利用已知的hash函数算出key对应的节点,这样就可以得到一个这样的关系:Map<node, somekeys>,也就是每个节点对应的一些keys

    它的操作时间=node次网络时间+n次命令时间,网络次数是node的个数,很明显这种方案比第一种要好很多,但是如果节点数足够多,还是有一定的性能问题。

 

 

(3). 并行IO

   此方案是将方案(2)中的最后一步,改为多线程执行,网络次数虽然还是nodes.size(),但网络时间变为o(1),但是这种方案会增加编程的复杂度。

   它的操作时间=1次网络时间+n次命令时间

 

 

(4). hash-tag实现。

    第二节提到过,由于hash函数会造成key随机分配到各个节点,那么有没有一种方法能够强制一些key到指定节点到指定的节点呢?

    redis提供了这样的功能,叫做hash-tag。什么意思呢?假如我们现在使用的是redis-cluster(10个redis节点组成),我们现在有1000个k-v,那么按照hash函数(crc16)规则,这1000个key会被打散到10个节点上,那么时间复杂度还是上述(1)~(3)

      

    那么我们能不能像使用单机redis一样,一次IO将所有的key取出来呢?hash-tag提供了这样的功能,如果将上述的key改为如下,也就是用大括号括起来相同的内容,那么这些key就会到指定的一个节点上。

   例如:

    

   

user1,user2,user3......user1000
{user}1,{user}2,{user}3.......{user}1000

 

 

 

例如下图:它的操作时间=1次网络时间+n次命令时间

 

 

3. 四种批量操作解决方案对比:

方案 优点 缺点 网络IO
串行mget

1.编程简单

2.少量keys,性能满足要求

大量keys请求延迟严重 o(keys)
串行IO

1.编程简单

2.少量节点,性能满足要求

大量node延迟严重

o(nodes)
并行IO

1.利用并行特性

2.延迟取决于最慢的节点

1.编程复杂

2.超时定位较难

o(max_slow(node))
hash tags 性能最高

1.tag-key业务维护成本较高

2.tag分布容易出现数据倾斜

o(1)

 

 

 

 

四、总结和建议

 

    无底洞问题对资源和性能有一定影响,但是其实大部分系统不需要考虑这个问题,因为

    1. 99%公司的数据和流量无法和facebook相比。

    2. redis/memcache的分布式集群通常来讲是按照项目组做隔离的,以我们经验来看一般不会超过50对主从。   

    所以这里只是提供了一种优化的思路,开阔一下视野。

    

 

五、参考文献

  1. Facebook's Memcached Multiget Hole: More machines != More Capacity  
  2. Multiget的无底洞问题
  3. 再说memcache的multiget hole(无底洞)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

分享到:
评论
2 楼 carlosfu 2016-01-11  
87029274 写道
博主加油,写的很好,学到了很多!


多谢夸奖,共同学习。
1 楼 87029274 2016-01-11  
博主加油,写的很好,学到了很多!

相关推荐

    cors-filter-1.7.jar 和 java-property-utils-1.9.jar

    CORS为解决这个问题提供了一种安全的方式。 `cors-filter-1.7.jar` 和 `java-property-utils-1.9.jar` 是在Java环境中实现CORS跨域访问时常用的两个库。`cors-filter-1.7.jar` 包含了一个过滤器,该过滤器能够处理...

    commons-dbcp-1.2.1.jar + commons-pool-1.4.jar + commons-collections-3.2.jar

    DBCP通过维护一个连接池来缓存数据库连接,当应用程序需要时,可以从池中获取连接,用完后归还,而不是直接关闭,这显著减少了与数据库的交互开销。 2. **Apache Commons Pool** `commons-pool-1.4.jar` 是Apache ...

    nexus 最新版 nexus-3.12.1-01-unix.tar.gz

    2. **代理仓库**:它可以作为Maven中央仓库和其他第三方仓库的代理,缓存常用的依赖,加快项目构建速度。 3. **托管仓库**:允许用户上传和管理自定义的组件,如内部库、私有库或特定版本的依赖。 4. **组仓库**:...

    安装Apache提示缺少 libapr-1.so.0与libaprutil-1完美解决

    如果问题仍未解决,可能需要检查系统的动态链接器配置文件`/etc/ld.so.conf`,确保包含了APR和APR-UTIL库的路径,并执行`ldconfig`命令以更新动态链接器缓存。 通过以上步骤,可以有效地解决因缺少`libapr-1.so.0`...

    redis-desktop-manager-0.8.8.384.zip

    Redis是一个开源(BSD许可),内存存储的数据结构服务器,可用作数据库,高速缓存和消息队列代理。 我上传的是redis-desktop-manager-0.8.8.384.exe版本,解压即可

    nexus-webapp-1.9.2.4安装文件

    1. **代理仓库**:Nexus可以作为Maven、npm、Gradle等工具的代理,缓存远程仓库的依赖,减少网络延迟,提高构建速度。 2. **存储库**:允许创建多个自定义仓库,用于存储内部构建的工件,确保团队间的协作和共享。 3...

    ibatis-2.3.4.726.jar,ibatis-2.3.0.677.jar,ibatis-2.3.3.720.jar下载

    5. **缓存机制**:为了提高性能,iBATIS引入了缓存机制,可以缓存查询结果,减少不必要的数据库访问。 接下来,我们关注这些版本的区别: - **ibatis-2.3.4.726.jar**:这是iBATIS 2.x系列的较新版本,可能包含了...

    gradle-3.3-all.zip 绿色版本,欢迎下载

    Gradle-3.3是Gradle的第3.3版本,它提供了一系列改进和新特性,以提升开发效率和项目管理能力。这个"gradle-3.3-all.zip"绿色版本是为了方便开发者在无法通过官网下载时获取到Gradle的离线安装包。 首先,让我们...

    nexus-2.3.1-bundle.tar.gz

    9. **监控和日志**:"sonatype-work" 目录下的日志文件是诊断问题和监控 Nexus 运行状态的重要资源。 10. **升级和迁移**:由于工作目录 "sonatype-work" 与软件主体分开,升级 Nexus 到新版本时,可以保留旧版本的...

    nexus-latest-bundle.tar.gz

    Nexus作为Maven仓库,可以是本地仓库的替代品,它能缓存远程仓库的依赖,减少网络请求,加快构建速度,并且可以作为发布新组件的平台。 在压缩包子文件的文件名称列表中,有两个关键文件: 1. "sonatype-work":这...

    hibernate-ehcache-4.1.0.Final.jar

    hibernate-ehcache-4.1.0.Final.jar 是hibernate4.1使用缓存的jar包

    gradle-4.1-all.zip 离线包下载 需要下载

    6. **缓存机制**:Gradle缓存构建结果和依赖,避免重复工作,节省时间和资源。 7. **Gradle Wrapper**:为确保所有开发者使用的Gradle版本一致,Gradle Wrapper提供了一种便捷方式,无需全局安装Gradle即可执行构建...

    redis-desktop-manager-0.8.8.384 最新版

    对于描述中提到的性能优化,这可能包括了更高效的缓存策略、更快的渲染速度以及优化的后台数据处理机制。这些改进使得在处理大数据集时,Redis Desktop Manager 0.8.8.384版能够更加流畅,避免了因性能瓶颈导致的...

    apache-activemq-5.13.1-bin.tar.gz

    7. **性能优化**:ActiveMQ具有高性能的设计,通过缓存、批量发送和高效的网络协议优化,可以处理大量并发的消息交换。 8. **协议桥接**:ActiveMQ可以作为不同消息系统的桥梁,实现不同消息协议之间的互操作性,...

    apache-tomcat-6.0.37.tar.gz

    Apache Tomcat 6.0系列是Tomcat的一个重要版本,它支持Java EE 5规范,包括Servlet 2.5和JSP 2.1。在这个版本中,开发者可以享受到更稳定、更高效的Java Web应用服务。下面我们将详细探讨一下这个版本的一些关键特性...

    spring-framework-3.0.5.RELEASE-dependencies.zip

    通过使用"spring-framework-3.0.5.RELEASE-dependencies.zip",开发者可以直接获取这些依赖,避免了手动添加和版本冲突的问题,极大地简化了项目配置。 在解压"spring-framework-3.0.5.RELEASE-dependencies.zip"后...

    nexus-2.9.0-04-bundle.zip

    它可以缓存来自Maven中央仓库和其他外部仓库的依赖,减少网络延迟,提高构建速度。 2. **存储库组**:你可以将多个仓库组合成一个组,这样在一个组里就能访问到所有成员仓库中的工件,简化了依赖管理。 3. **宿主...

    commons-codec-1.3.jar和commons-httpclient-3.0.jar

    `commons-codec`可以帮助XFire处理编码解码问题,而`commons-httpclient`则提供了与远程Web服务通信的底层实现。 使用这两款库的开发者可以利用它们的功能来: 1. **Base64编码/解码**:在数据传输中,Base64编码常...

    nagios-plugins-1.4.14.tar.gz

    Nagios插件是一系列可执行的小程序,它们负责与服务器、网络设备或其他系统组件通信,收集状态信息,然后返回给Nagios核心进行解析和展示。nagios-plugins-1.4.14包含了多种插件,如check_http用于检查HTTP服务,...

    php-memcached-demo.tar.gz

    3. 获取数据:使用`get()`方法获取缓存中的数据,如`$value = $memcache-&gt;get('key')`。 4. 删除数据:当不再需要某个键的数据时,可以调用`delete()`方法,如`$memcache-&gt;delete('key')`。 5. 其他操作:除了基础...

Global site tag (gtag.js) - Google Analytics