FastDFS V3引入合并存储(trunk file)特性后,有用户反馈上传文件提示trunk空间被占用的问题。我在测试环境中经过一通测试,在极其偶然的情况下也能重现这个问题。然后就开始排查这个问题。
FastDFS一个group(存储分组)内有一台storage server被选举为trunk server,用于管理和分配该组的trunk可用空间。为了高效管理trunk file的可用空间,我们使用了平衡二叉树 AVL。我们很自然地怀疑trunk空间管理和分配出了bug。于是对管理和分配trunk空间的代码前前后后做了不下10遍的代码review,直到看花眼了,也没有发现任何问题。也怀疑过AVL实现有bug,于是写单元测试对AVL进行了大量测试,也没有发现任何问题。
这个问题很难复现,尝试通过代码review解决,但多次无功而返。合并存储这个潜在bug一直存在,导致合并存储存在风险,我心里很忐忑。
到了2017年初,我再次尝试解决这个困扰多年的bug。既然代码排查没有任何效果,那就想办法重现吧。于是我开始通过小规模压力测试试图复现这个问题,通过上传和删除文件并行,问题终于得到复现,并且多次压测可以大概率复现。这次我盯住trunk空间分配的binlog,写脚本进行分析和排查,发现binlog记录本身是正确的。但在发生trunk空间冲突的时间点,从binlog中发现一个trunk空间被回收后几乎立即就被分配出去了,我凭直觉抓住了这条关键线索。
继续review代码,然并卵,依然一无所获。业界有个说法我比较认可:问题能够稳定复现,就等于解决了一大半。在这么明显的线索的指引下,我终于转变了思路,开始思考这个成精的bug是否是多机环境导致的。然后。。。,经过反复推敲,我终于终于想明白了这个bug是如何被触发的了:
多机环境下操作时序问题。
以前的排查重心在trunk空间管理,经反复验证,这块是没问题的。问题在于一个group的多台storage server均可执行文件上传操作,而FastDFS对文件操作分发(复制)到其他存储节点采用异步方式,一个trunk空间的回收和再利用机制本身没有问题,但storage server在其trunk file上存放用户上传的文件时,就可能会因时序问题而导致冲突(trunk server返回该空间可用,但因文件同步延迟导致实际还在被其他文件占用)。具体如何引起乱序和冲突的,留给各位读者去思考。
问题的现象和原因找到后,解决方法就很容易了:指定group中的一台storage server上传文件即可。FastDFS默认配置是轮流(round robin)上传到各台storage server的,通过tracker.conf配置文件中的store_server这个参数来设置。贴一下配置示例:
# which storage server to upload file
# 0: round robin (default)
# 1: the first server order by ip address
# 2: the first server order by priority (the minimal)
# Note: if use_trunk_file set to true, must set store_server to 1 or 2
store_server=0
千万不要小看Note这一句话,其背后是满满的辛酸和血泪啊!
补充说明一下,在开启合并存储,即use_trunk_file设置为true的情况下,为了避免上述乱序问题,若store_server设置为0的话,程序将强制调整为1。
V3最后一个版本是V3.11,通过查看HISTORY文件,其发布日期为 2012-08-04。直到2017-03-29,终于修复了trunk文件空间偶发冲突的问题。贴出HISTORY文件中的changelog为证(git log也可以查到):
Version 5.10 2017-03-29
* adjust parameter store_server when use_trunk_file is true
一个修复了约5年的bug,必须记录在案。
本文分享自微信公众号 - FastDFS分享与交流(fastdfs100)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。