2020年5月12日 下午10:15
单点登录的进化
本质是一个验证问题
- Client - 单服务器
- 方案一:每次都用username password到数据库中进行验证
- 方案二:使用SessionID作为验证的已登录用户的方法,client和server端有共同的ID,client保存在cookie中,server保存在tomcat的缓存中,一旦tomcat重启,那么缓存就消失了,我们必须做持久化到硬盘才可以
- 方案三:使用redis作为这个持久化的地方,解决重启需要重新验证的问题
- Client - 多服务器
- 方案一:跟上面一致
- 方案二:那么多台服务器之间无法共享登录状态,其实就是无法共享tomcat私有的sessionID
- 方案三:不仅解决了单服务器重启的问题,也做到了SessionID多服务器之间的共享
- Client - 多服务器 — redis集群
- 什么场景下缓存一致性:
- 主要考虑的是redis集群扩展的情况下,如何保证仍然有较高的缓存命中率的问题。也就是说本质问题是:缓存命中率的问题
- 一致性hash有哪些问题,如何解决:
- hash倾斜性:由于hash的倾斜,会导致hash结果分布不均匀
- 什么是hash倾斜性?
- 首先我们一致性哈希中有两个过程:
- 第一步:正常的hash操作,得到一个hash结果
- 第二步:数据的hash向redis的hash在环上进行靠拢
- 如果数据的hash和redis的hash结果在环上分布“不搭”,eg:数据hash密集的地方,redis的hash不密集。靠拢之后的结果就会倾斜
- 首先我们一致性哈希中有两个过程:
- 解决方法:
- 我们有一个直观的感受:如果redis越多,那么在环上的分布就越有可能均匀。
- 那么,我们就假设出更多的虚拟redis节点。然后再将虚拟节点二次hash到实在的redis节点中,注意这次的hash是直接hash到实在的redis节点,而没有了“靠拢”这一步骤。
- 二次hash就是最最普通的hash,反而不容器造成hash的倾斜性
- 什么场景下缓存一致性:
什么场景下需要分布式锁
- 本质问题:对有限资源(仅一个)的争抢下,如何确定第一个获得者
- 这其中需要设计两个:
- 争抢时:需要设计一个游戏规则,争抢的人都遵守这个游戏规则
- 争抢完之后:需要设计一个条件,能区分出第一名和其他人。
- 一个好的锁条件 + 游戏规则 设计需要保证:有且只有一个被筛选出来
- 必须有,不能一个都没有
- 有,但只能有一个
- 这其中需要设计两个:
- 我们虽然很难设计出这样一个锁条件,但是我们反过来验证一下是否满足有且只有一个:
- 我们可以想象一个图

- 我觉得这个问题本质和编程无关,更像是一道中学数学逻辑题:
- 问:你是否能够设计一个游戏规则,保证在资源争抢的时候,有且只有一个人获得资源
- 也就是说,所有参与游戏的人都遵循一套规则,并没有暗箱操作,就可以保证唯一性,这个游戏规则在并发的时候,会出现相互的制约,从而保证的结果的正确,也只有并发的时候才会体现出来
- 分析这种游戏规则的方法:就如图中所示的一样,在一条时间线上,我们假设一个人已经获得了锁,此时我们枚举出所有的可能情况,看是否能找到第二人再次获得锁,如果我们再所有的情况中都无法获得锁,那么说明这个规则有效。
- 我们可以想象一个图
架构思维:对问题的本质进行认识,做到举一反三
涉及到的java语法知识:
- 什么场景下需要static
- 场景一:在服务启动时,就默认初始化好redis的连接池
- 场景二:在使用的时候,不用声明对象,直接通过类来使用
- 什么场景下需要,多态,强制类型转换
- 什么场景下需要泛型
- 场景一:在对象序列化的时候,序列化函数的接口就需要满足各种类型进行序列化的要求,甚至在嵌套类型list
中使用<?>,当代码中不使用这个类型的时候,可以指定为?,对于多类型的话,可以使用变长参数。
- 场景一:在对象序列化的时候,序列化函数的接口就需要满足各种类型进行序列化的要求,甚至在嵌套类型list