首先说明下memcached存在如下问题
本身没有内置分布式功能,无法实现使用多台Memcache服务器来存储不同的数据,最大程度的使用相同的资源;无法同步数据,容易造成单点故障。(memagent代理实现集群)
在 Memcached中可以保存的item数据量是没有限制的,只要内存足够 。
Memcached单进程最大使用内存为2G,要使用更多内存,可以分多个端口开启多个Memcached进程
最大30天的数据过期时间,设置为永久的也会在这个时间过期,常量REALTIME_MAXDELTA
60*60*24*30控制
最大键长为250字节,大于该长度无法存储,常量KEY_MAX_LENGTH 250控制
单个item最大数据是1MB,超过1MB数据不予存储,常量POWER_BLOCK 1048576进行控制,
它是默认的slab大小
最大同时连接数是200,通过 conn_init()中的freetotal进行控制,最大软连接数是1024,通过
settings.maxconns=1024 进行控制
跟空间占用相关的参数:settings.factor=1.25, settings.chunk_size=48, 影响slab的数据占用和步进方式
memcached是一种无阻塞的socket通信方式服务,基于libevent库,由于无阻塞通信,对内存读写速度非常之快。
memcached分服务器端和客户端,可以配置多个服务器端和客户端,应用于分布式的服务非常广泛。
memcached作为小规模的数据分布式平台是十分有效果的。
memcached是键值一一对应,key默认最大不能超过128个字 节,value默认大小是1M,也就是一个slabs,如果要存2M的值(连续的),不能用两个slabs,因为两个slabs不是连续的,无法在内存中 存储,故需要修改slabs的大小,多个key和value进行存储时,即使这个slabs没有利用完,那么也不会存放别的数据。
集群配置
由于Memcached服务器与服务器之间没有任何通讯,并且不进行任何数据复制备份,所以当任何服务器节点出现故障时,会出现单点故障,如果需要实现HA,则需要通过另外的方式来解决。
通过Magent缓存代理,防止单点现象,缓存代理也可以做备份,通过客户端连接到缓存代理服务器,缓存代理服务器连接缓存连接服务器,缓存代理服务器可以连接多台Memcached机器可以将每台Memcached机器进行数据同步。如果其中一台缓存服务器down机,系统依然可以继续工作,如果其中一台Memcached机器down掉,数据不会丢失并且可以保证数据的完整性。具体可以参考:http://code.google.com/p/memagent/
memcached的分布式
Memcached作为集中式Cache,就存在着集中式的致命问题:单点问题,Memcached支持多Instance分布在多台机器上,仅仅只是解决了数据全部丢失的问题,但是当其中一台机器出错以后,还是会导致部分数据的丢失,一个篮子掉在地上还是会把部分的鸡蛋打破。
因此就需要实现一个备份机制,能够保证Memcached在部分失效以后,数据还能够依然使用,当然大家很多时候都用Cache不命中就去数据源获取的策略,但是在SIP的场景中,如果部分信息找不到就去数据库查找,那么要把SIP弄垮真的是很容易,因此SIP对于Memcached中的数据认为是可信的,因此做Cluster也是必要的。
memcached和memcache的安装请看上一篇,这里不做介绍,下面直接安装magent
1、安装magent:
[root@lys2 src]# mkdir magent [root@lys2 src]# mv magent-0.6.tar.gz magent [root@lys2 src]# cd magent [root@lys2 magent]# tar -zxvf magent-0.6.tar.gz [root@lys2 magent]# /sbin/ldconfig [root@lys2 magent]# sed -i "s#LIBS = -levent#LIBS = -levent -lm#g" Makefile [root@lys2 magent]# make (此处遇到几个报错,解决方法请看文章末尾) [root@lys2 magent]# cp magent /usr/bin/magent
2、测试magent +memcached的强大功能
开5个memcached端口依次执行
[root@lys2 magent]# memcached -m 1 -u root -d -l192.168.144.101 -p 10001 [root@lys2 magent]# memcached -m 1 -u root -d -l192.168.144.101 -p 10002 [root@lys2 magent]# memcached -m 1 -u root -d -l192.168.144.101 -p 10003 [root@lys2 magent]# memcached -m 1 -u root -d -l192.168.144.101 -p 10004 [root@lys2 magent]# memcached -m 1 -u root -d -l192.168.144.101 -p 10005
先看看是否启动监听端口成功
[root@lys2 magent]# netstat -ulpnt Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:60734 0.0.0.0:* LISTEN 1313/rpc.statd tcp 0 0 127.0.0.1:9000 0.0.0.0:* LISTEN 1479/php-fpm tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN 1291/rpcbind tcp 0 0 192.168.144.101:10001 0.0.0.0:* LISTEN 2004/memcached tcp 0 0 192.168.144.101:10002 0.0.0.0:* LISTEN 2012/memcached tcp 0 0 192.168.144.101:10003 0.0.0.0:* LISTEN 2020/memcached tcp 0 0 192.168.144.101:10004 0.0.0.0:* LISTEN 2028/memcached tcp 0 0 192.168.144.101:10005 0.0.0.0:* LISTEN 2036/memcached
接着启动magent 设置启动参数 -u当然是启动账号 -n是最大连接数,-l是magent监听的IP -p是magent监听的端口后面的格式依次是 -s IP:端口 代表是主服务器 然后指定IP:端口的格式
#命令详解 ''' -h this message -u uid -g gid -p port, default is 11211. (0 to disable tcp support) -s ip:port, set memcached server ip and port -b ip:port, set backup memcached server ip and port -l ip, local bind ip address, default is 0.0.0.0 -n number, set max connections, default is 4096 -D do not go to background -k use ketama key allocation algorithm -f file, unix socket path to listen on. default is off -i number, max keep alive connections for one memcached server, default is 20 -v verbose '''
这里设置了10001,10002,10003 为主Memcached服务器 10004,10005 为memcached备份服务器
[root@lys2 magent]# magent -uroot -n 51200 -l 192.168.144.101 -p 12000 -s 192.168.144.101:10001 -s 192.168.144.101:10002 -s 192.168.144.101:10003 -b 192.168.144.101:10004 -b 192.168.144.101:10005
执行命令后 可以先查看是否启动成功
[root@lys2 magent]# ps -ef | grep magent root 2062 1 0 09:06 ? 00:00:00 magent -uroot -n 51200 -l 192.168.144.101 -p 12000 -s 192.168.144.101:10001 -s 192.168.144.101:10002 -s 192.168.144.101:10003 -b 192.168.144.101:10004 -b 192.168.144.101:10005 root 2067 1881 0 09:07 pts/0 00:00:00 grep magent
3、在XP客户端上测试
直接连接magent 端口 12000 执行stats
说明magent 里面已经负载了3个memcached 端口接着我们继续set
好了 依次设置了3个key ,这里说明下参数 <command name> <key> <flags> <exptime> <bytes>
既然设置了3个key,我们来读取看执行命令get key1 get key2 get key3依次返回了
到此,一个缓存写入已经存取的过程就完成了
然后我们直接登陆memcached的端口get数据看 它是怎么样保存的
依次telnet 192.168.144.101 10001 192.168.144.101 10002 192.168.144.101 10003 192.168.144.101 10004 192.168.144.101 10005 去获取key值
telnet 192.168.144.101 10001:
telnet 192.168.144.101 10002:
telnet 192.168.144.101 10003:
telnet 192.168.144.101 10004:
telnet 192.168.144.101 10005:
然后我把主服务器的10001 10002 10003的进程全部kill了
[root@lys2 magent]# netstat -ulpnt | egrep "10001|10002|10003" | grep LISTEN | awk '{print $7}' | awk -F / '{print $1}' | xargs kill [root@lys2 magent]# netstat -unlpt Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:60734 0.0.0.0:* LISTEN 1313/rpc.statd tcp 0 0 192.168.144.101:12000 0.0.0.0:* LISTEN 16346/magent tcp 0 0 127.0.0.1:9000 0.0.0.0:* LISTEN 1479/php-fpm tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN 1291/rpcbind tcp 0 0 192.168.144.101:10004 0.0.0.0:* LISTEN 16330/memcached tcp 0 0 192.168.144.101:10005 0.0.0.0:* LISTEN 16338/memcached
再在magent的端口上get key
并不影响取值。不过如果备用服务器也死了的话,就无力了,
集群搭建到此全部完成!
报错解决:
make
错误1:
gcc -lrt -Wall -g -O2 -I/usr/local/include -m64 -c -o magent.o magent.c
magent.c: In function ‘writev_list’:
magent.c:729: error: ‘SSIZE_MAX’ undeclared (first use in this function)
magent.c:729: error: (Each undeclared identifier is reported only once
magent.c:729: error: for each function it appears in.)
make: *** [magent.o] Error 1
解决办法:
vi ketama.h
在开头加入
#ifndef SSIZE_MAX
# define SSIZE_MAX 32767
#endif
错误2:
gcc -Wall -g -O2 -I/usr/local/include -m64 -c -o magent.o magent.c
gcc -Wall -g -O2 -I/usr/local/include -m64 -c -o ketama.o ketama.c
gcc -Wall -g -O2 -I/usr/local/include -m64 -o magent magent.o ketama.o /usr/lib64/libevent.a /usr/lib64/libm.a
/usr/lib64/libevent.a(event.o): In function `gettime’:
(.text+0×449): undefined reference to `clock_gettime’
/usr/lib64/libevent.a(event.o): In function `event_base_new’:
(.text+0x72a): undefined reference to `clock_gettime’
collect2: ld returned 1 exit status
make: *** [magent] Error 1
解决办法
vim Makefile
CFLAGS = -Wall -g -O2 -I/usr/local/include $(M64)
改为:
CFLAGS = -lrt -Wall -g -O2 -I/usr/local/include $(M64)
错误3:centos 6
[root@test magent]# make
gcc -Wall -g -O2 -I/usr/local/include -m64 -c -o magent.o magent.c
gcc -Wall -g -O2 -I/usr/local/include -m64 -c -o ketama.o ketama.c
gcc -Wall -g -O2 -I/usr/local/include -m64 -o magent magent.o ketama.o /usr/lib64/libevent.a /usr/lib64/libm.a
gcc: /usr/lib64/libm.a:没有那个文件或目录
make: *** [magent] 错误 1
解决办法
ln -s /usr/lib64/libm.so /usr/lib64/libm.a
注:有可能还会报错 gcc: /usr/lib64/libevent.a: 没有那个文件或目录
如果有,可执行
vi Makefile
找到 LIBS = /usr/lib64/libevent.a /usr/lib64/libm.a
修改 LIBS = /usr/libevent 的安装路径/libevent.a /usr/lib64/libm.a
例: LIBS = /usr/lib/libevent.a /usr/lib64/libm.a
查看magent是否安装成功
cd usr/bin/magent ./magent
please provide -s "ip:port" argument
memcached agent v0.6 Build-Date: Oct 15 2012 16:12:30
Usage:
-h this message
-u uid
-g gid
-p port, default is 11211. (0 to disable tcp support)
-s ip:port, set memcached server ip and port
-b ip:port, set backup memcached server ip and port
-l ip, local bind ip address, default is 0.0.0.0
-n number, set max connections, default is 4096
-D don't go to background
-k use ketama key allocation algorithm
-f file, unix socket path to listen on. default is off
-i number, set max keep alive connections for one memcached server, default is 20
-v verbose