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 缓存图解

这里写图片描述


重要的启动项

这里写图片描述

  • -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

这里写图片描述

在 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 完全一样,不单独写
这里写图片描述

get 查询

get key

返回 key 的值

set 是设置和修改值

参数和 add ,replace 一样,但功能不一样. 如下比较:
这里写图片描述
用 add 时, key 不存在,才能建立此键值.

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

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

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

如下图的演示该图中name 是已经存在而 date 原本不存在. set 都可以成功设置
这里写图片描述

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

这里写图片描述

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 的内存管理与删除机制

slab allocator 缓解内存碎片化

memcached 用 slab allocator 机制来管理内存. slab allocator 原理: 预告把内存划分成数个 slab class 仓库.(每个 slab class 大小 1M)
各仓库,切分成不同尺寸的小块(chunk).
需要存内容时,判断内容的大小,为其选取合理的仓库.
这里写图片描述
这里写图片描述
由于 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 中的一些参数限制

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

分布式集群算法

memcached 如何实现分布式

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

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

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

分布式之取模算法

这里写图片描述

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

假设有 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)得到相同的结果
这里写图片描述
所以 命中率在服务器 down 的短期内, 急剧下降至 (N-1)/(N*(N-1)) = 1/(N-1)

所以: 服务器越多, 则 down 机的后果越严重!
这里写图片描述

一致性哈希算法原理

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

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

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

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

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

当某个节点 down 后,只影响该节点顺时针之后的 1 个节点,而其他节点不受影响.因此,Consistent Hashing 最大限度地抑制了键的重新分布
这里写图片描述

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

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

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

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

这样,某真实节点 down 后,则把其影响平均分担到其他所有节点上.
这里写图片描述


缓存雪崩现象

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

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

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

这里写图片描述


缓存的无底洞现象 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:永久数据很久没动了….

官方解决方案: 永久数据和非永久数据分开放
这里写图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值