memcached笔记

memcached是什么?

memcached is a high-performance,
distributed memory object caching system,
generic in nature, but originally intended for use in
speeding up dynamic web applications by alleviating database load.

You can think of it as a short-term memory for your applications.
memcached是一个高性能,分布式内存对象缓存系统,具备通用性,但本来的目的是用于为动态web程序加速,并减轻数据库的的负担.
这里写图片描述


memcached 缓存图解

memcached笔记_第1张图片


重要的启动项

memcached笔记_第2张图片

  • -p < num> 监听的TCP端口 (缺省: 11211)
  • -d 以守护进程方式运行Memcached
  • -u < username> 运行Memcached的账户,非root用户
  • -m < num> 最大的内存使用, 单位是MB,缺省是 64 MB
  • -c < num> 软连接数量, 缺省是 1024
  • -v 输出警告和错误信息
  • -vv 打印客户端的请求和返回信息
  • -h 打印帮助信息
  • -i 打印memcached和libevent的版权信息

启动memcached

memcached笔记_第3张图片

在 win 下启动
memcached -m 64 -p 11211 -vvv


连接memcached

memcached已经打开,并监听11211端口,
因此,任何能满足端口通信的工具,
都可以连接memcahced

我们利用telnet来连接

telnet localhost 11211

连接后 ctrl+] ,然后回车, 打开回显功能
输入stats 回车, 即可查看memcached运行状态.
memcached 客户端与服务器端的通信比较简单,使用的基于文本的协议,而不是二进制协议. (http 协议也是这样), 因此我们通过 telnet 即可与 memcached 作交互. 另开一个终端,并运行 telnet 命令 (开启 memcached 的终端不要关闭)

# 格式 telnet host port# telnet localhost 11211Trying ::1...Connected to localhost.Escape character is '^

命令

add 增

语法: add key flag expire length 回车

