一、什么是分布式系统?
分布式系统:旨在支持应用程序和服务的开发,可以利用物理架构由多个自治的处理元素组成,不共享内存,通过网络发送消息合作。
分布式系统的三个特点:
多节点,消息通信,不共享内存。
二、 什么是session?
广义的session:指会话控制。由于http协议是无状态的,对于不同http请求是没有上下文关系的,因此常见的场景就是,当用户登陆一个系统时候要有合适的方式记录用户的登陆信息和状态以便在后续操作中继续使用。
三、分布式session问题
a. session 多服务器共享的问题,假如有多台 php 服务器进行负载均衡的时候,用户登录时访问的是第一台服务器,没准下一个页面访问的是第二台服务器,但是 session 数据是存储在第一台服务器上的,因此在访问下一个页面的时候由于没有 session 数据(第二台服务器上)导致用户必须重新登陆。
b. 从前面的分析我们也知道,php 中 session 默认通过文件的方式实现,但是如果访问量大,可能产生的 SESSION 文件会比较多,从众多的文件中选择其中一个文件不是一件轻松的事情,而且每次都以打开文件、读取文件的方式,也会产生大量的 I/O操作,严重影响服务器的性能。
四、 分布式session如何共享
1. 通过复制或同步的方式使得 a、b、c 服务器上都具有相同的 session 数据。
这种方式的弊端是,速度慢。复制数据会出现延迟。
复制数据要消耗很多网络带宽的。在实际中业界用得比较少。机器的数量越多,复制数据的性能损耗越大。不具备高度扩展性。
2. 把原来存储在服务器磁盘上的session数据存储到客户端的cookie中去。
这样子,就不需要涉及到数据共享了。当客户端请求的时候,原来生成在服务器的数据生成到浏览器的 cookie 中,根据 cookie 中的数据识别用户。php 由原来的”从本地(也就是服务器)磁盘上读取 session 数据”转变为”浏览器的 cookie 中读取数据”。
好处是服务器的压力减小了,因为session数据不存在服务器磁盘上。根本就不会出现 session 读取不到的问题。
带来的弊端是:1. 网络请求占用很多。每次请求时,客户端都要通过 cookie 发送 session 数据给服务器。2. 浏览器对 cookie 的大小存在限制。3. cookie的安全问题。
3. 分发请求
用一种算法,什么机制下 session 是保存在哪台服务器下,那么读取的时候就按照这种规则去读取,就能定位到原来的服务器。
例如 Nginx 的 ip_hash, 每个请求按访问 ip 的 hash 结果分配,这样每个访客固定访问一个后端服务器。
这种方式的弊端是:如果这台机子挂掉了,那么后续的请求按照 session 的规则还是会分发到这台服务器上去,但是现在不可用了,就会导致归属到这台服务器上的所有用户登录失败。
4. 数据库存放session
保存在数据库中,这种方式的扩展性很强,可以随意增加WEB而不受影响。放在数据库里面安全方面好。
弊端是:放在数据库里面,访问量小没有问题。大流量网站这么做,只会拖慢速度。因为得查询数据库,造成数据库压力大。
5. 使用文件系统存放session
通过文件系统(比如NFS方式,文件共享)来实现各台服务器间的Session共享,各台服务器只需要mount共享服务器的存储Session的磁盘即可,实现较为简单。但NFS 对高并发读写的性能并不高,在硬盘I/O性能和网络带宽上存在较大瓶颈,尤其是对于Session这样的小文件的频繁读写操作。 适合并发量不大的网站。
6. 利用缓存存储session
可以将 session 数据保存在 memcached,redis 之类内存数据库中,memcached 是基于内存存储数据的,性能很高,用户并发量很大的时候尤其合适。
主要是利用内存的数据读取速度是很快的,与磁盘读取的速度不是一个数量级的。使用内存存储,方便统计在线人数,内存的速度比磁盘访问快、内存数据库系统能够控制内存中的过期数据自动失效(刚好符合 session 过期需要)。
缺点: session 数据都保存在 memory 中,一旦宕机,数据将会丢失。但对 session 数据来说并不是严重的问题。如果网站访问量太大,session太多的时候,memcached会将不常用的部分删除,但是如果用户隔离了一段时间之后继续使用,已经全部乱套了。
使用Redis搭建session服务器,
每个用户进来,系统都会去Redis搭建的session服务器查询用户信息进行后续操作,我们只需要在登陆时候存储key,登出的时候让key失效即可。这样无论是水平拓展或者是垂直拓展就都不影响session的使用了。
具体方案:
为了解决集群环境下的seesion共享问题,共有4种解决方案:
1.粘性session
粘性session是指Ngnix每次都将同一用户的所有请求转发至同一台服务器上,即将用户与服务器绑定。
2.服务器session复制
即每次session发生变化时,创建或者修改,就广播给所有集群中的服务器,使所有的服务器上的session相同。
3.session共享
缓存session,使用redis, memcached。
4.session持久化
将session存储至数据库中,像操作数据一样才做session。
其实,最简单的两种方案,就是方案一和方案三,都不需要对session进行任何操作,只需要将Nginx和Tomcat上的配置文件修改一下即可。由于我们做集群,访问量一定是比较大的了,对于第一种方案,如果某台服务器发生故障,此服务器上的所有用户的session都会丢失,所以今天我们采用第三种解决方案。