图片来自Pexels自从上次被拉进群聊后(那天被拉进了一个Redis群聊...),我已经从一个人单打独斗变成了团队合作。Redis的新烦恼,感谢小伙伴们的共同努力,不仅有主从复制做数据备份,还有哨兵节点做监控管理,我现在可以拍拍胸脯说我们是高可用服务!然而,快乐的日子并没有持续太久,我们就不再笑了。不知道是我们做的太好了,还是业务发展太快了。程序员越来越依赖我们,什么都写给我们,数据量越来越大。我们这个年纪承受着不该有的压力~虽然有主从复制+sentinel,但是只能解决高可用的问题,不能解决大数据量的问题!因为我们看起来人数很多,但是他们都存储了全量数据,所以对增加数据容量没有帮助。集群时代那天,我找到了大白和小黑。我们三个总结了一下。一个节点的力量不足,但每个人都可以扬帆远航。我们决定把三个人的内存空间“合二为一”,每人负责一部分数据,演变成一个大的缓存服务器,进入集群时代!集群,集群,首要问题当然是团队建设!我们要想办法组队,还要考虑以后扩张的可能性,会有新的伙伴加入我们,我们三个憋了很久,抄三路TCP的握手,也想出了一个握手协议。如果你想加入集群,你必须有一个介绍人,通过团队的任何成员。以我为例,你只要告诉我IP和端口,我就给他发MEET消息发起握手,对方回复我PONG消息同意入群,最后我会给他回一个PING信息,三次握手就完成了!然后,我会把这件事告诉团队的其他成员,新伙伴就正式成为我们的一员了。第二个很重要的是解决数据存储的公平性问题。不能旱死,不能涝死。我们争论了很久,最后决定借鉴别人的哈希表。我们一共划分了16384个哈希桶,我们称之为slotslots,程序员可以根据自己的能力分配一部分slots给我们每个人。比如我们队:我:0-4000大白:4001-9000小黑:9001-16383我比较好,只拿到了4000个名额。小黑哥最辛苦,负责7000+槽位,俗话说能力越大,责任越大,谁叫他内存空间最大。读写数据时,对key值做hash计算,谁负责映射到哪个slot。为了让大家对信息达成共识,在开始的时候,大家要告诉其他小伙伴自己负责的slot信息。总共有超过10,000个插槽。要通知其他合作伙伴,需要传输的数据量是相当大的。后来,我们三个又商量了一下。为了压缩数据空间,每个slot简单的用一个bit来表示,你负责就是1,否则就是0,一共只有16384位,也就是2048字节,很容易传输速度快。刚刚发送。structclusterNode{//...unsignedchar*slots[16384/8];//...};这种方式传输的数据是轻量级的,但实际工作时还是不方便。遇到读写数据的时候,总是看不到每个人的都是1,简单的一步到位,用空间换时间,我们准备了一个超大的数组来存放哪个节点负责每个插槽。通过上述方法获取到信息后,更新这里:structclusterNode*slots[16384];这样在遇到数据访问的时候,我们可以很快的知道数据的负责人是谁。对了,这16384个slot必须有人看管,这样我们整个集群才能正常工作,处于online状态,否则就是offline状态。想一想,如果没有人负责key-valuehashmap之后的slot,应该从哪里读,写到哪里呢?所以我们要工作,而且不能少于一个!集群数据访问数据分配问题已经解决,我们团队终于可以正式上线了!不同的是,读写数据时多了一个步骤:你要检查数据是否是你的责任。如果是你的责任,那就处理,否则,返回一个MOVED错误给请求者,同时告诉他槽号,IP和端口,让他知道该找谁处理。哎,这个MOVED也是抄袭HTTP中的302重定向~不过程序员是感知不到的,都是用封装好的库来操作,所以就不写代码来和我交流了~一开始工作还算顺利,但是没过多久,事情发生了:然后我们开始了数据迁移,把这一套流程标准化,为以后加入群的新朋友保存数据。经过一段时间的磨合,我们的集群团队越来越融洽了。但是光靠我们三个还是不够的,万一哪天有人挂了,整个集群都得下线!我们三个人每人至少要有一个备份!于是就找到了原来那群小弟,让他们也加入我们,继续做我们的从节点,平时作为我们的备份,从我们这里复制数据,一旦我们遇到故障,他们可以迅速接手。通过集群工作+主从复制,我们现在不仅高可用,而且数据容量也大大增加。就算以后不够用,扩容一下,又可以过上小康生活了~作者:轩辕志峰编辑:陶家龙来源:转载自公众号编程科技宇宙(ID:xuanyuancoding)
