正确理解memcached,才能更好的使用
Posted 虞大胆的叽叽喳喳
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了正确理解memcached,才能更好的使用相关的知识,希望对你有一定的参考价值。
基于memcached官方wiki,写了几篇 memcached 内部机制的文章,比如内存分配、LRU的工作原理。接下来从应用的角度说说memcached,只有从正确的角度理解,才能更好的应用,否则就会出现很多误解,比如有时候比较memcached和redis是毫无意义的。
1:内存、内存、内存
memcached是完全基于内存操作的,是一个缓存系统,从本质它不是一个数据库系统,也不支持持久化。
既然是内存,在使用之前问自己,memcached缓存的数据如果丢失,会影响你的业务吗?
2:分布式系统
memcached本身是一个非常轻量级的服务,不支持主辅同步,也没有集群的概念。但为了可扩展性,memcached 服务器端和 memcached 客户端结合起来可以构成一个分布式系统。
在memcached分布式系统中,各个 memcached 节点之间无须通信,所以扩展性非常好。
3:不支持复杂的操作
和 redis 不一样的是,memcached 没有复杂的数据结构(比如队列、集合),它只能存储字符串类型,也不关心具体存储什么,这是它的一个优势:简单。但很多人用的时候可能就不爽了,说它比 redis 弱爆了,其实双方的应用场景不一样。
当然也可以基于基本命令模拟一些数据结构,这是允许的,但这和memcached无关。
4:原子操作
memcached 所有操作都是 O(1) ,都是原子操作,同一时间操作多个 set 不会有任何的影响。
5:性能
memcached 性能高的原因主要在于 libevent 事件机制、多线程、全内存操作、模型简单(比如 O(1),尽量避免锁机制)。
配置相对较高的服务器,每秒可以处理 200,000+ 的请求,即使在很慢的机器上,每秒处理几百次也毫无压力。
memcached 所有的操作都是 O(1),set/get 操作不应该出现滞后,一个请求正常情况下不到 1ms 就能返回,如果遇到 Hang,那可能是连接数过多、产生了 swap、遇到了网络问题。
6:不推荐存储 session 数据
现在很多业务都用 memcached 存储 session 数据,在使用之前一定要评估风险,因为 memcached 是基于内存的,如果存储的 session 丢失了,会话用户就掉线了。
7:不支持命名空间
memcached 一般针对某个key进行操作,不支持 namespace 功能,原因在于为了实现namespace,会让系统实现复杂化(比如为了实现过期设置功能)。
但命名空间的作用却非常大,比如以下需求:
希望批量删除某些 key。
如果获取相关联数据(比如有多个key),但 memcached 节点非常多,如果这些key根据 Hash 算法分散存储到多个节点,那么获取的时候性能就会下降。
但很多客户端模拟实现了namespace功能 ,比如 php memcached 扩展就有相应的函数,比如 addByKey(),getAllKeys() 等函数,这些后续我再说。
8:Failure or Failover
如果你的应用没有使用一致性hash算法或其他的hash算法,连接某一个memcache节点的时候,如果网络连接超时,或某个节点不能通信(比如网线被拔了),那么客户端调用只能选择 Failure,遇到这样的情况,可能就要去后端读取数据了。
如果你的应用使用一致性hash算法,那么应该选择 Failure or Failover?
这里有一个误区,一致性 hash 算法是减少上线或下线服务器带来的缓存失效问题,本质上不是为了让客户端随时随地都能获取到数据。
如果网络连接超时,或某个节点不能通信(比如网线被拔了),尽量不要选择自动 Failover,比如三个节点,本来某个 key 对应第一个节点,如果客户端发现第一个节点不可用,就自动存储到第二个节点,原因就在于如果第一个节点恢复了,可能获取到旧的数据(在 Failover 的时候新数据更新到第二个节点)。
根据这一原则,PHP memcached 扩展默认是不做 Failover 的,这也是正确的应用方式,如果你实在要 Failover,可以使用下面的代码。
$memcache = new Memcached;
$memcache->setOption(Memcached::OPT_DISTRIBUTION,Memcached::DISTRIBUTION_CONSISTENT);
$memcache->setOption(Memcached::OPT_SERVER_FAILURE_LIMIT, 1);
$memcache->setOption(Memcached::OPT_AUTO_EJECT_HOSTS,true);
$memcache->addServer('localhost', 11212);
$memcache->addServer('localhost', 11213);
$memcache->set("abc",1);
echo $memcache->get("abc");
print_r($memcache->getResultMessage());
9:能不能list所有的keys
不能,memcached 本身不支持,它就是一个 key-value 系统,但如果实在想实现list,可以通过两个办法:
推荐在启动的时候配置 -vvv,这样能够将所有set的key打印出来,而且是排查问题非常好的方法。
运行 stats cachedump 命令,不过不推荐使用,因为操作比较慢,而且只能拿到局部的数据。
10:memcached 应用场景?
能缓存任何数据,有效减少后端的压力并提升响应能力。
计算器,比如利用 incr 命令。
Rate limiting,非常有用,比如登陆系统可以使用它限制非法登陆。
虽然 memcached 不支持队列和堆栈,但 append/prepend 命令还是有一定作用的,比如可以实现排行榜。
11:一些小技巧
(1)Zero byte values
如果你只是要使用 memcached 的key ,其对应的value没有任何价值,那么为了减少内存的使用,可以设置0字节长的值。
(2)尽量减少 key 长度,有效利用内存。
(3)有效利用锁机制,比如 add 命令,专门写过一篇文章介绍过《》。
memcached 相关文章:
以上是关于正确理解memcached,才能更好的使用的主要内容,如果未能解决你的问题,请参考以下文章
我的 setInterval 函数减慢了我的代码速度——我怎样才能修改它以获得更好的性能?