memcache不适合存session

最近接手一个sso项目,采用memcache存储session的,经过研究和使用一段时间,发现还是不是适合存放session,原因mc的淘汰机制决定,内存满时,lru算法乱淘汰session信息导致用户无故被踢下线。

    Memcached创建者Dormando很早就写过两篇文章[1][2],告诫开发人员不要用memcached存储Session。他在第一篇文章中给出的理由大致是说,如果用memcached存储Session,那么当memcached集群发生故障(比如内存溢出)或者维护(比如升级、增加或减少服务器)时,用户会无法登录,或者被踢掉线。而在第二篇文章中,他则指出,memcached的回收机制可能会导致用户无缘无故地掉线。

   Titas Norkūnas是DevOps咨询服务提供商Bear Mountain的联合创始人。由于看到Ruby/Rails社区忽略了Dormando那两篇文章所指出的问题,所以他近日撰文对此进行了进一步的阐述。他认为问题的根本在于,memcached是一个设计用于缓存数据而不是存储数据的系统,因此不应该用于存储Session。

    对于Dormando的那两篇文章,他认为第一篇文章给出的原因很容易理解,而人们经常会对第二篇文章给出的原因认识不足。因此他对这个原因进行了详细地阐述:

Memcached使用“最近最少使用(LRU)”算法回收缓存。但memcached的LRU算法针对每个slab类执行,而不是针对整体。

这意味着,如果所有Session的大小大致相同,那么它们会分成两三个slab类。所有其它大小大致相同的数据也会放入同一些slab,与Session争用存储空间。一旦slab满了,即使更大的slab中还有空间,数据也会被回收,而不是放入更大的slab中……在特定的slab中,Session最老的用户将会掉线。用户将会开始随机掉线,而最糟糕的是,你很可能甚至都不会注意到它,直至用户开始抱怨……

另外,Norkūnas提到,如果Session中增加了新数据,那么Session变大也可能会导致掉线问题出现。

有人提出将Session和其它数据分别使用单独的memcached缓存。不过,由于memcached的LRU算法是局部的,那种方式不仅导致内存使用率不高,而且也无法消除用户因为Session回收而出现随机掉线的风险。

如果读者非常希望借助memcached提高Session读取速度,那么可以借鉴Norkūnas提出的memcached+RDBMS(在有些情况下,NoSQL也可以)的模式:

       当用户登录时,将Session “set”到memcached,并写入数据库;

       在Session中增加一个字段,标识Session最后写入数据库的时间;

       每个页面加载的时候,优先从memcached读取Session,其次从数据库读取;

       每加载N页或者Y分钟后,再次将Session写入数据库;

       从数据库中获取过期Session,优先从memcached中获取最新数据。

MemCache指令汇总

MemCache的某个节点,直接telnet过去,就可以使用各种命令操作MemCache了,下面看下MemCache有哪几种命令:

命 令 作 用
get 返回Key对应的Value值
add 添加一个Key值,没有则添加成功并提示STORED,有则失败并提示NOT_STORED
set 无条件地设置一个Key值,没有就增加,有就覆盖,操作成功提示STORED
replace 按照相应的Key值替换数据,如果Key值不存在则会操作失败
stats 返回MemCache通用统计信息(下面有详细解读)
stats items 返回各个slab中item的数目和最老的item的年龄(最后一次访问距离现在的秒数)
stats slabs 返回MemCache运行期间创建的每个slab的信息(下面有详细解读)
version 返回当前MemCache版本号
flush_all 清空所有键值,但不会删除items,所以此时MemCache依旧占用内存
quit 关闭连接

MemCache服务器的基本信息,它们的意思是:

参 数 名 作 用
pid MemCache服务器的进程id
uptime 服务器已经运行的秒数
time 服务器当前的UNIX时间戳
version MemCache版本
pointer_size 当前操作系统指针大小,反映了操作系统的位数,64意味着MemCache服务器是64位的
rusage_user 进程的累计用户时间
rusage_system 进程的累计系统时间
curr_connections 当前打开着的连接数
total_connections 当服务器启动以后曾经打开过的连接数
connection_structures 服务器分配的连接构造数
cmd_get get命令总请求次数
cmd_set set命令总请求次数
cmd_flush flush_all命令总请求次数
get_hits 总命中次数,重要,缓存最重要的参数就是缓存命中率,以get_hits / (get_hits + get_misses)表示,比如这个缓存命中率就是99.2%
get_misses 总未命中次数
auth_cmds 认证命令的处理次数
auth_errors 认证失败的处理次数
bytes_read 总读取的字节数
bytes_written 总发送的字节数
limit_maxbytes 分配给MemCache的内存大小(单位为字节)
accepting_conns 是否已经达到连接的最大值,1表示达到,0表示未达到
listen_disabled_num 统计当前服务器连接数曾经达到最大连接的次数,这个次数应该为0或者接近于0,如果这个数字不断增长, 就要小心我们的服务了
threads 当前MemCache总线程数,由于MemCache的线程是基于事件驱动机制的,因此不会一个线程对应一个用户请求
bytes 当前服务器存储的items总字节数
current_items 当前服务器存储的items总数量
total_items 自服务器启动以后存储的items总数量

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值