1.总结本文将告诉大家分布式文件系统HDFS在大容量时如何进行性能优化有多少客户端同时写入数据?2、背景介绍首先介绍一个小背景。如果多个client同时想在HadoopHDFS上并发写一个文件,可以吗?显然不能接受,因为HDFS上的文件是不允许并发写入的,比如并发追加一些数据。所以在HDFS中有一种机制叫做文件契约机制。也就是说,同一时刻只有一个client可以获取到NameNode上的一个文件的contract,然后才能写入数据。此时如果其他客户端尝试获取文件合约,将获取不到,只能等待。通过这种机制,可以保证一次只有一个客户端在写一个文件。获取到文件契约后,在写文件的过程中,客户端需要开启一个线程,不断的向NameNode发送更新文件的请求,并告诉NameNode:NameNode兄弟,我还在写文件呢,你给我可以一直遵守那个合同吗?并且NameNode内部有一个专门的后台线程,负责监控每个合约的续约时间。如果长期没有续签合同,此时合同自动失效,让其他客户代写。说了这么多,老规矩,这里放一张图让大家直观感受整个过程。3.问题突出。现在问题来了。如果我们大规模部署一个Hadoop集群,可能同时有上万个客户端。这时候NameNode内部维护的文件合约列表会非常非常大,监控合约的后台线程需要经常定时检查所有合约是否已经过期。比如每隔几秒就遍历大量的合约,势必会导致性能不佳,那么这种合约监控机制显然不适合hadoop集群的大规模部署。4.优化方案那么如何优化文件合约监控算法呢?下面我们一步步看一下它的实现逻辑。首先我们来看看下面这张手绘图:其实谜男很简单。客户端每次发送续约请求时,都会设置这个合约的最晚续约时间。然后基于一个TreeSet数据结构,将合约按照最晚续约时间排序,每次续约时间最早的合约排在第一位。这种排序后的合约数据结构非常重要。TreeSet是一种可排序的数据结构,其底层实现基于TreeMap。TreeMap底层是基于红黑树实现的,可以保证元素不重复,也可以在每次插入元素时按照我们自己定义的排序规则进行自定义排序。所以这里是我们的排序规则:按照合约的最新续约时间排序。其实这个优化就是这么简单,就是维护这样一个排序好的数据结构。现在来看一下Hadoop中合约监控的源码实现:每次检查一个合约是否过期,不想遍历几千个合约,当然遍历效率会很低。我们可以从TreeSet中获取续约时间最早的合约。如果续约时间最早的合约还没有到期,那么就不用继续查了!这意味着续约时间更近了那些合同永远不会到期!比如:最旧续约时间的合约,最晚续约时间是10分钟前,但是我们判断合约到期时间限制是超过15分钟合约就会到期。这个时候连10分钟前续约的合约都没有到期,那么8分钟前和5分钟前续约的那些合约肯定不会到期!这种机制的优化对于性能的提升是很有帮助的。因为正常情况下,过期的合约肯定还是少数,所以没必要每次都遍历所有的合约来检查是否过期。我们只需要检查续订时间最早的合同。如果合同到期,删除该合同,然后检查第二旧的合同。等等。通过这种TreeSet排序+最老合约优先级检查的机制,可以有效提升大规模集群下合约监控机制的性能至少10倍。这个理念值得学习和借鉴。给大家稍微扩展一下,在SpringCloud微服务架构中,Eureka作为注册中心,其实有一个合约续签检查机制,这个机制和Hadoop类似。而Eureka中并没有实现类似的更新优化机制,而是每一轮暴力遍历所有服务实例的更新时间。如果你面对的是大规模部署微服务系统,情况就不好了!部署了一个几十万机器的大型系统,几十万个服务实例的更新信息驻留在Eureka内存中,是否需要每隔几秒遍历一次几十万个服务实例的更新信息?最后提醒大家,优秀的开源项目包含着很多优秀的设计思想。看各种优秀的开源项目的源代码,是一种在短时间内快速大幅度提高自己的技术水平和技术水平的方法。你不妨试一试。
