BT

如何利用碎片时间提升技术认知与能力? 点击获取答案

为什么不能用memcached存储Session

| 作者 谢丽 关注 11 他的粉丝 发布于 2015年1月29日. 估计阅读时间: 3 分钟 | CNUTCon 了解国内外一线大厂50+智能运维最新实践案例。

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中获取最新数据。

关于memcached的更多信息,可以查看这里


感谢郭蕾对本文的审校。

给InfoQ中文站投稿或者参与内容翻译工作,请邮件至editors@cn.infoq.com。也欢迎大家通过新浪微博(@InfoQ)或者腾讯微博(@InfoQ)关注我们,并与我们的编辑和其他读者朋友交流。

评价本文

专业度
风格

您好,朋友!

您需要 注册一个InfoQ账号 或者 才能进行评论。在您完成注册后还需要进行一些设置。

获得来自InfoQ的更多体验。

告诉我们您的想法

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

不错的建议 by 贾 珣

不错的建议

换redis吧 by zhang yucan

memcached+nosql不如直接换成redis

Re: 换redis吧 by 's Rong

redis也是缓存数据库,如果内存超过maxmemory也会采用近似LRU算法清理旧数据的。

Re: 换redis吧 by 彭 震

可以采用持久化啊,文章所描述确实有点复杂了

Re: 换redis吧 by gong weixin

memcached 是针对局部进行LRU的,而redis是针对整体进行LRU的,也就是说使用memcached可能系统还有内存就发生了LRU,这样的问题非常难发现和调试,相对于redis会更便于发现问题,并且redis不建议设置maxmemory,这样内存超过限制会产生异常

Re: 换redis吧 by 易 朴素

不一样,这要看场景

这的确值得注意 by 江天 皓月

我就是用Memcached做Session缓存,替代品当然是redis之类的,不过如果Session存在心跳检测,就无须担心异常了。

Re: 换redis吧 by gong weixin

今天又看一遍,对文章又有了新的理解,如果把memcache换成redis在集群环境下问题依旧,换成redis后问题二应该没有了,而问题一还在,redis集群中的某一台或某几台挂了,分布在这些redis中的session丢失,就会导致这部分用户被迫下线

Re: 换redis吧 by 李 鹏

session存储有序列化的问题吧,使用了shiro作为权限验证的框架,session存入redis后,反序列化总是失败,知道怎么解决么?

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

9 讨论

登陆InfoQ,与你最关心的话题互动。


找回密码....

Follow

关注你最喜爱的话题和作者

快速浏览网站内你所感兴趣话题的精选内容。

Like

内容自由定制

选择想要阅读的主题和喜爱的作者定制自己的新闻源。

Notifications

获取更新

设置通知机制以获取内容更新对您而言是否重要

BT