分布式session有如下几种方案:
1. 基于nfs(net filesystem)的session共享mysql
将共享服务器目录mount各服务器的本地session目录,session读写受共享服务器io限制,不能知足高并发。web
2. 基于关系数据库的session共享redis
这种方案广泛使用。使用关系数据库存储session数据,对于mysql数据库,建议使用heap引擎。 这种方案性能取决于数据库的性能,在高并发下容易形成表锁(虽然能够采用行锁的存储引擎,性能会降低),而且须要本身实现session过时淘汰机制。算法
3. 基于cookie的session共享sql
这种方案也在大型互联网中广泛使用,将用户的session加密序列化后以cookie的方式保存在网站根域名下(好比taobao.com),当 用户访问全部二级域名站点式,浏览器会传递全部匹配的根域名的cookie信息,这样实现了用户cookie化session的多服务共享。 此方案可以节省大量服务器资源,缺点是存储的信息长度受到http协议限制;cookie的信息还须要作加密解密; 请求任何资源时都会将cookie附加到http头上传到服务器,占用了必定带宽。数据库
4. 基于resin/tomcat/iis等web容器的session机制浏览器
利用容器机制,经过配置便可实现。tomcat
5. 基于zookeeper的分布session存储服务器
详见http://my.oschina.net/u/699015/blog/159654cookie
6. 基于redis/memcached的session共享存储
这些key/value非关系存储有较高的性能,轻松达到2000左右的qps,内置的过时机制正好知足session的自动实效特性。
以上方案各有优缺点,本文主要介绍第六种基于redis存储session时,如何实现动态扩容。 redis目前并无内置高可用集群,不少客户端代理基于一致性hash算法可以实现分布式存储,可是扩容并不方便(须要成倍扩容),目前咱们采用了淘宝 fourinone中session方案的思想:
a. 用于存储session的redis集群有多个redis节点
b. proxy记录了每一个节点加入到集群的时间,并按照时间顺序对节点进行了编号(0—n)
c. session key的生成算法方面,须要在session key中包含生成时的当前日期(可考虑细化到小时仍是分秒),在session key生成后,再进行取模运算 hash(sesionKey)%redisHost_count, 根据取模结果决定当前session值存储到落到哪一个节点上存储。
d. 再经过sessionkey获取session信息时,根据当前sessionKey取出时间部分,再根据取出的时间与redis集群中全部的节点的添加 时间进行比较,筛选出全部addtime<sessionkey_time的节点,再进行c中的取模计算,因为即便这期间进行了扩容,因为进行了时 间匹配,redisHost_count也不会发生变化,因此取模结果和存储此session时同样,还会落到当时存储这个session的节点上,在那 个节点可以获得此session的值。
可是对于这种部署结果如何可以保障高可用性,如何应对单点故障,后续会在redis高可用方案中介绍。