@HUST张友东 work@taobao zyd_com@126.com
分类: 大数据
2013-01-19 18:45:32
昨天下午线上辅集群加机器扩容,扩容的机器在运行一段时间后线上有block lost的告警,从Nameserver(NS)的日志上发现,扩容的新机器上有多次加入集群和退出集群的记录,最初我怀疑是扩容后,集群做容量负载均衡,大量数据往新加入的节点迁移,导致新机器负载高,从而出现心跳信息没有及时到达NS的情况,此时NS认为Dataserver(DS)宕机,如果有一个block的多个副本都被迁入到新扩容的机器中,则可能出现某一段时间NS认为block已经丢失,但实际上block仍然正常存在的;查看NS最新的日志后发现,block可能丢失的日志一直都存在,于是开始找DS的问题。
从已丢失block列表中选取一个block,查找block创建记录,发现其13:23时刻在A、B两个DS上创建,从A的日志发现,A在13:32时刻被强制kill,并很快被启动了,从日志中找该block的记录,发现在被kill前的确有创建block的记录,但重启后,完全没有跟该block相关的记录,block莫名奇妙的不见了,只有一种可能性,第二次重启前,文件系统被重新格式化过。
跟PE同事确认后,发现问题在于运维平台上的上线请求被提交了两次(第一次提交后,页面没什么动静,PE以为有问题,刷新了一下页面),为什么提交两次会有问题? 后台在服务DS上线请求时,如果发现有DS进程在运行,则会先将其强制kill,然后格式化文件系统,再启动DS进程。
这里有两个设计相关的问题: (1) 发送请求后页面没动静。 (2) 上线DS时,强制先下线。
对于问题(1):用户提交请求后,如果任务需要执行很长时间,可以给用户一些友好的提示,比如告诉用户请求已经收到,后台正在执行,大概需要多长时间之类的信息; 如果请求在语义上不能重复提交,就应该使用技术手段显式阻止用户重新提交其请求。
对于问题(2): 接口的语义应该尽量简单,比如向用户提供上线、下线服务器的接口,上线的语义应该是把一个原来不在集群中的DS加入到集群;下线就是把原来在集群中的DS从集群中移除;如果上线时发现机器上已有DS在运行,这样是不满足上线条件的,则直接把问题抛给请求者,请求者发现有进程在运行,须先确认情况,如果发现的确需要把正在运行的DS下线掉,他就需要先执行一次下线操作,再重新上线。