作者回复: 主要4点原因: 1. 携程session数据总量大,如果全部存入redis缓存,成本比较高,而我们需要的是一套二级缓存机制,一级缓存常驻内存,存放当前活跃session数据,二级缓存可以持久化,存当前不活跃session数据,这样可以平衡性能和成本。 2. 我们需要细粒度的埋点和监控,只有定制自研才能做到。 3. 实现一个ASP.NET state server protocol+缓存并不复杂,我们完全可以在2~3月内搞定上线,如果引入redis,当然也可以架构设计出来一套类似系统,但是时间成本不会少多少,同时还是需要实现state server protocol,而且我们还需要监控维护redis。 4. session server对携程这样体量的公司来说,太重要,不能出问题,定制自研我们的把控力会更大,可以做到全程白盒子,不留黑盒子。
作者回复: 如果不采用二级缓存,全部基于redis,也可以实现SessionServer,只是需要采用不同的架构设计。 SessionServer开发于2014年,当时的redis集群技术还不成熟,另外携程当时也没有专门的redis运维团队。 我们自研的SessionServer也很轻量,开发工作量也不大,而且可以做精细化埋点监控,项目也挺成功的。
作者回复: 你好,我们做分布式系统设计的时候,一般会做一个假设,就是每次出现故障的时候,假设一次只出现一个故障,不会两个故障同时发生(虽然理论上可能,但是几率极小)。所以我们假定session写入数据库失败,和该Session服务器同时又故障这两个故障不同时发生。如果不做这样的假设,那么还有可能超过两个以上同时故障的情况发生,这样就没完没了。 即便session写入数据库失败,和该服务器又故障同时发生了,那会造成session数据丢失(假设这期间有session写入操作),但是只是一个很小的时间窗口,SessionClient会很快重试其它SessionServer,也就是说数据丢失很少,概率也很小,所以我们认为这是可以接收的。 sessionClient如果访问SessionServer失败,它会重试一定次数,超过一定阈值再切换到其它SessionServer做数据恢复。
作者回复: 可持久化缓存的数据可以存在磁盘上,磁盘的容量一般比内存大很多。
作者回复: 1. 这个ip是内部的,外网访问不到 2. 实际系统对cookie中的ip信息有加密处理, 所以没有特别的安全隐患。
作者回复: 存在服务器端,服务器端就变成有状态了,有状态系统很难升级维护,非常容易出错。 服务器端的开发原则是尽量无状态,这样比较容易扩展,不容易出错。如果必须有状态,那么优先考虑集中状态。如果你搞成了需要状态同步的话,复杂性和出错概率会大大提升。
作者回复: 你学得很仔细,异步写入有一个小的时间窗口,可能在用户更新还没有被写入后台DB前,SessionServer正好挂了,这个时候更新会丢失。 实际使用中SessionSession自己挂概率非常小,即使发生也只是非常小的影响(异步写入时间窗是秒级)。另外,我们后面考虑后台用redis,SessionServer同步写穿透到redis,这样数据就不会丢失了。
作者回复: 如果service client访问session server异常,并且重试3次还是异常,就可以判断后端服务挂掉,然后它就会重新选择1台可用的session server(从eureka获取可用session server ip列表),进行session数据的恢复处理流程。 因为这个设计没有引入raft之类分布式仲裁协议,所以不会出现脑裂。
作者回复: 1. 一般同城的跨IDC可以使用光线链路(例如后面提到的波分多路复用光纤),性能就像两个IDC在局域网内,性能完全没有问题。 2. 电信的GSLB一般有策略状态,一般一个地区的IP都会被路由到同一个IDC,不会经常摆来摆去的,除非出现特殊情况(比如某个IDC的入口挂了),这个时候GSLB才会摆到另一个IDC。
作者回复: 携程网站要求客户端浏览器启用cookie,否则Session不能正常工作。 有些客户端浏览器虽然禁用了Cookie,但只是cookie不能持久化话,内存中还是有的,除非浏览器关闭,那么Cookie就没有了,下次必须重新登录获取Session。