在做服务器端应用开发,我们常常要考虑很多东西。从单台机器到集群,从混乱的结构到分层结构,接着是系统优化,中间作cache处理,后端优化缓存。
今天就讨论一下服务器端缓存:)
先来看一下这么一个应用场景:当应用A要获取应用B的一批数据,这个数据一开始为一个定值10,而这些数据有个特点,一般几天内不会作变化,而且对业务的影响比较小。应用B由于是网络提供服务,获取数据需要一定时间。
我们把上面的场景抽取一下:
应用B提供的获取数据方法:getData()
按照一般编程方法是这样:会直接调用这个函数进行使用
但是是否有更好的解决方案,我们注意到,这里的数据是今天或更长的时间才变更一次的,是否可以利用这个时间点把内容缓存起来,于是新的构想如下:初始一个日期,如果这个日期值不为null并且加上一天小于今天的时间,我们就认为数据不过期,不去请求使用默认值,如果非这种情况则重新去请求这个值,这样就每隔一天才请求一次数据,如果请求量比较大。如一天10万次,优化还是比较可观的。
这里就引入了一个东西——缓存,和把应用服务其中的一部分内存使用起来,同时减少了网络请求的数量。
从上面这个例子我们了解到我们会有意识无意识的把一些性能瓶颈的点放到缓存里面,这就是今天我们主题要介绍的memcached的产生的一个原因吧(个人理解)。
我们知道,如果应用服务器的内存有限,我们很难这样操作,同时这样也不便于对这个cache机制进行管理和优化,memcached则很好的解决了这方面的需求。
个人理解,memcached有以下几个优点:
1.cache同一管理
2.协议简单且实用
3.可扩展性高,基于文本协议,直接用telnet就可以操作
4.可同一处理并优化cache系统
5.不做多余事情
memcached采用c/s结构,如果使用过http或smtp、pop等协议时就知道了。memcached基于tcp和udp实现,可以采用telnet进行连接。
服务器端启动命令:
memcached -p 11211 -m 10m -f 1.25 -vvv(-d)
这里稍微解释一下:
-p:指定端口,11211是默认端口
-m:指定该memcached的内存最大使用内存量
-f:指定chunk增长因子大小,1.2版本该默认值为2,1.4版本该默认值为1.25,该值越小所能提供的chunk间隔越小,可以减少内存的浪费
-vvv:主要从控制台输出信息
举例:
slab class 1: chunk size 80 perslab 13107
slab class 2: chunk size 104 perslab 10082
slab class 3: chunk size 136 perslab 7710
slab class 4: chunk size 176 perslab 5957
.........................
slab class 38: chunk size 367192 perslab 2
slab class 39: chunk size 458992 perslab 2
slab class 40: chunk size 573744 perslab 1
slab class 41: chunk size 717184 perslab 1
slab class 42: chunk size 1048576 perslab 1
这里有几个概念:slab class、chunk
chunk是一个固定大小的内存块空间
slab class是一组相同大小chunk的合集
我们看到这里面分配了42个slab class,他们的chunk大小从80bit到1048576都有,默认每个slab class都预先初始化1M空间。如果一个slab class大小不够用了会再分配直到内存不够用
操作只有有限的几个命令:
1.连接:telnet 192.168.0.123 11211
这个是telnet连接,当然既然是基于tcp udp协议,所以很多语言都有扩展,java、c、perl、python等都有。11211是默认端口,服务器可以指定
2.存储:
add 添加,只有在该键不存在时才写入
replace 替换,只有在该建存在时才写入
set 设置,不管任何条件都写入
格式一般如下:command key flag exptime bytes
比如要设置一个大小为键值对为[key1,value1],过期为1分钟,可以如下些:
set key1 0 60
values1
写在两行是因为需要换行输入
3.取回:
get key \r\n:取回单个
gets key \r\n:取回多个,空格分割
返回键值和有效期
4.增加/减少:
incr key value \r\n:增加
decr key value \r\n:减少
5.统计(监控最有用的命令)
stats \r\n:获取一堆信息
stat : 获取单个指定的信息
具体命令请google memcached protocol,有一个文本,内容很全,不做介绍了。
这个抛出几个问题:
1.边界测试,如果我最大空间比插入的对象还小会怎么样?
答案:
在你插入这个数据时,服务器不给你响应,也不提是你操作成功还是失败,而是一直保持连接,算是一个bug吧
2.memcached中过期时间是如何判断的?
答案:
memcached采用的是服务器时间来比对是否过期,而不是程序内部时钟,这就存在一个问题,如果集群中访问memcached服务器的时间不一致,会出现memcached写进去时就过期,测试环境如果遇到写入memcached失败,首先考虑一下这方面的原因。同时,对于服务器,要安装上ntp服务,保持服务器上时间一致。对于xen虚拟机,如果不同步,需要开启修改手动改写权限,echo 1 >/proc/sys/net/ipv4/ip_forward,然后同步时间
3.存储在memcached中的数据是否一定可用
答案:
1.memcached是基于内存的,这样如果断电等原因就很容易数据全部丢失,这样就有memcachedb
2.memcached采用的LRU算法,如果内存不够用,memcached会把最近未使用的空间给释放掉,可能有人会问这很不安全,其实前提搞错了,memcached不是为了安全而存在,而是因为速度而存在。
4.memcache一般都作哪些优化?
答案:
1.空间优化,memcached的机制是会产生一定的空间浪费,在系统使用到一定程度,会发现内存中的对象发布图,根据这个现象可以进行优化,如重新改变增长因子,改变内存初始chunk大小。当然这些是破坏性的,不是调整
2.访问速度优化,这个是主要优化的点
3.服务器连接优化
当然还有很多,就不一一举例了
5.memcached有没有集群的概念?
答案:
memcached没有集群的概念,因为彼此都不知道都有哪些服务存在,但是有分布式概念,两者完全不同
6.memcached如何作监控
答案:
一个程序为了相对安全使用必然涉及到这个问题,memcached本身不存在任何监控方面的功能,但是memcached是基于tcp、udp协议,所以你能很容易进行扩展
抛砖引玉:)