# LEC-PR **Repository Path**: JimmyYangMJ/LEC-PR ## Basic Information - **Project Name**: LEC-PR - **Description**: 分布式存储系统中,纠删码恢复系统 - **Primary Language**: Java - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2023-03-06 - **Last Updated**: 2024-06-05 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 流程 ## 1. 局部校验块编码 master 向 slaves 发送局部编码指令 长连接:等待 slaves 回复:确认码 + 运行时间 + 生成的局部条带数 ## 2. 局部校验块布局 master 根据每个节点生成的局部条带总数 生成 局部校验块布局方式 slave 接收到 校验块的放置的目标节点 自主选择 迁移的局部校验块 1. 查询 短连接,判断累计接收的ACK 确定一轮传输结束 # class 说明 ## Master —— namenode MasterCMDListen.class 用于接收slave节点的确认命令 * 实现: 独立线程,使用 NIO 的非阻塞模式 监听 slave 节点的确认命令 接收到命令后,根据 ack 类型 push 到 volatile 修饰的 Queue(ackQueue 或 ackDecodeQueue)中 ## Slave —— datanode 标识符含义: HDFS 条带 stripeId 局部条带 localStripeId::Long e.g. -9223372036854659294 localParityBlkName::String , e.g. -9223372036854659294_0 localParityBlkIndex::Integer 校验块在局部条带的校验块组中的相对位置 localStripeBlkIndex::Integer 数据块在局部条带中的位置 ### 默认参数 默认恢复的数据块 存放在 第0个磁盘 ## 用到的设计模式 1. 创建型模式 2. 结构型模式 3. 行为型模式 1. 策略模式: new DataReceive(new MySocketNIOImpl()).start(); // 数据接收 线程 可用 MySocketImpl 替换 MySocketNIOImpl 2. 责任链模式 ## 运行 1. 更新 lecpr 字节码文件 2. 运行 python start.py 3. 先启动从节点,后启动主节点 [Tips] 测试文件存放目录: /home/ ### 从节点命令: java -jar /home/LECPR-Slave/LECPR-Slave.jar ### 主节点命令: 多磁盘恢复: - lecpr * `java -jar /home/LECPR-Master/LECPR-Master.jar lecpr-multi <恢复块个数>` - 全迁移 * `java -jar /home/LECPR-Master/LECPR-Master.jar m-multi <恢复块个数>` 单磁盘恢复 - (同构) * ` java -jar /home/LECPR-Master/LECPR-Master.jar lecpr <恢复块个数> ` - (网络异构) * `java -jar /home/LECPR-Master/LECPR-Master.jar lecpr_bandwidth <恢复块个数> <所用方法>` * 所用方法:1:仅方法1, 2:仅方法2, 4:仅方法三 - 全迁移 `java -jar /home/LECPR-Master/LECPR-Master.jar m 30 0 0` ## 测试文件 1. /home/diskPlace 每个节点的所有磁盘标识 ![img.png](img.png) 2. /home/proactiveDiskInfo-%d-%d",desIPIndex,diskId 某节点的某磁盘信息 ![img_1.png](img_1.png) 3. /home/parseLog.txt 当前集群中条带数据块分布 ## [Tips] 该项目中遇到的问题 和 解决方式 ### java.util.ConcurrentModificationException 执行 map 对象的 查看 size , 遍历 value() 、 执行keySet().toArray() 方法时, 如果另一个线程对其进行 修改操作会报ConcurrentModificationException错误 - 解决方法:ConcurrentHashMap HashMap> 改为了 HashMap> ### map 的size 和实际元素数量 不一样 普通HashMap方法 的 size() 方法 和实际keySet().toArray()中元素个数 在多线程中可能存在不一致现象,例如,map中已经push元素,但是size还没修改 - 解决方法:改为ConcurrentHashMap ### volatile 赋值问题 当一个 volatile 变量 赋值给 一个普通变量时,并不能转移 volatile 的特性 ### 通过 NIO 零拷贝 加快节点内 数据复制 和 网络传输 transferTo() 方法 ## fileChannel.transferTo / transferFrom 阻塞问题 ping 目标机器 查看 其中 time 和其他机器是否有明显区别 运行独立Java测试样例, 重启机器试试 ### 使用线程池,多线程数据块复制(增加CPU时间) ## DirectByteBuffer 的内存回收问题 一开始通过System.gc() 回收内存,但是DirectByteBuffer在申请内存时,如果不够会自己触发GC DirectByteBuffer构造函数中Bits.reserveMemory(size, cap)方法 会触发System.gc() ![img_3.png](image/img_3.png) 如果还是超过限制,则抛出java.lang.OutOfMemoryError. ## 连接线程太多 创建连接线程池