系统设计 — 会话状态的处理

对于状态要从两个角度来考虑,一个是对象状态,对象包含了状态(数据)和行为,一个没有状态的对象是不合理的,是种不良设计。
另一种是分布式服务器无状态:指的是在多次请求间不保存对象的状态,但是对象自身是有状态的。服务器端的无状态保证了每次请求不关心是哪个对象来处理,若是需要保存状态,就需要找同一个对象来处理。无状态可以使得我们缓存这些对象,用很少的对象就能处理很多用户。同时在高流量的情况,我们的服务端一般对应的是一个集群,无状态对于集群的横向扩展基本是0代价。无需考虑服务的状态。

但是实际的业务场景中,还是存在一些需要记录会话状态的场景,例如登陆信息,购物车信息,我们需要在某一个地方记录用户是否登陆,购物车是否加载了东西。那么就牵扯出如何保存会话状态的方式。通常的有三种:

  1. 客户端会话状态
  2. 服务端会话状态
  3. 数据库端会话状态

客户端会话状态有这么几种实现方式:

  1. 将会话信息编码在URL中
  2. 将会话信息保存中cookie中
  3. 将会话信息通过一个隐藏域提交

优点:
将会话状态保留在客户端,减轻服务端的压力,中间需要做的是一个会话信息的转译,为了安全性等方面考虑
缺点:
若是会话信息非常大的话,那么带宽就会成为灾难。
总结的看客户端会话状态适合于那些会话信息非常少的场景下

服务端会话就是将信息保存在服务端的内存中,同样面临的第一个问题,服务端的内存资源是非常珍贵的,所以对于单台服务器能够承受的会话数量是非常有限的,对于此的做法是添加服务器数量,通过更多的内存来承载更多的会话信息,但是多服务器又会带来一个问题,就是会话复制,一个用户不可能每次请求都落到同一台服务器中,这个会话复制的陈本是不可避免的一点。当然对于这点也是可以考虑服务器亲和的策略,将IP绑定到第一次访问的服务器中,但是这里就引入了一个中间环节,对于扩张和分布和宕机处理很不友好!

最后种是数据库会话状态,就是将会话信息保存进行持久化,也正因为这个持久化过程,加剧了会话的流程,所以在系统响应中不是很好的体验,有一个不太靠谱的数据对比:

  • 从L1缓存中取数据是1ns,
  • 从L2是5ns
  • 从内存中获取数据是10-15ns
  • 从持久化设备就无一个准确的值,基本应该到100+ns

可以看出,数据库会话的最大问题是速率。

开发陈本:
服务器会话状态陈本最低,基本不需要什么特殊的处理,但是考虑的是数据会话迁移及数据安全隔离,若是集中式的服务端会话控制的话,还需设计到网络通信问题。
客户端和数据库的都需要考虑数据的解析和转化 ,同时数据库还涉及到磁盘IO.

选择:
客户端奔溃,服务器挂机,网络突然断掉、数据库挂了等等情况看,其中任何一种都有可能发生,但是不太可能一起发生,所以对于以上手段,应该更复合的去使用,若是较少量的会话信息,通过客户端保存,保存的仅仅是一个会话标示,若是类似购物车等较多的信息,通过集中式的服务器会话保存是一个好的方案,但是对了应对各种异常和做容灾的话,那么必须将部分重要会话信息持久化到数据库了!

以上都只是大体上提到了处理方案,期间还是有很多具体的考量点,例如集中式的服务器会话如何做到关键数据的隔离,保证ACID的事务特性等等!

作者: inter12

在这苦短的人生中,追求点自己的简单快乐

发表评论

电子邮件地址不会被公开。 必填项已用*标注