memcached详解

Memcached是一个自由开源的,高性能,分布式内存对象缓存系统。

安装

确保linux已安装gcc环境,memcached依赖libevent事件通知库
一 安装libevent 官网:http://libevent.org
1:上传并解压libevent压缩包。
2:进入解压包后执行 ./configure -prefix=/usr/local/libevent prefix后为安装路径
3: 执行编译命令 make 再执行安装命令 make install
二 安装memcached 官网:https://memcached.org/
1:上传并解压memcached压缩包。
2:进入解压包后 ./configure -prefix=/usr/local/memcached --with-libevent=/usr/local/libevent/ --with-libevent为指定libevent安装的路径。
3: 执行编译命令 make 再执行安装命令 make install
4:启动 ./usr/local/memcached/bin/memcached -d -m 128 -p 11211 -u root
-d:后台启动
-m:设置内存大小,单位为M,即整个memcached所能使用的内存大小
-p:监听端口号,默认为11211
-u:启动用户名
查看是否启动 ps -ef|grep memcached

基础说明

1:基于内存,宕机或重启后数据丢失。
2:以键值对形式存储。key最大为250个字节,最大存储不能超过1M,下面内存机制会说到。
3:内部使用LRU(最近最少使用)淘汰机制,并以Lazy Expiration惰性机制处理过期键值对,即当某个键值对设置的过期时间到了之后,并不会自动把该键值对标上过期,而是直到对该键值对进行访问后如查询操作,才会去判断记录的时间戳是否过期,这样不需耗费资源去轮询查看哪些键值对是否过期。默认为永不过期,但最多存活为30天。即使过期被设置为过期的数据并不会立即被删除,而是打上了过期标志,等到真正进行LRU时才会被删除。
4:使用NIO实现IO多路复用,还使用多线程,可同时处理多个请求。
5:支持分布式,但并不是服务器端来实现,每个服务器端之间没有任何通信,其分布式是通过其客户端来实现的,其客户端有java、php等各种语言来实现,java中较常用的为XMemcached,XMemcached同样是基于NIO的客户端,并提供连接池的功能,在高并发下性能更加得以体现。

分布式算法实现

我们知道服务器各节点间是没有通信的,而分布式则由客户端来实现,如何知道某个值到哪台服务器去存放或获取呢,常用算法有余数计算分散法和一致性Hash算法。

一:余数计算分散法
可简单理解为:目前有node0、node1、node2三个服务器节点,要放到缓冲里的键值对的键key1的hashCode假设为31,31%3=1,则该键值对路由到服务节点node1上进行存放。加入被匹配到的节点无法连接,则会尝试把连接的次数加到key1后再进行取余匹配。
特点:取余算法可以让键值对随机均匀的分配在各个不同的节点上,同时也因为是通过取余算法,所以给节点加权重是不容易实现。并且在服务器节点增加或减少时都会对极大影响原有的缓冲数据命中率。比如再增加一个节点,原本key1取余后为3匹配到了新增节点node3上,所以节点0、1、2这三个节点原有的数据都会失效。
二:一致性Hash算法
把各服务节点的hash值分布到0~2^32的一致性Hash环上,键值对的键对应的hash值也映射到Hash环上,并顺时针找到的第一个节点就是要访问的服务节点。如下图,key1的hash值在环上所在位置顺时针寻找到的第一个节点node1即为要访问的服务节点。在这里插入图片描述
加入此时加入了节点node3,如下图,key1匹配到的服务器将是node3,原来的几台服务器中,受影响的只是键的hash值落在node0~node3这一区间的数据,其余不受影响。在这里插入图片描述
特点:这一算法服务器伸缩性有所提升,增加或删除节点对原有节点的影响不大,但如果服务器节点在Hash环上分布不均匀,则会产生数据倾斜问题,即比如node0与node1的区间太大,则会有更多的键值对会存到node1上。当然可以通过引入虚拟节点解决数据倾斜的问题。
虚拟节点大致可以理解为:如把node1节点分成多个地址后再映射在Hash环上,这样一台服务器就可以接收多个Hash环区间的键值对了,如假设把node1节点分成两个虚拟地址。当然可以根据需要把各个节点虚拟多个虚拟节点以达到数据的均匀分配。
在这里插入图片描述

memcached存储机制

memcached采用的是Slab allocation的内存预先分配分配机制,解决了malloc() 机制动态的分配内存产生的内存碎片问题。
先了解几个memcached的内存概念。slab、chunk、slab class
slab:一个内存块,以page为单位,默认一个page的大小为1M,不同的slab会把page分配成大小不同的chunk。但同一个slab下的chunk大小是相同的。
chunk:用于存放数据的最小单位,以字节为单位,一个chunk仅能存放一个item,即一个键值对。
slab class:大小相同的chunk组成一个slab class。
在这里插入图片描述
如上图,memcached默认生成39中不同大小的chunk,即slab class 1 到clab class 39,chunk大小以1.25递增,即clab class1 的chunk大小为96字节,共有10922个,10922x96=1M,clab class2的chunk大小为120(96x1.25),共有8378个chunk,120x8738=1M=1个page,说明初始化的时候不同的slab都只默认分配一个page。那数据又是怎么存放的呢?假设有一个键值对大小为100个字节,96个字节的chunk是放不下的,就只能放到120个字节的chunk里,先判断是否有空闲的chunk,如果有则放入进去,那么这剩余的这20个字节就直接浪费掉了。如果没有空闲的chunk,则在内存还没用完的情况下会给该chunk为120字节的内存块slab申请一个page,page再把1M分成8378个大小为120字节的chunk,最后把数据存放到其中一个chunk里。
虽然默认chunk是以1.25来递增的,也可以通过参数-f来更改,假如我改成以2倍递增如下图可以看到slab class分组会少很多,因为chunk之间跨越会更大,同样可能会造成更严重的内容浪费。
在这里插入图片描述
想要查看slab的各种状态信息,可以telnet ip 11211(默认端口号)连接到服务器后,通过stats slabs命令可查看,如下图,查看的是chunk大小为96的slab,该slab下分配了一个page(total_pages),已经使用的chunk为1个(used_chunks),空余的chunks数等等参数都有,以及该slab下的命中率等信息(命中率=get_hits/(get_hits+get_misses)),get_misses为查询成功但没获取到数据的次数,我这里没有体现出来。在这里插入图片描述
当我们存放的数据越来越多后,memcahed默认分配的内存是64M,可通过-m参数修改,假设放入的数据越来越多,现在有一个大小为90个字节的item需要存入,检查发现chunk大小为96字节没有空余的chunk,该slab则会申请内存,发现这64M内存都用完了,则会触发在该slab下进行LRU。

https://www.cnblogs.com/zhoujinyi/p/5554083.html
https://www.jianshu.com/p/80340c92dfd1

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值