Memcached 是一个开源的,高性能的内存绶存软件,从名称上看 Mem 就是内存 的意思,而 Cache 就是缓存的意思。Memcached 的做用:经过在事先规划好的 内存空间中临时绶存数据库中的各种数据,以达到减小业务对数据库的直接高并 发访问,从而达到提高数据库的访问性能,加速网站集群动态应用服务的能力。前端
memcached 服务在企业集群架构中有哪些应用场景?mysql
1、做为数据库的前端缓存应用web
a、完整缓存(易),静态缓存redis
例如:商品分类(京东),以及商品信息,可事先放在内存里,而后再对外提供 数据访问,这种先放到内存,咱们称之为预热,(先把数据存缓存中),用户访 问时能够只读取 memcached 缓存,不读取数据库了。算法
b、执点缓存(难)sql
须要前端web 程序配合,只缓存热点的数据,即缓存常常被访问的数据。 先预热数据库里的基础数据,而后在动态更新,选读取缓存,若是缓存里没有对 应的数据,程序再去读取数据库,而后程序把读取的新数据放入缓存存储。数据库
特殊说明 :后端
例如:称杀只是获取资格,而不是瞬间秒杀到手商品。数组
那么什么是获取资格?缓存
2、做业集群的 session 会话共享存储。
特殊说明:Memcached 集群和 web 服务集群是不同的,全部 Memcached 的 数据总和才是数据库的数据。每台 Memcached 都是部分数据。
(一台 memcached 的数据,就是一部分 mysql 数据库的数据)
a、程序端实现 程序加载全部 mc 的 ip 列表,经过对 key 作 hash (一致性哈希算法)
例如:web1 (key)===>对应 A,B,C,D,E,F,G…..若干台服务器。(经过哈希算法实 现)
b、负载均衡器
经过对 key 作 hash (一致性哈希算法)
一致哈希算法的目的是不但保证每一个对象只请求一个对应的服务器,并且当节点 宕机,缓存服务器的更新从新分配比例降到最低。
a、彻底基于内存缓存的
b、节点之间相互独立
c、C/S 模式架构,C 语言编写,总共 2000 行代码。
d、异步I/O 模型,使用 libevent 做为事件通知机制。
e、被缓存的数据以 key/value 键值对形式存在的。
f、所有数据存放于内存中,无持久性存储的设计,重启服务器,内存里的数据会 丢失。
g、当内存中缓存的数据容量达到启动时设定的内存值时,就自动使用 LRU 算法 删除过时的缓存数据。
h、能够对存储的数据设置过时时间,这样过时后的数据自动被清除,服务自己不 会监控过时,而是在访问的时候查看 key 的时间戳,判断是否过时。
j、memcache 会对设定的内存进行分块,再把块分组,而后再提供服务。
早期的 Memcached 内存管理方式是经过 malloc 的分配的内存,使用完后经过 free 来回收内存,这种方式容易产生内存碎片,并下降操做系统对内存的管理效 率。加剧操做系统内存管理器的负担,最坏的状况下,会致使操做系统比memcached 进程自己还慢,为了解决这个问题,Slab Allocation 内存分配机制 就延生了。
如今 Memcached 利用 Slab Allocation 机制来分配和管理内存。
Slab
Allocation 机制原理是按照预先规定的大小,将分配给 memcached 的内存分割 成特定长度的内存块(chunk),再把尺寸相同的内存块,分红组 (chunks slab class),这些内存块不会释放,能够重复利用。
并且,slab allocator 还有重复使用已分配的内存的目的。 也就是说,分配到的 内存不会释放,而是重复利用。
Slab Allocation 的主要术语
Page
分配给 Slab 的内存空间,默认是 1MB。分配给 Slab 以后根据 slab 的大小切分红 chunk。
Chunk
用于缓存记录的内存空间。
SlabClass
特定大小的chunk 的组。
集群架构方面的问题
Memcached 的神奇来自两阶段哈希(two-stage hash)。Memcached 就像一 个巨大的、存储了不少对的哈希表。经过 key,能够存储或查询任意 的数据。
客户端能够把数据存储在多台 memcached 上。当查询数据时,客户端首先参节点列表计算出 key 的哈希值(阶段一哈希),进而选中一个节点;客户端将请 求发送给选中的节点,而后 memcached 节点经过一个内部的哈希算法(阶段二 哈希),查找真正的数据(item)。
Memcached 最大的好处就是它带来了极佳的水平可扩展性,特别是在一个巨大的 系统中。因为客户端本身作了一次哈希,那么咱们很容易增长大量 memcached 到集群中。memcached 之间没有相互通讯,所以不会增长 memcached 的负载; 没有多播协议,不会网络通讯量爆炸(implode)。memcached 的集群很好用。 内存不够了?增长几台 memcached 吧;CPU 不够用了?再增长几台吧;有多余 的内存?在增长几台吧,不要浪费了。
基于 memcached 的基本原则,能够至关轻松地构建出不一样类型的缓存架构。除 了这篇 FAQ,在其余地方很容易找到详细资料的。
cache 相比,有什么优缺点?
把 memcached 引入应用中,仍是须要很多工做量的。MySQL 有个使用方便的 query cache,能够自动地缓存 SQL 查询的结果,被缓存的 SQL 查询能够被反复 地快速执行。Memcached 与之相比,怎么样呢?MySQL 的 query cache 是集中 式的,链接到该 query cache 的 MySQL 服务器都会受益。
首先,local cache 有许多与上面(query cache)相同的问题。local cache 可以利 用的内存容量受到(单台)服务器空闲内存空间的限制。不过,localcache 有一点比 memcached 和 query cache 都要好,那就是它不但能够存储任 意的数据,并且没有网络存取的延迟。
Memcached 主要的 cache 机制是 LRU(最近最少用)算法+超时失效。当您存 数据到 memcached 中,能够指定该数据在缓存中能够呆多久 Which is forever, or some time in the future。若是 memcached 的内存不够用了,过时的 slabs 会优先被替换,接着就轮到最老的未被使用的 slabs。
不实现!咱们对这个问题感到很惊讶。Memcached 应该是应用的缓存层。它的设 计自己就不带有任何冗余机制。若是一个 memcached 节点失去了全部数据,您 应该能够从数据源(好比数据库)再次获取到数据。您应该特别注意,您的应用 应该能够容忍节点的失效。不要写一些糟糕的查询代码,寄但愿于 memcache来保证一切!若是您担忧节点失效会大大加剧数据库的负担,那么您能够采起一 些办法。好比您能够增长更多的节点(来减小丢失一个节点的影响),热备节点 (在其余节点 down 了的时候接管 IP),等等。
不处理! 在 memcached 节点失效的状况下,集群没有必要作任何容错处理。如 果发生了节点失效,应对的措施彻底取决于用户。节点失效时,下面列出几种方 案供您选择:
您不该该这样作!Memcached 是一个非阻塞的服务器。任何可能致使 memcached 暂停或瞬时拒绝服务的操做都应该值得深思熟虑。向 memcached 中批量导入数据每每不是您真正想要的!想象看,若是缓存数据在导出导入之间 发生了变化,您就须要处理脏数据了;
所以,批量导出导入数据并不像您想象中的那么有用。不过在一个场景却是颇有 用。若是您有大量的从不变化的数据,而且但愿缓存很快热(warm)起来,批量 导入缓存数据是颇有帮助的。虽然这个场景并不典型,但却常常发生,所以咱们 会考虑在未来实现批量导出导入的功能。
若是一个 memcached 节点 down 了让您很痛苦,那么您还会陷入其余不少麻烦。 您的系统太脆弱了。您须要作一些优化工做。好比处理”惊群”问题(好比 memcached 节点都失效了,反复的查询让您的数据库不堪重负…这个问题在 FAQ 的其余提到过),或者优化很差的查询。记住,Memcached 并非您逃避优化 查询的借口。
没有身份认证机制!memcached 是运行在应用下层的软件(身份验证应该是应用 上层的职责)。memcached 的客户端和服务器端之因此是轻量级的,部分缘由就 是彻底没有实现身份验证机制。这样,memcached 能够很快地建立新链接,服务 器端也无需任何配置。
若是您但愿限制访问,您可使用防火墙,或者让 memcached 监听 unix domain socket。
线程就是定律(threads rule)!在 Steven Grimm 和 Facebook 的努力下, memcached 1.2 及更高版本拥有了多线程模式。多线程模式容许 memcached 能 够充分利用多个 CPU,并在 CPU 之间共享全部的缓存数据。memcached 使用一 种简单的锁机制来保证数据更新操做的互斥。相比在同一个物理机器上运行多个 memcached 实例,这种方式可以更有效地处理 multi gets。
若是您的系统负载并不重,也许您不须要启用多线程工做模式。若是您在运行一 个拥有大规模硬件的、庞大的网站,您将会看到多线程的好处。
简单地总结一下:命令解析(memcached 在这里花了大部分时间)能够运行在多 线程模式下。memcached 内部对数据的操做是基于不少全局锁的(所以这部分工 做不是多线程的)。将来对多线程模式的改进,将移除大量的全局锁,提升 memcached 在负载极高的场景下的性能。
key 的最大长度是 250 个字符。须要注意的是,250 是 memcached 服务器端内 部的限制,若是您使用的客户端支持”key 的前缀”或相似特性,那么 key(前+原始 key)的最大长度是能够超过 250 个字符的。咱们推荐使用使用较短的 key, 由于能够节省内存和带宽。
memcached 对 item 的过时时间有什么限制?
过时时间最大能够达到 30 天。memcached 把传入的过时时间(时间段)解释成 时间点后,一旦到了这个时间点,memcached 就把 item 置为失效状态。这是一 个简单但 obscure 的机制。
1MB。若是你的数据大于 1MB,能够考虑在客户端压缩或拆分到多个 key中。
为何单个 item 的大小被限制在 1M byte 以内?
啊…这是一个你们常常问的问题!
简单的回答:由于内存分配器的算法就是这样的。
详细的回答:Memcached 的内存存储引擎(引擎未来可插拔…),使用 slabs 来 管理内存。内存被分红大小不等的 slabs chunks(先分红大小相等的 slabs,而后 每一个 slab 被分红大小相等 chunks,不一样 slab 的 chunk 大小是不相等的)。chunk 的大小依次从一个最小数开始,按某个因子增加,直到达到最大的可能值。
Memcache 客户端仅根据哈希算法来决定将某个 key 存储在哪一个节点上,而不考 虑节点的内存大小。所以,您能够在不一样的节点上使用大小不等的缓存。可是一 般都是这样作的:拥有较多内存的节点上能够运行多个 memcached 实例,每一个 实例使用的内存跟其余节点上的实例相同。
关于二进制最好的信息固然是二进制协议规范:
二进制协议尝试为端提供一个更有效的、可靠的协议,减小客户端/服务器端因处 理协议而产生的 CPU 时间。
根据 Facebook 的测试,解析 ASCII 协议是 memcached 中消耗 CPU 时间最多的 环节。因此,咱们为何不改进 ASCII 协议呢?
实际上,这是一个编译时选项。默认会使用内部的 slab 分配器。您确实确实应该 使用内建的 slab 分配器。最先的时候,memcached 只使用 malloc/free 来管理 内存。然而,这种方式不能与 OS 的内存管理之前很好地工做。反复地 malloc/free 形成了内存碎片,OS 最终花费大量的时间去查找连续的内存块来知足 malloc 的 请求,而不是运行 memcached 进程。若是您不一样意,固然可使用 malloc!只 是不要在邮件列表中抱怨啊
slab 分配器就是为了解决这个问题而生的。内存被分配并划分红 chunks,一直被 重复使用。由于内存被划分红大小不等的 slabs,若是 item 的大小与被选择存放 它的 slab 不是很合适的话,就会浪费一些内存。Steven Grimm 正在这方面已经 作出了有效的改进。
全部的被发送到 memcached 的单个命令是彻底原子的。若是您针对同一份数据 同时发送了一个 set 命令和一个 get 命令,它们不会影响对方。它们将被串行化、 前后执行。即便在多线程模式,全部的命令都是原子的,除非程序有 bug:)
命令序列不是原子的。若是您经过 get 命令获取了一个 item,修改了它,而后想 把它 set 回 memcached,咱们不保证这个 item 没有被其余进程(process,未 必是操做系统中的进程)操做过。在并发的状况下,您也可能覆写了一个被其余 进程 set 的 item。
memcached 1.2.5 以及更高版本,提供了 gets 和 cas 命令,它们能够解决上面 的问题。若是您使用 gets 命令查询某个 key 的 item,memcached 会给您返回 该 item 当前值的惟一标识。若是您覆写了这个 item 并想把它写回到 memcached 中,您能够经过 cas 命令把那个惟一标识一块儿发送给 memcached。若是该 item 存放在 memcached 中的惟一标识与您提供的一致,您的写操做将会成功。若是 另外一个进程在这期间也修改了这个 item,那么该 item 存放在 memcached 中的 惟一标识将会改变,您的写操做就会失败
Session 是运行在一台服务器上的,全部的访问都会到达咱们的惟一服务器上,样咱们能够根据客户端传来的 sessionID,来获取 session,或在对应 Session 存在的状况下(session 生命周期到了/用户第一次登陆),建立一个新的 Session; 可是,若是咱们在集群环境下,假设咱们有两台服务器 A,B,用户的请求会由 Nginx 服务器进行转发(别的方案也是同理),用户登陆时,Nginx 将请求转发 至服务器 A 上,A 建立了新的 session,并将 SessionID 返回给客户端,用户在浏 览其余页面时,客户端验证登陆状态,Nginx 将请求转发至服务器 B,因为 B 并无对应客户端发来 sessionId 的 session,因此会从新建立一个新的 session, 而且再将这个新的 sessionID 返回给客户端,这样,咱们能够想象一下,用户一次操做都有 1/2 的几率进行再次的登陆,这样不只对用户体验特别差,还会让 服务器上的 session 激增,加大服务器的运行压力。
为了解决集群环境下的 seesion 共享问题,共有 4 种解决方案:
1.粘性 session
粘性 session 是指 Ngnix 每次都将同一用户的全部请求转发至同一台服务器上即将用户与服务器绑定。
2.服务器 session 复制
即每次 session 发生变化时,建立或者修改,就广播给全部集群中的服务器,使 全部的服务器上的 session 相同。
3.session 共享
缓存 session,使用 redis, memcached。
4.session 持久化
将 session 存储至数据库中,像操做数据同样才作 session
一、Redis 不只仅支持简单的 k/v 类型的数据,同时还提供 list,set,zset,hash 等数据结构的存储。而 memcache 只支持简单数据类型,须要客户端本身处理复 杂对象
二、Redis 支持数据的持久化,能够将内存中的数据保持在磁盘中,重启的时候可 以再次加载进行使用(PS:持久化在 rdb、aof)。
三、因为 Memcache 没有持久化机制,所以宕机全部缓存数据失效。Redis 配置 为持久化,宕机重启后,将自动加载宕机时刻的数据到缓存系统中。具备更好的 灾备机制。
四、Memcache 可使用 Magent 在客户端进行一致性 hash 作分布式。Redis 支 持在服务器端作分布式(PS:Twemproxy/Codis/Redis-cluster 多种分布式实现方 式)
五、Memcached 的简单限制就是键(key)和 Value 的限制。最大键长为 250 个 字符。能够接受的储存数据不能超过 1MB(可修改配置文件变大),由于这是型 slab 的最大值,不适合虚拟机使用。而 Redis 的 Key 长度支持到 512k。
六、Redis 使用的是单线程模型,保证了数据按顺序提交。Memcache 须要使用 cas 保证数据一致性。CAS(Check and Set)是一个确保并发一致性的机制,属 于“乐观锁”范畴;原理很简单:拿版本号,操做,对比版本号,若是一致就做,不一致就放弃任何操做 cpu 利用。因为 Redis 只使用单核,而 Memcached 可使用多核,因此平均每 一个核上 Redis 在存储小数据时比 Memcached 性能更 高。而在 100k 以上的数 据中,Memcached 性能要高于 Redis 。
七、memcache 内存管理:使用 Slab Allocation。原理至关简单,预先分配一系 列大小固定的组,而后根据数据大小选择最合适的块存储。避免了内存碎片。(缺 点:不能变长,浪费了必定空间)memcached 默认状况下下一个 slab 的最大值 为前一个的 1.25 倍。
八、redis 内存管理: Redis 经过定义一个数组来记录全部的内存分配状况, Redis 采用的是包装的 malloc/free,相较于 Memcached 的内存 管理方法来讲,要简 单不少。因为 malloc 首先以链表的方式搜索已管理的内存中可用的空间分配,导 致内存碎片比较多