key 给值起一个独特的名
flag 标志,要求为一个正整
expire 有效期
length 缓存的长度(字节为单
这里写图片描述
flag 的意义:
memcached 基本文本协议,传输的东西,理解成字符串来存储. 想:让你存一个 php 对象,和一个 php 数组,怎么办?
答:序列化成字符串,往出取的时候,自然还要反序列化成 对象/数组/json 格式等等. 这时候, flag 的意义就体现出来了. 比如, 1 就是字符串, 2 反转成数组 3,反序列化对象…..

expire 的意义:
设置缓存的有效期,有 3 种格式

  • 1:设置秒数, 从设定开始数,第 n 秒后失效.
  • 2:时间戳, 到指定的时间戳后失效.
    比如在团购网站,缓存的某团到中午 12:00 失效.
    add key 0 1379209999 6
  • 3: 设为 0. 不自动失效

注: 有种误会,设为 0,永久有效.错误的

  • 1:编译 memcached 时,指定一个最长常量,默认是 30 天. 所以,即使设为 0,30 天后也会失效.
  • 2:可能等不到 30 天,就会被新数据挤出去

delete 删除

delete key [time seconds]

删除指定的 key. 如加可选参数 time,则指删除 key,并在删除 key 后的 time 秒内,不允许get,add,replace 操作此 key.
这里写图片描述

replace 替换

replace key flag expire length

参数和 add 完全一样,不单独写
memcached笔记_第4张图片

get 查询

get key

返回 key 的值

set 是设置和修改值

参数和 add ,replace 一样,但功能不一样. 如下比较:
memcached笔记_第5张图片
用 add 时, key 不存在,才能建立此键值.

但对于已经存在的键,可以用replace 进行替换/更改
这里写图片描述
repalce,key 存在时,才能修改此键值,如上图,date 不存在,则没改成功.

而 set 想当于有 add replace 两者的功能.
set key flag expire leng 时

  • 如果服务器无此键 —-> 增加的效果
  • 如果服务器有此键 —-> 修改的效果

如下图的演示该图中name 是已经存在而 date 原本不存在. set 都可以成功设置
memcached笔记_第6张图片

incr decr增加/减少值的大小

语法: incr/decr key num

set age 0 0 2
28
stored
get age
value age 0 2
28
end
incr age 1
29
incr age 2
31
decr age 1
30
decr age 2
28

memcached笔记_第7张图片

stats 统计命令

把 memcached 当前的运行信息统计出来

stats
stat pid 2296 进程号
stat uptime 4237 持续运行时间
stat time 1370054990
stat version 1.2.6
stat pointer_size 32
stat curr_items 4 当前存储的键个数
stat total_items 13
stat bytes 236
stat curr_connections 3
stat total_connections 4
stat connection_structures 4
stat cmd_get 20
stat cmd_set 16
stat get_hits 13
stat get_misses 7 // 这 2 个参数 可以算出命中率
stat evictions 0
stat bytes_read 764
stat bytes_written 618
stat limit_maxbytes 67108864
stat threads 1
end

缓存有一个重要的概念: 命中率.

命中率是指:
(查询到数据的次数/查询总数)*100%

如上, 13/(13+7) = 60+% , 的命中率.

flush_all 清空所有的存储对象

memcached笔记_第8张图片


memcached 的内存管理与删除机制

slab allocator 缓解内存碎片化

memcached 用 slab allocator 机制来管理内存. slab allocator 原理: 预告把内存划分成数个 slab class 仓库.(每个 slab class 大小 1M)
各仓库,切分成不同尺寸的小块(chunk).
需要存内容时,判断内容的大小,为其选取合理的仓库.
memcached笔记_第9张图片
memcached笔记_第10张图片
由于 slab allocator 机制中, 分配的 chunk 的大小是”固定”的, 因此, 对于特定的 item,可能造
成内存空间的浪费. 比如, 将 100 字节的数据缓存到 122 字节的 chunk 中, 剩余的 22 字节就浪费了
这里写图片描述
对于 chunk 空间的浪费问题,无法彻底解决,只能缓解该问题.

开发者可以对网站中缓存中的 item 的长度进行统计,并制定合理的 slab class 中的 chunk 的大小.

可惜的是,我们目前还不能自定义 chunk 的大小,但可以通过参数来调整各 slab class 中 chunk 大小的增长速度. 即增长因子, grow factor!默认1.25

grow factor 调优

memcached 在启动时可以通过­f 选项指定 Growth Factor 因子, 并在某种程度上控制 slab 之间的差异. 默认值为 1.25. 但是,在该选项出现之前,这个因子曾经固定为 2,称为”powers of 2” 策略

>memcached ­f 2 ­vvv
slab class 1: chunk size 128 perslab 8192
slab class 2: chunk size 256 perslab 4096
slab class 3: chunk size 512 perslab 2048
slab class 4: chunk size 1024 perslab 1024
....
.....
slab class 10: chunk size 65536 perslab 16
slab class 11: chunk size 131072 perslab 8
slab class 12: chunk size 262144 perslab 4
slab class 13: chunk size 524288 perslab 2
可见,从 128 字节的组开始,组的大小依次增大为原来的 2 倍. 来看看 f=1.25 时的输出:
>memcached -f 1.25 -vvv
slab class 1: chunk size 88 perslab 11915
slab class 2: chunk size 112 perslab 9362
slab class 3: chunk size 144 perslab 7281
slab class 4: chunk size 184 perslab 5698
....
....
slab class 36: chunk size 250376 perslab 4
slab class 37: chunk size 312976 perslab 3
slab class 38: chunk size 391224 perslab 2
slab class 39: chunk size 489032 perslab 2

memcached 的过期数据惰性删除

  • 1: 当某个值过期后,并没有从内存删除, 因此,stats 统计时, curr_item 有其信息
  • 2: 当某个新值去占用他的位置时,当成空 chunk 来占用.
  • 3: 当 get 值时,判断是否过期,如果过期,返回空,并且清空, curr_item 就减少了.

即——这个过期,只是让用户看不到这个数据而已,并没有在过期的瞬间立即从内存删除. 这个称为 lazy expiration, 惰性失效.

好处—— 节省了 cpu 时间和检测的成本

memcached 此处用的 lru 删除机制.

如果以 122byte 大小的 chunk 举例, 122 的 chunk 都满了, 又有新的值(长度为 120)要加入, 要
挤掉谁?
memcached 此处用的 lru 删除机制.

(操作系统的内存管理,常用 fifo,lru 删除)

  • lru: least recently used 最近最少使用
  • fifo: first in ,first out

原理: 当某个单元被请求时,维护一个计数器,通过计数器来判断最近谁最少被使用. 就把谁 t 出.

注: 即使某个 key 是设置的永久有效期,也一样会被踢出来!
即——永久数据被踢现象
memcached笔记_第11张图片

memcached 中的一些参数限制

  • key 的长度: 250 字节, (二进制协议支持 65536 个字节)
  • value 的限制: 1m, 一般都是存储一些文本,如新闻列表等等,这个值足够了.
  • 内存的限制: 32 位下最大设置到 2g

分布式集群算法

memcached 如何实现分布式

memcached 是一个”分布式缓存”,然后 memcached 并不像mongoDB 那样,允许配置多个节点,且节点之间”自动分配数据”.

就是说——memcached 节点之间,是不互相通信的.

因此,memcached 的分布式,要靠用户去设计算法,把数据分布在多个memcached 节点中.

分布式之取模算法

memcached笔记_第12张图片

取模算法对缓存命中率的影响

假设有 8 台服务器, 运行中,突然 down 一台, 则求余的底数变成 7

key0%8==0, key0%7 ==0 hits
....
key6%8==6, key6%7== 6 hits
key7%8==7, key7%7==0 miss
key9%8==1, key9%7 == 2 miss
...
key55%8 ==7 key55%7 == 6 miss

一般地,我们从数学上归纳之:
有 N 台服务器, 变为 N-1 台,
每 N*(N-1)个数中, 只有(n-1)个单元,%N, %(N-1)得到相同的结果
memcached笔记_第13张图片
所以 命中率在服务器 down 的短期内, 急剧下降至 (N-1)/(N*(N-1)) = 1/(N-1)

所以: 服务器越多, 则 down 机的后果越严重!
memcached笔记_第14张图片

一致性哈希算法原理

Consistent Hashing 原理:
首先求出memcached服务器(节点)的哈希值,并将其配置到0~2^32的圆(continuum)上。

然后用同样的方法求出存储数据的键的哈希值,并映射到圆上。

然后从数据映射到的位置开始顺时针查找,将数据保存到找到的第一个服务器上。

如果超过2^32仍然找不到服务器,就会保存到第一台memcached服务器上。
memcached笔记_第15张图片
通俗理解一致性哈希:
把各服务器节点映射放在钟表的各个时刻上, 把 key 也映射到钟表的某个时刻上.
该 key 沿钟表顺时针走,碰到的第 1 个节点即为该 key 的存储节点。
memcached笔记_第16张图片
memcached笔记_第17张图片

一致性哈希对其他节点的影响

当某个节点 down 后,只影响该节点顺时针之后的 1 个节点,而其他节点不受影响.因此,Consistent Hashing 最大限度地抑制了键的重新分布
memcached笔记_第18张图片

一致性哈希+虚拟节点对缓存命中率的影响

由图 5.5 中可以看到,理想状态下,

  • 1) 节点在圆环上分配分配均匀,因此承担的任务也平均,但事实上, 一般的 Hash 函数对于节点在圆环上的映射,并不均匀.
  • 2) 当某个节点 down 后,直接冲击下 1 个节点,对下 1 个节点冲击过大,能否把 down 节点上的压力平均的分担到所有节点上?

