刚刚毕业进入工做岗位第一个任务是重构分布式缓存的console。不太重构是后面的事情,原由是对console的rebalance算法作简化。若是你有兴趣能够翻看我第一篇blog,里面解析了新rebalance算法。算法来自于豌豆荚的codis,为了搞懂他的思想,我看了codis rebalance的源码,并在github上跟向做者提问,终于彻底搞懂了。下面会记录一下重构这个项目的过程。java
首先说明一下缓存console的功能:git
console主要功能是控制。二维表是console的核心数据结构,重构前他的结构是第0行为缓存主机,第1行第一个备机,第二行是第二个备机,以此类推。纵向看index是桶号,0号桶的主备机,1号桶的主备机,以此类推。切换成组以后的不一样是一个组包含了主机和备机,而对于缓存client来讲他只能看到主机,因此,新的二维表只有一行,表中的内容从机器地址扩展为group对象,增长了字段和功能。github
上面罗列的console功能中屡次出现不一样功能的二维表,在zk上有三张不一样功能的二维表,他们共同为client、console、引擎提供组信息。第一张是c表,是client看到的组的分布状况;第二张是m表,存放“旧”数据;第三张d表存放“最终结果”数据。算法
新算法对增长组进行rebalance计算,如果宕机则须要人工介入,重启宕掉的组。做为组出现,即主备机同时宕掉的概率极低,若是主机宕掉,备机顶上来。新增组后,作rebalance,其算法思想很简单明了,很好理解。根据上来组的内存大小按比例分配多少个桶(bucket or slot)“落在”哪一个组中。越大的组分配越多的桶。这个前提是认为各个桶的分配是均衡的。算法详情点击这里。缓存
思路很清楚,须要新增两个zkChildListener,分别监控组和迁移结果的变化。经过对比二维表和zk上组路径下子节点的数量和子节点的内容,就能够判断有哪些组是新增的、哪些组宕掉了。若是当掉了,三张表中对应位置组置为0。client看到0会报错,console同时也会在宕机逻辑中报错,且还会有一个线程持续检查是否有宕机状况。组减小的处理状况很简单,不过也是最合理的。由于尽管宕机这种事情“必然”会发生,但频率很低,用人工介入代替复杂的算法逻辑是合理的。不过增长组的逻辑就稍微麻烦一些。session
最正常的状况是新增组是三张表是相同的,没有宕机和迁移这两种状况。那么正常rebalance,将“最终结果”写入d表,m表中就变成了“旧”数据,将c表中迁移的源组置为只读。例如(1 : 192.168.0.1:33661, 2 : 192.168.0.2:33661....) : m表111222,增长3,d表变为113223,须要迁移的是二、5号桶、迁移的源和目的也能得出。数据结构
若是正在迁移,新增组这种状况不会发生,由于这里有其余模块控制这种异常状况,但确实是一种异常状况。这种异常很复杂,须要处理不少复杂逻辑。架构
若是是有宕机的状况,新增组,这种异常的思路是“填回去,不计算”。既然有空位为何不直接填回去,干吗还要rebalance,原先也必定是平衡状态。宕机也分为两种,一种是旧组宕掉,一种是新组宕掉。其区别是对不一样的二维表作操做,缘由是m、d表的数据不相同。分布式
迁移就更简单明了,你也应该能感受到,对比m、d表计算出须要迁移,监控migration节点子节点变化,引擎完成一个桶的迁移,写一条记录,触发一次计算。迁移结束更新三张表。测试
不过以上这些结论都是通过几回作错、再重构后得出的,毕竟架构师不会把太多的时间放在我身上。。。
关于第5点功能,我遇到了zk的bug,若是你也遇到过能够交流一下。console的主备是依靠注册到zk上的顺序决定的。会在一个临时节点中存master的值。但这个临时节点在zk server停掉后没有消失,随即报错。这个问题我还要测一下。。醉了,其余的都蛮简单的就略过了。。
----------------------------------------------------------------分割线--------------------------------------------------------------------
这个并非zk的bug,测试时由于机器宕机,但在zk服务端,旧的session还没过时,session的过时时间是30s,形成临时节点没有释放。其实规避方法很明显有两种,一是重连间隔 > 30s,二是建立节点以前要判断节点是否exists。
因为是公司的项目须要保密,只能说一下思想,源码就不贴了,其实贴了也没太大的意义,除非把,,哦,对了,这个分布式缓存已经开源,但新console还没开源,但愿感兴趣的同窗能在github上跟主创交流,开源代码点击这里。