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

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介:     转载请注明出处哈:http://carlosfu.iteye.com/blog/2269678   最近有点忙,一直没更新博客,继续坚持下去。   一、背景    1. 什么是缓存无底洞问题: Facebook的工作人员反应2010年已达到3000个memcached节点,储存数千G的缓存。

 

  转载请注明出处哈: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(无底洞)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
22天前
Elasticsearch【问题记录 02】【不能以root运行es + max virtual memory areas vm.max_map_count [65530] is too low处理】
【4月更文挑战第12天】Elasticsearch【问题记录 02】【不能以root运行es + max virtual memory areas vm.max_map_count [65530] is too low处理】
21 3
|
4月前
|
关系型数据库 MySQL
innodb_buffer_pool_size 配置文件设置的值和查询的值怎么不一致
您可以配置缓冲池大小 脱机或在服务器运行时。中描述的行为 本节适用于这两种方法。更多信息 关于在线配置缓冲池大小,请参阅在线配置 InnoDB 缓冲池大小。InnoDB 当增加或减少innodb_buffer_pool_size时, 操作以块的形式执行。块大小由 innodb_buffer_pool_chunk_size 配置选项定义,该选项的缺省值为 。有关更多信息,请参阅配置 InnoDB 缓冲池区块大小。128M 缓冲池大小必须始终等于 innodb_buffer_pool_chunk_size * innodb_buffer_pool_instances 的倍数或倍数。 如果将in
|
19天前
|
索引
filebeat 设置索引的 max_result_window
在 Filebeat 中设置索引的 max_result_window 需要修改 Elasticsearch 的索引模板。max_result_window 参数定义了在 Elasticsearch 中执行搜索时,最大返回文档的数量。默认情况下,该值为 10000。 要修改该值,可以按照以下步骤操作: 打开 Filebeat 的配置文件。 找到输出部分,其中定义了 Elasticsearch 输出。 在 Elasticsearch 输出配置中,找到索引模板相关的配置。 确保你已经定义了自定义的索引模板(如果没有,请创建一个)。 在索引模板中,设置 max_result_window 参数为
|
7月前
|
缓存 关系型数据库 MySQL
【异常解决】缓存报错:Null key returned for cache operation (maybe you are using named params on classes withou
【异常解决】缓存报错:Null key returned for cache operation (maybe you are using named params on classes withou
219 0
|
10月前
|
测试技术
pg_rewind实例--could not find previous WAL record at %X/%X
pg_rewind实例--could not find previous WAL record at %X/%X
59 0
报错FileSystemException: /datas/nodes/0/indices/gtTXk-hnTgKhAcm-8n60Jw/1/index/.es_temp_file
首先我碰到的问题是服务器突然断电导致elasticsearch宕机,当我再次启动的时候 >FileSystemException: /data/elasticsearchDatas/datas/nodes/0/indices/gtTXk-hnTgKhAcm-8n60Jw/1/index/.es_temp_file: 结构需要清理
141 0
报错FileSystemException: /datas/nodes/0/indices/gtTXk-hnTgKhAcm-8n60Jw/1/index/.es_temp_file
|
SQL 关系型数据库 MySQL
MGR修改max_binlog_cache_size参数导致异常
MGR修改max_binlog_cache_size参数导致异常
133 0
MGR修改max_binlog_cache_size参数导致异常
|
SQL 存储 Oracle
PostgreSQL 分页, offset, 返回顺序, 扫描方法原理(seqscan, index scan, index only scan, bitmap scan, parallel xx scan),游标
PostgreSQL 分页, offset, 返回顺序, 扫描方法原理(seqscan, index scan, index only scan, bitmap scan, parallel xx scan),游标
3740 0
|
缓存 算法 Java
Elasticesearch内存详解(五)——Node Query Cache
接收Elasticesearch内存中的Node Query Cache
459 0
|
算法 开发者
关于 加载图片"Corrupt JPEG data: premature end of data segment" 的解决方法
关于 加载图片"Corrupt JPEG data: premature end of data segment" 的解决方法
关于 加载图片"Corrupt JPEG data: premature end of data segment" 的解决方法