- hbase中, 假设server A持有锁,之后在准备写入sstable文件时由于GC导致了进程暂停,在此期间由于租约过期,Server B获得了锁,并且试图写入sstable文件,A从GC中恢复过来后也尝试修改数据,导致文件数据被写乱。
- 解决办法: 每次授予租约时,锁服务同时返回一个全局递增的fencing令牌,并且要求存储系统记录最近已经完成的最大令牌号同时拒绝掉令牌号更低的写请求。这样如果Server B获得了锁,就会以更高的令牌号向文件系统写入数据,当Server A恢复过来时,由于文件系统已经接受了更高的令牌号,因此可以拒绝掉server A的写请求。
- 对于离线任务而言,可以采用更简单的办法。每次任务产出都写入新的文件,文件末尾通过magic string或者更复杂的校验码检测文件完整性,如果有任务僵死,那么新任务启动后,检测旧任务留下的文件是否完整,如果文件完整则按照在之前的进度继续工作,否则删除此次产出的文件,从上一次正确的数据点开始重做(重做的数据来源可以从WAL中读取)。旧任务恢复后,继续之前的写操作会失败(由于正准备写入的文件已经别其它任务删除),然后任务可以尝试原地重启,重新获取租约,此时由于新任务已经获取了租约,因此旧任务可以安全退出
- 从上文可以看出,进程中不可控制的GC导致的停顿会带来灾难性的后果,解决GC的方法在这里列出以下两种
- 将GC暂停视作计划内的临时理线,当节点启动GC时通知其他节点来接管客户端的请求。
- 只对可以快速回收的短期对象执行垃圾回收,然后定期重启进程,避免对长期存活对象执行全面回收。