分类:
2012-03-31 10:07:59
原文地址:一个分布式的负载设计 作者:laoliulaoliu
要求:对于saas这种服务一个用户名,同一段时间只能有一次登录系统。因为用户数量大,所以对于用户的登录,需要能够在多个server上做负载均衡。
Hash 潜在冲突检测模块
节点检测模块
上线用户连接发现与维持模块
各个节点
节点的说明:
1.hash函数计算用户名后,映射到M个bits中的一个,并置1(初始为0),如果已经不是0,就加1.
2.使用countingbloom filter进行计算,支持用户下线删除
3.减少一个node。可能新到的用户名唯独在这个node里面检测是为0,其他都是1,所以认为他上线过了。这样就需要在“hash冲突检测模块”里进行查找,产生退化。
4.增加一个node。只要把“hash冲突检测模块”里的每一个已登陆用户名在这台机器的M个bits里面做hash就可以了。
流程:
登陆的用户,在若干个node里面计算hash,如果有一个空间之前是0,反馈给“节点检测模块”,此模块知道这个用户之前没有登陆过,发送count指令给各个node,各个node把计算出来的那个bit在M空间中置1。
登陆的用户,在若干个node里面计算hash,如果所有空间之前都是大于等于1,反馈给“节点检测模块”,此模块知道这个用户‘可能’之前登陆过(可能是因为hash存在冲突)。于是在“Hash潜在冲突检测模块”里面查找一次,找到表明真的登录过,没找到表明没有登录过。登陆过则给各个node发cancel指令使之结束这次计算过程,并拒绝登陆,没有登陆则给各个node发送count指令,各个node把计算出来的那个bit在M空间中置1。
“上线用户连接发现与维持模块”发现登陆过用户的长连接断开,则表明用户下线,对各个node的这个用户名计算hash,并把M个bits位中的计算结果哪一位减1。
设计缺陷:
对于负责动态负载均衡的node,countingbloom filter本身有空间M和最优hash函数个数的要求,最好根据用户数确定。
如果用户数很多,那么每个node都做hash函数,其实并没有负载均衡,而是增加了计算的负担。
2012年3月23日
快一年了,重新看自己的设计,觉得细节是有,但思路比较复杂,主要思想还是hash+MapReduce。Bloomfilter错误率其实可以做到很小的,所以偶尔有人重复登陆也不要紧。下面是现在的思路。
服务器端的自动更新程序可以自动更新客户端的配置文件。(写一个服务端程序,自动搜集客户端节点存活信息,调整分配hash值的策略?)
登陆:对用户名散列值的计算可以放到若干台机器上,计算时主登陆服务器轮询分配,此节点死去就不再分配(其中未计算完成的散列导致用户可以二次登陆),主登陆服务器程序动态读取配置文件,给新增节点分配计算量。
检测:计算完成的散列根据散列值的大小的空间分配到相应的机器上按照“拉链法”查找,找到返回主登陆服务器“已登陆”,没找到,返回主登陆服务器“允许登陆”,并把hash值和用户名存储起来。对这些存放登陆信息的服务器通过存储冗余信息,达到坏死一个节点仍能正常运行的目的。比如:10台机器,每一台机器在给主登陆服务器发送“允许登陆”存储hash值和用户名时,把hash值和用户名信息发送给后一台机器(第10台发送给第1台),这样形成一个循环冗余。坏死一个节点时,只要先查询删除后一台机器,并保证迅速恢复坏死机器。增加机器需要重新分配hash值空间,从第一台机器开始逐渐往后拷贝hash值和用户名。或使新增机器和已存在的一台机器共用已存在机器的hash空间,让这几个机器充当一台机器的角色,是为了不重新分配hash空间。
“上线用户连接发现与维持模块”发现登陆过用户的长连接断开,则表明用户下线,根据散列空间给相应的机器发送“删除”命令,删除此用户的登陆信息。