转载:https://blog.csdn.net/breakout_alex/article/details/107499035?utm_medium=distribute.pc_relevant.none-task-blog-baidulandingword-1&spm=1001.2101.3001.4242
参考:https://blog.csdn.net/qq_33440092/article/details/103863218
Hdfs双缓冲机制
问题
Hdfs的Namenode如何抵抗住客户端发起的高并发请求,主要是元数据的修改和更新,背景是hdfs的元数据是有两份一份是NN中的内存元数据,一份是fsimage+edits文件(磁盘)。回忆之前提到过的写数据流程,对于修改元数据的动作,比如上传一个文件,创建新的目录等都需要先写入edits并要把元数据变化写入到NN的内存元数据。最消耗性能的就是edits写磁盘的动作存在IO开销。
例子
每次请求NN修改一条元数据,比如申请上传一个文件,需要在内存目录树中加入一个文件,都要写一个edits log,写edits log的两个步骤
- 写入本地磁盘
- 通过网络传输给JournalNodes集群
针对写入本地磁盘文件
大量客户端同时写会导致写入本地磁盘文件时出现多线程安全问题,HDFS如何保证安全呢?
两个方面
- 对每个写入的edits log分配一个全局顺序递增的transactionid(txid),基于这个序号可以标识每个edits log的先后顺序。
针对txid,要保证全局顺序一致,就要加锁保证安全,也就是每个修改元数据的线程都要先拿到锁然后生成txid才能写入edits log。
怎么设计呢?如下图设计会存在什么问题?
我们发现NN本身可以用多线程接收多个客户端发送过来的并发请求,但是如果按照上面的设计会发现多个线程修改内存元数据之后,在串行的写editslog,这里面会有两大性能杀手,本地磁盘+网络传输。如果真是如上设计NN可以支撑的并发也就每秒几十个。
HDFS解决方案
其中一个解决方案就是把释放锁的动作前移,也就是在获取到锁生成txid之后,就把数据写入缓冲区就释放锁而不是落磁盘网络传输之后再释放锁。但是事情不能这么就解决了,我们知道缓冲区也是有大小限制,所以缓冲区数据达到一定大小后还需要定期刷写到磁盘,但是一块内存不能同时并发读写一块内存数据。
因此HDFS引入的双缓冲机制,把一块内存划分为两个部分:
一个部分用于写入数据
一个部分用户读取后写入磁盘和Journalnode