有关memcached企业面试案例讲解
1、Memcached是什么,有什么作用?
a. memcached是一个开源的、高性能的内存的缓存软件,从名称上看Mem就是内存的意思,而Cache就是缓存的意思。
b. 作用:memcached通过在事先规划好的内存空间中,临时缓存数据库中的各类数据,以达到减少业务对数据库的直接高并发访问,从而达到提升数据库的访问性能,加速网站集群动态应用服务的能力。
2、Memcached服务在企业集群架构中应用场景
(1). 作为数据库的前端缓存应用
a. 完整缓存(易),静态缓存
例如:商品分类,以及商品信息,可事先放在内存里,然后再对外提供数据访问,这个被称之为预热。用户访问时可以只读取memcached缓存,不读取数据库了。
b. 热点缓存(难)
需要前端程序配合。只缓存热点的数据,即缓存经常被访问的数据。
先预热基础数据,然后在再动态更新。先读取缓存,如果缓存里没有对应的数据,再去读取数据库,然后把读到的数据放入缓存。
特殊说明:
1. 如果碰到电商秒杀等高并发的业务,一定要事先预热,或者其他思想实现,例如:秒杀只是获取资格,而不瞬间秒杀到手商品。
2. 如果数据更新,同时触发缓存更新,防止给用户过期数据。
c. 对于持久化缓存存储系统,例如:redis,可以替代一部分数据库的存储。一些简单的数据业务,投票,统计,好友关注,商品分类等。
(2). 作为集群的session会话共享存储。
http://oldboy.blog.51cto.com/2561410/1331316
http://oldboy.blog.51cto.com/2561410/1323468
3、Memcached服务在不同企业业务应用场景中的工作流程
a. 当web程序需要访问后端数据库获取数据时会优先访问memcached内存缓存,如果缓存中有数据就直接获取返回前端服务及用户,如果没有数据(没有命中),再由程序请求后端的数据库服务器,获取到对应的数据后,除了返回给前端服务及用户数据外,还会把数据放到Memcached内存中进行缓存,等待下次请求被访问,Memcached内存始终是数据库的挡箭牌,从而大大的减轻数据库的访问压力,提高整个网站架构的响应速度,提升了用户体验。
b. 当程序更新,修改或删除数据库已有的数据时,会同时发送请求通知memcached已经缓存过的同一个ID内容的旧数据失效,从而保证memcache中的数据和数据库中的数据一致。
如果是在高并发场合,除了通知memcached过期的缓存失效外,还会通过相关机制,使得在用户访问新数据前,通过程序预先把更新过的数据推送到memcached中缓存起来,这样可以减少数据库的访问压力,提升memcached中缓存的命中率。
c. 有一款数据库插件可以在写入更新数据库后,自动抛给memcached缓存起来,自身不CACHE。
4、Memcached服务分布式集群如何实现?
特殊说明:memcached集群和web服务集群是不一样的,所有memcached的数据总和才是数据库的数据。每台memcached都是部分数据。
a. 程序端实现
程序加载所有memcached的ip列表,通过对key做hash(一致性哈希)
b. 负载均衡器
通过对key做hash(一致性哈希)。
说明:一致性哈希算法的目的是不但保证每个对象只请求一个对应的服务器,而且当节点宕机缓存服务器的更新重新分配比例降到最低。
==========================================================
5、Memcached服务特点及工作原理是什么?
a. 全部数据存放于内存中,无持久性存储的设计,重启服务,数据会丢失。
b. 节点之间相互独立
c. 异步I/O模型,基于libevent模型的事件通知机制
d. key/value对形式存在的
e. C/S模式架构,C语言编写,总共代码2000多行
f. 当内存中缓存的数据容量达到启动时设定的内存值时,就自动使用LRU算法删除过期的缓存数据
g. 可以对存储的数据设置过期时间,这样过期后数据自动被清除,服务本身不会监控过期,则是在访问的时候查看key的时间戳判断是否过期。
i. memcache内存分配机制是对特定的内存进行分块,再把多个块分为一组。
6、简述Memcached内存管理机制原理?
malloc的全称是memory allocation,中文叫动态内存分配,当无法知道内存具体位置的时候,想要绑定真正的内存空间,就需要用到动态的分配内存。
早期的memcached的内存管理方式是通过malloc分配的内存,使用完后通过free来回收内存,这种方式容易产生内存碎片并降低操作系统对内存的管理效率。加重操作系统内存管理器的负担,最坏的情况下,会导致操作系统比memcached进程本身还慢,为了解决上述问题,Slab Allocator内存分配机制就诞生了。
现在Memcached利用 slab allocator机制来分配和管理内存。
Slab Allocator机制原理是按照预先规定的大小,将分配给memcached的内存分割成特定长度的内存块(chunk),再把尺寸相同的内存块分成组(chunks slab class),这些内存块不会释放,可以重复利用。
memcached服务器中保存着slab内空闲chunk的列表,根据该列表选择chunk,然后将数据缓存于其中。当有数据存入时,memcached根据接收到的数据大小,选择最适合数据大小的slab分配一个能存下这个数据的最小内存块(chunk).例如:有100字节一个数据,就会被分配存入下面112字节的一个内存块中,这样会有12字节被浪费掉,这部分空间不能被使用了,这就是slab allocator机制的一个缺点。
slab allocator还有重复使用已分配的内存的作用。也就是说,分配到的内存不会释放,而是重复利用。
slab allocator的主要术语:
Page: 分配给slab的内存空间,默认是1MB,分配给slab之后根据slab的大小切分成chunk。
chunk: 用于缓存数据的内存空间或内存块。
slab class: 特定大小的多个chunk的集合或组。
memcached slab allocator内存管理机制缺点:
slab allocator解决了当初的内存碎片问题,但新的机制也给memcached带来了新的问题,这个问题就是,由于分配的是特定长度的内存,因此无法有效利用分配的内存。例如,将100字节的数据缓存到128字节的chunk中,剩余的28字节就浪费了。
避免浪费内存的办法是,预先计算出应用存入数据大小,或把同一业务类型的数据存入一个Memcached服务器中,确保存的数据大小相对均匀,这样就可以减少内存的浪费。还有一种办法是,在启动时指定"-f"参数,能在某种程序上控制内存组之间的大小差异。在应用中使用memcached时,通常可以不重新设置这个参数,使用默认值1.25进行部署。如果想优化memcached对内存的使用,可以考虑重新计算数据的预期平均长度,调整这个参数来获得合适的设置值。
-f <factor> chunk size growth factor (default: 1.25)!
使用 Growth Factor对Slab Allocator内存管理机制调优
memcached在启动时指定Growth Factor因子(通过f选项),就可以在某种程序上控制slab之间的差异。默认值是1.25。但是,在该选项出现之间,这个因子曾经固定为2,称为“powers of 2”策略。让我们用以前的设置,以verbose模式启动memcached试试看:
#memcached -f 2 vv
下面是启动后的verbose输出:
可以,从128字节的组开始,组的大小依次增大为原来的2倍,这样设置的问题是,slab之间的差别比较大,有些情况下就相当浪费内存。因此,为尽量减少内存浪费,就增加了growth factor这个选项。
来看看现在的默认设置(f=1.25)时的输出:
7、Memcached的删除原理与删除机制?
memcached主要的cache机制是LRU(最近最少用)算法,加上自身的过期失效。当您存数据到memcached中,可以指定该数据在缓存中可以呆多久which is forever, or some time in the future. 如果memcached的内存不够用了,过期的slabs会优先被替换,接着就轮到最老的未被使用的slabs。在某些情况下(完整缓存),如果不想使用LRU算法,那么可以通过“-M”参数来启动memcached,这样memcached在内存耗尽时,会返回一个报错信息。
-M return error on memory exhausted (rather than removing items)
8、Memcached服务端与客户端的安装部署与使用测试
memcached的安装比较简单,很多平台支持memcached,常见的有:linux、FreeBSD、Solaris、Windows
软件地址:
memcached下载地址:http://www.danga.com/memcached/
libevent下载地址:http://monkey.org/~provos/libevent/
网友安装资料:http://instance.iteye.com/blog/1691705
安装memcached前需要先安装libevent,有关libevent我们在前文已经介绍,首先用wget下载libevent:
操作命令:
tar zxf libevent-1.4.13-stable.tar.gz
cd libevent-1.4.13-stable
./configure
make
make install
安装memcached 服务端
操作过程:
tar xf memcached-1.4.13.tar.gz
cd memcached-1.4.13
./configure
make
make install
提示:
memcache-2.2.4.tgz <--客户端
memcached-1.4.13.tar.gz <--服务端
启动memcached
(1)配置ld.so.conf路径防止启动Memcached时报错
# memcached --help
memcached: error while loading shared libraries: libevent-1.4.so.2: cannot open shared object file: No such file or directory
echo "/usr/local/lib" >>/etc/ld.so.conf
ldcoonfig
(2) 开始启动memcached
# memcached -m 16m -p 11211 -d -u root -c 8192
参数说明:
-m #分配的内存大小
-p #port
-d #后台启动
-c #并发连接数
(3) 检查启动结果:
netstat -ntulp
ps -ef | grep memcached
(4) 启动多个实例
memcached -m 1m -p 11212 -d -uroot -c 8192
(5) 写入数据检查结果
向memcached中添加数据: 键值对
key1 --> values1
key2 --> values2
a. 通过nc写入
# printf "set key008 0 0 10
oldboy0987
"|nc 127.0.0.1 11211 #存数据
提示:命令的字节是10,那么后面就要10个字符。否则添加不成功。
# printf "get key001
" |nc 127.0.0.1 11211 #取数据
# printf "delete key001
" | nc 127.0.0.1 11211 #删除数据
b. 通过telnet写入
Escape character is '^]'.
set user 0 0 6 #设置key
oldboy #存的key值
STORED
get user #取key值
VALUE user 0 6
oldboy
END
操作memcached命令的语法:
set key 0 0 10
<command> <key> <flags> <exptime> <byte>
安装memcache客户端
wget http://pecl.php.net/get/memcache-2.2.5.tgz
tar zxvf memcache-2.2.5.tgz
cd memcache-2.2.5
/usr/local/php/bin/phpize
./configure --enable-memcache --with-php-config=/usr/local/php/bin/php-config --with-zlib-dir
make && make install
安装完成后,在如下目录中会有一个memcache.so文件:
/usr/local/php/lib/php/extensions/no-debug-non-zts-200906026/
然后修改php的php.ini文件:
==>将extension_dir = "./"
==>修改为:extension_dir = "/usr/local/php/lib/php/extensions/no-debug-non-zts-200906026/"
==>并添加一行:extension=memcache.so
然后apache或者nginx
==>程序连接memcached测试
cat op_mem.php
<?php
$memcache = new Memcache; //创建一个memcache对象
$memcache->connect('127.0.0.1', 11212) or die ("Could not connect"); //连接Memcached服务器
$memcache->set('key001','oldboy001'); //设置一个变量到内存中,名称是key001值是oldboy001
$memcache->set('key002','oldboy002'); //设置一个变量到内存中,名称是key002值是oldboy002
$get_value01=$memcache->get('key001'); //从内存中取出key001值
$get_value02=$memcache->get('key002'); //从内存中取出key002值
echo $get_value02. "<br>";
echo $get_value01;
?>
9、如何实现集群中的session共享存储?
修改php.ini文件:中[session]部分如下内容:
session.save_handler = memcache
session.save_path = "tcp://10.0.0.7:11211"
10、如何获取MEMCACHED服务的状态信息,例如:命中率
========================================
11、通过Nagios监控Memcached需要监控哪些指标
12、redis是什么,有什么作用?
13、memcached与redis的区别?