对于一个分布式存储系统来说,数据是分散存储在多个节点上的。如何让数据均衡的分布在不同节点上,来保证其高可用性?所谓均衡,是指系统中每个节点的负载是均匀的,并且在发现有不均匀的情况或者有节点增加/删除时,能及时进行调整,保持均匀状态。本文将探讨Elasticsearch的数据分布方法,文中所述的背景是Elasticsearch 5.5。
  
    在Elasticsearch中,以Shard为最小的数据分配/迁移单位。数据到节点的映射分离为两层:一层是数据到Shard的映射(Route),另一层是Shard到节点的映射(Allocate)。
  
    一方面,插入一条数据时,ES会根据指定的Key来计算应该落到哪个Shard上。默认Key是自动分配的id,可以自定义,比如在我们的业务中采用CompanyID作为Key。因为Primary Shard的个数是不允许改变的,所以同一个Key每次算出来的Shard是一样的,从而保证了准确定位。
  
  shard_num = hash(_routing) % num_primary_shards
  
  1
  
    另一方面,Master会为每个Shard分配相应的Data节点进行存储,并维护相关元信息。通过Route计算出来的Shard序号,在元信息中找到对应的存储节点,便可完成数据分布。Shard Allocate的映射关系并不是完全不变的,当检测到数据分布不均匀、有新节点加入或者有节点挂掉等情况时就会进行调整,称为Relocate。那么,Elasticsearch是根据什么规则来为Shard选取节点,从而保证数据均衡分布的?概括来看,主要有三方面的影响:节点位置、磁盘空间、单个节点上的Index和Shard个数。
  
  节点位置
  
     对于一个ES节点来说,它可能是某台物理机器上的一个VM,而这个物理机器位于某个Zone的某个机架(Rack)上。通过将Primary Shard和Replica Shard分散在不同的物理机器、Rack、Zone,可以尽可能的降低数据丢失和系统不可用的风险,这一点几乎在所有的分布式系统中都会考量。
  
     Elasticsearch是通过设置awareness.attribute对集群中的节点进行分组,从而实现Rack和Zone的发现。比如按照下列方式对elasticsearch.yml进行配置,再启动相应的节点,即可实现Zone的区分。
  
  // elasticsearch.yml
  
  cluster.routing.allocation.awareness.attributes: zone
  
  // 启动ES
  
  ./bin/elasticsearch -Enode.attr.zone=zone_one
  
  ./bin/elasticsearch -Enode.attr.zone=zone_two
  
    实践中,如果使用了这样的Awareness机制,应该保证不同分组类的机器个数一致,不会发生倾斜。比如,在Zone Awareness下,如果集群有10台机器,应该保证每个Zone各有5台机器(2个Zone)。
  
  磁盘空间
  
    磁盘空间是制约存储的硬性条件,单机的可用磁盘空间决定了能否继续往这个节点写入新数据、分配新Shard以及是否需要迁移数据等。在ES中,有三个参数用来控制与此相关的特性,默认每30秒检查一次。
  
  cluster.routing.allocation.disk.watermark.low: 默认为85%,超过这个阈值后,就不允许往这个节点分配Shard。
  
  cluster.routing.allocation.disk.watermark.high:默认为90%,超过这个阈值后,就需要将该节点的Shard迁移出去。
  
  cluster.routing.allocation.disk.watermark.flood_stage:默认为95%,超过这个阈值后,与该节点上的Shard有关的Index都变成只读,不允许写入数据。
  
  单个节点上的Index和Shard个数
  
    在满足节点位置和磁盘空间的条件后,单个节点上的Index和Shard个数是否均匀,决定了Shard可以分配/迁移到哪个节点。ES通过计算权值来量化这样的分配方式。
  
    以检测某个Shard是否需要迁移到其他节点为例,ES会先计算该Shard所在节点(A)的权值,然后依次跟其他节点的权值比较,如果与节点B的差值(Delta-A)超过了阈值,再进一步计算节点A去掉该Shard后的权值与节点B增加该Shard后的权值之间的差值(Delta-B),如果Delta-A大于Delta-B,则表明Shard可以迁移到节点B。
  
    这里的权值计算简化如下,其中indexBalance与shardBalance分别由参数控制,而阈值由cluster.routing.allocation.balance.threshold设置,默认为1.0f。当然,这里只描述了核心思想,详细逻辑请阅读BalancedShardsAllocator.java中的源码。通过调整三个参数,可以控制策略的松紧。
  
  // indexBalance = cluster.routing.allocation.balance.index, default is 0.55f
  
  // shardBalance = cluster.routing.allocation.balance.shard, default is 0.45f
  
  float sum = indexBalance www.yinmaoyule178.com+ shardBalance;
  
  float theta0 = shardBalance / sum;
  
  float theta1 = indexBalance / sum;
  
  private float weight(Balancer balancer, ModelNode node, String index, int numAdditionalShards) {
  
  final float weightShard www.dfgjpt.com= node.www.ysyl157.com numShards(www.dasheng178.com) + numAdditionalShards - balancer.avgShardsPerNode();
  
  final float weightIndex = node.numShards(index) + numAdditionalShards - balancer.avgShardsPerNode(index);
  
  return theta0 * weightShard + theta1 * weightIndex;
  
  Primary与Replica分布
  
    最初关注Elasticsearch的数据分布,是因为在性能调优时遇到了一个与Primary/Replica分布有关的问题。背景是这样的,为了能够复用单个节点上的Disk Cache,我们对查询请求进行了限制,只允许其访问Primary Shard。然而总是有那么一两台机器的查询会被Queue住,通过调研发现,这些机器上面的Primary Shard比其他机器多(对某一个Index而言),即下图中左边所示,而我们希望的是右图所示的均匀分布。
  
    引起这个问题的根源是,Elasticsearch中的Shard均匀分布是针对Primary+Replica整体而言的,也就是说没法做到只针对Primary Shard单方面做均匀分布,所以才会出现下图左边所示,某个节点上有3个Primary Shard,而另一个节点只有1个。目前尚未发现可以调节的地方。

谈Elasticsearch下分布式存储的数据分布相关推荐

  1. python中文字符串编码_浅谈python下含中文字符串正则表达式的编码问题

    前言 Python文件默认的编码格式是ascii ,无法识别汉字,因为ascii码中没有中文. 所以py文件中要写中文字符时,一般在开头加 # -*- coding: utf-8 -*- 或者 #co ...

  2. shell for循环1到100_浅谈Linux下shell 编程的for循环常用的6种结构

    浅谈Linux下shell 编程的for循环常用的6种结构 1. 常用for循环结构 (1) for 变量 in 值1 值2 值3... do 程序块儿 done (2) for 变量 in `命令` ...

  3. Linux系统常用函数,浅谈linux下的一些常用函数的总结(必看篇)

    1.exit()函数 exit(int n)  其实就是直接退出程序, 因为默认的标准程序入口为int main(int argc, char** argv),返回值是int型的. 一般在shell下 ...

  4. 百度、支付宝、今日头条先后被约谈,下一个会是谁?

    点击上方"CSDN",选择"置顶公众号" 关键时刻,第一时间送达! 前有BAT,后有TMD,曾几何时,BAT和TMD的格局也会被打乱?如今,百度.支付宝.今日头 ...

  5. python打开文件夹中的tiff_浅谈python下tiff图像的读取和保存方法

    对比测试 scipy.misc和 PIL.Image和 libtiff.TIFF三个库 输入: 1. (读取矩阵) 读入uint8.uint16.float32的lena.tif 2. (生成矩阵) ...

  6. Linux命令删除find,浅谈Linux下通过find命令进行rm文件删除的小技巧

    我们经常会通过find命令进行批量操作,如:批量删除旧文件.批量修改.基于时间的文件统计.基于文件大小的文件统计等,在这些操作当中,由于rm删除操作会导致目录结构变化,如果要通过find结合rm的操作 ...

  7. 计算机病毒的隐藏方式有ign,浅谈windows下的病毒隐藏技术.doc

    浅谈windows下的病毒隐藏技术 浙江工业职业技术学院 毕业论文 (2011届) 浅谈windows下的病毒隐藏技术 学生姓名 学 号 分 院 专 业 信 指导教师 完成日期 2011年5月 19日 ...

  8. linux cp mv区别,浅谈Linux下mv和cp命令的区别

    1.功能上的区别 mv:用户可以使用该命令为文件或目录重命名或将文件由一个目录移入另一个目录中. cp: 该命令的功能是将给出的文件或目录拷贝到另一文件或目录中. 2.从inode角度来区分 mv:会 ...

  9. linux gz文件压缩比,浅谈Linux下各种压缩 解压命令和压缩比率对比.doc

    浅谈Linux下各种压缩 解压命令和压缩比率对比 浅谈Linux下各种压缩 解压命令和压缩比率对比 Linux下压缩.解压命令五花八门,不像在windows下一个winrar打遍天下无敌手,清一色的. ...

最新文章

  1. mysql excel 命令行_MySQL 命令行数据导出到 Excel
  2. Java 连接 MS sql Server 2005
  3. Centos搭建PHP5.3.8+Nginx1.0.9+Mysql5.5.17
  4. how can we make wise decisions?
  5. 【nginx配置】 proxy_pass反向代理配置中url后面加不加/的说明
  6. ASP.NET 开发人员不必担心 Node 的五大理由
  7. 怎样实现一个简单的jQuery编程
  8. 解读Mybatis数据库开发框架
  9. 实战系列-IDEA中Spring MVC实现接口功能
  10. oracle10G分区的创建与维护Oracle分区表和本地索引
  11. 前景检测算法(十五)--LOBSTER算法
  12. 日更第4期-2015-1-19-openFrameworks系列第三讲-面向对象的小球们
  13. paip.声音按键音延迟的解决
  14. MATLAB实现FFT算法
  15. 服务器系统如何清理,服务器清理内存怎么清理
  16. IPD在华为成功的6个原因
  17. 经纬度转换度分秒工具
  18. Qt中undefined reference to报错的三种可能性和解决方法(以libgdal为例)
  19. Unable to initialize EGL
  20. F - 郭鑫的难题(三)

热门文章

  1. android 根据文件Uri获取图片url
  2. android 如何终止线程
  3. .Net Framwork概述
  4. Dalvik线程模型
  5. 2016年华为校招上机考试试题答案
  6. (三)Docker四种网络模式
  7. SDNU 1029.巧分整数(斯特林数(改)dp)
  8. 2019牛客暑期多校训练营(第八场)G Gemstones(模拟)
  9. js - 浅拷贝和深拷贝
  10. 简单线性回归预测实现