完全可以——引入虚拟节点来达到目标
虚拟节点即——N 个真实节点,把每个真实节点映射成 M 个虚拟节点, 再把 M*N 个虚拟节点, 散列在圆环上. 各真实节点对应的虚拟节点相互交错分布

这样,某真实节点 down 后,则把其影响平均分担到其他所有节点上.
memcached笔记_第19张图片


缓存雪崩现象

缓存雪崩一般是由某个缓存节点失效,导致其他节点的缓存命中率下降, 缓存中缺失的数据去数据库查询.短时间内,造成数据库服务器崩溃.

重启 DB,短期又被压跨,但缓存数据也多一些.
DB 反复多次启动多次,缓存重建完毕,DB 才稳定运行.

或者,是由于缓存周期性的失效,比如每 6 小时失效一次,那么每 6 小时,将有一个请求”峰值”, 严重者甚至会令 DB 崩溃.

memcached笔记_第20张图片


缓存的无底洞现象 multiget-hole

官方回应:http://dormando.livejournal.com/521163.html

请求多台服务器并不是问题的症结,真正的原因在于客户端在请求多台服务器时是并行的还是串行的!

问题是很多客户端,包括Libmemcached在内,在处理Multiget多服务器请求时,使用的是串行的方式!

也就是说,先请求一台服务器,然后等待响应结果,接着请求另一台,结果导致客户端操作时间累加,请求堆积,性能下降。

如何解决这个棘手的问题呢?
只要保证Multiget中的键只出现在一台服务器上即可!

比如说用户名字(user:foo:name),用户年龄(user:foo:age)等数据在散列到多台服务器上时,不应按照完整的键名(user:foo:name和user:foo:age)来散列的,而应按照特殊的键(foo)来散列的,这样就保证了相关的键只出现在一台服务器上。

以PHP的 Memcached客户端为例,有getMultiByKey和setMultiByKey可供使用。


老数据被踢现象

网上有人反馈为”memcached数据丢失”,明明设为永久有效,却莫名其妙的丢失了.

其实,这要从2个方面来找原因:
即前面介绍的 懒删除,与 LRU 最近最少使用记录删除.

提示:

  • 1:数据在内存中并未真正删除.,下次去get他时才知道失效.
  • 2:如上房间可能被很多未删除的过期数据占满
  • 3:永久数据很久没动了….

官方解决方案: 永久数据和非永久数据分开放
memcached笔记_第21张图片

你可能感兴趣的:(nosql)