1、memcache介绍
百科介绍很详细,这里不再啰嗦。
搬过来一些比较重要的信息:
MemCache的工作流程如下:先检查客户端的请求数据是否在memcached中,如有,直接把请求数据返回,不再对数据库进行任何操作;如果请求的数据不在memcached中,就去查数据库,把从数据库中获取的数据返回给客户端,同时把数据缓存一份到memcached中(memcached客户端不负责,需要程序明确实现);每次更新数据库的同时更新memcached中的数据,保证一致性;当分配给memcached内存空间用完之后,会使用LRU(Least Recently Used,最近最少使用)策略加上到期失效策略,失效数据首先被替换,然后再替换掉最近未使用的数据。
Memcache是一个高性能的分布式的内存对象缓存系统,通过在内存里维护一个统一的巨大的hash表,它能够用来存储各种格式的数据,包括图像、视频、文件以及数据库检索的结果等。简单的说就是将数据调用到内存中,然后从内存中读取,从而大大提高读取速度。
Memcache是danga的一个项目,最早是LiveJournal 服务的,最初为了加速 LiveJournal 访问速度而开发的,后来被很多大型的网站采用。
Memcached是以守护程序(监听)方式运行于一个或多个服务器中,随时会接收客户端的连接和操作。
2、磁盘cache和memcache的区别
磁盘cache的开销
磁盘IO延迟和资源开销,如果涉及到File,还要算上文件系统开销。
memcache开销
建立一个到Memcached的TCP连接,可以使用到Memcached的持久连接,或者采用链接池。
3、安装及应用
1、安装
在此目录下进行安装,将对应压缩包考至此目录:
ubuntu@jx-vm04:/usr/local/wangpei/cloud/memcache$ ls
libevent-2.0.21-stable.tar.gz memcached-1.4.15.tar.gz
或者直接从官网下载,自己查找合适版本:
下载:http://www.danga.com/memcached/dist/memcached-1.2.5.tar.gz
Memcache用到了libevent这个库用于Socket的处理,所以还需要安装libevent。
下载:http://www.monkey.org/~provos/libevent-1.3.tar.gz
安装依赖lib
解压:
memcache$ sudo tar -zxvf libevent-2.0.21-stable.tar.gz
将 libevent 安装在 /usr/local 下,
ubuntu@jx-vm04:/usr/local/wangpei/cloud/memcache/libevent-2.0.21-stable$ sudo ./configure –prefix=/usr/local/libevent
编译、运行:
libevent-2.0.21-stable$ sudo make
$ sudo make install
安装memcache:
memcache$ sudo tar -zxvf memcached-1.4.15.tar.gz
依赖libevent安装memcached到指定目录下:
/memcached-1.4.15$ ./configure –with-libevent=/usr/local/libevent
$sudo make
$susdo make install
memcache安装在 /usr/local/bin下,可以进行查看:
ubuntu@jx-vm04:/usr/local/bin$ ls
docker memcached
ubuntu@jx-vm04:/usr/local/bin$ ls -al /usr/local/bin/mem*
-rwxr-xr-x 1 root root 447510 7月 3 16:32 /usr/local/bin/memcached
2、启动memcache
/usr/local/bin$ memcached -m 64 -p 11211 -u nobody -vv
slab class 1: chunk size 96 perslab 10922
slab class 2: chunk size 120 perslab 8738
slab class 3: chunk size 152 perslab 6898
slab class 4: chunk size 192 perslab 5461
slab class 5: chunk size 240 perslab 4369
slab class 6: chunk size 304 perslab 3449
slab class 7: chunk size 384 perslab 2730
slab class 8: chunk size 480 perslab 2184
slab class 9: chunk size 600 perslab 1747
slab class 10: chunk size 752 perslab 1394
slab class 11: chunk size 944 perslab 1110
slab class 12: chunk size 1184 perslab 885
slab class 13: chunk size 1480 perslab 708
slab class 14: chunk size 1856 perslab 564
slab class 15: chunk size 2320 perslab 451
slab class 16: chunk size 2904 perslab 361
slab class 17: chunk size 3632 perslab 288
slab class 18: chunk size 4544 perslab 230
slab class 19: chunk size 5680 perslab 184
slab class 20: chunk size 7104 perslab 147
slab class 21: chunk size 8880 perslab 118
slab class 22: chunk size 11104 perslab 94
slab class 23: chunk size 13880 perslab 75
slab class 24: chunk size 17352 perslab 60
slab class 25: chunk size 21696 perslab 48
slab class 26: chunk size 27120 perslab 38
slab class 27: chunk size 33904 perslab 30
slab class 28: chunk size 42384 perslab 24
slab class 29: chunk size 52984 perslab 19
slab class 30: chunk size 66232 perslab 15
slab class 31: chunk size 82792 perslab 12
slab class 32: chunk size 103496 perslab 10
slab class 33: chunk size 129376 perslab 8
slab class 34: chunk size 161720 perslab 6
slab class 35: chunk size 202152 perslab 5
slab class 36: chunk size 252696 perslab 4
slab class 37: chunk size 315872 perslab 3
slab class 38: chunk size 394840 perslab 2
slab class 39: chunk size 493552 perslab 2
slab class 40: chunk size 616944 perslab 1
slab class 41: chunk size 771184 perslab 1
slab class 42: chunk size 1048576 perslab 1
<26 server listening (auto-negotiate)
<27 server listening (auto-negotiate)
<28 send buffer was 212992, now 268435456
<29 send buffer was 212992, now 268435456
<28 server listening (udp)
<28 server listening (udp)
<28 server listening (udp)
<28 server listening (udp)
<29 server listening (udp)
<29 server listening (udp)
<29 server listening (udp)
<29 server listening (udp)
想让 memcached 作为 daemon 在后台运行,只需要加-d 选项
$memcached -m 64 -p 11211 -u nobody -d
查看服务启动情况:
ubuntu@jx-vm04:/usr/local/bin$ ps -ef | grep memcache
root 4139 1 2 5月26 ? 1-00:18:56 java -Xms300M -Xmx300M -XX:+UseParallelGC -XX:+AggressiveOpts -XX:+UseFastAccessorMethods -XX:+HeapDumpOnOutOfMemoryError -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:logs/gc20170526112346.log -cp .:config/:lib/commons-lang-2.5.jar:lib/commons-logging-1.1.1.jar:lib/fqueue-0.1.1-release.jar:lib/log4j-1.2.16.jar:lib/netty-3.2.4.Final.jar:lib/slf4j-api-1.6.1.jar:lib/slf4j-nop-1.6.1.jar com.google.code.fqueue.memcached.StartServer
ubuntu 22888 1 0 16:39 ? 00:00:00 memcached -m 64 -p 11211 -u nobody -d
ubuntu 22897 21437 0 16:40 pts/3 00:00:00 grep –color=auto memcache
ubuntu@jx-vm04:/usr/local/bin$
参数说明:
$memcached -d -m 10 -u root -l 192.168.0.200 -p 12000 -c 256 -P /tmp/memcached.pid
-d选项是启动一个守护进程,
-m是分配给Memcache使用的内存数量,单位是MB,我这里是10MB,
-u是运行Memcache的用户,我这里是root,
-l是监听的服务器IP地址,如果有多个地址的话,我这里指定了服务器的IP地址192.168.0.200,
-p是设置Memcache监听的端口,我这里设置了12000,最好是1024以上的端口,
-c选项是最大运行的并发连接数,默认是1024,我这里设置了256,按照你服务器的负载量来设定,
-P是设置保存Memcache的pid文件,如保存在 /tmp/memcached.pid,
2)如果要结束Memcache进程,执行:
kill `cat /tmp/memcached.pid`
3、memcache和redis的使用区别:
1、存储方式:
memecache 把数据全部存在内存之中,断电后会挂掉,数据不能超过内存大小
redis有部份存在硬盘上,这样能保证数据的持久性,支持数据的持久化(笔者注:有快照和AOF日志两种持久化方式,在实际应用的时候,要特别注意配置文件快照参数,要不就很有可能服务器频繁满载做dump)。
2、数据支持类型:
redis在数据支持上要比memecache多的多。
3、使用底层模型不同:
新版本的redis直接自己构建了VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求。
4、运行环境不同:
redis目前官方只支持Linux 上去行,从而省去了对于其它系统的支持,这样的话可以更好的把精力用于本系统 环境上的优化,虽然后来微软有一个小组为其写了补丁。但是没有放到主干上。
强调下,如果断电,memcache数据会丢失,redis有存储机制;redis是单核运行,memcache是多核运行支持分布式,redis集群的读写节点。
4、memcache代码测试
package memcached;
import com.danga.MemCached.MemCachedClient;
import com.danga.MemCached.SockIOPool;
import java.util.Date;
/**
* Created with goDemo
* Created by wangpei on 17/7/3.
*/
public class MemCachedManager {
// 创建全局的唯一实例
protected static MemCachedClient mcc = new MemCachedClient();
protected static MemCachedManager memCachedManager = new MemCachedManager();
// 设置与缓存服务器的连接池
static {
// 服务器列表和其权重
String[] servers = { "10.10.75.15:11211" };
Integer[] weights = { 3 };
// 获取socke连接池的实例对象
SockIOPool pool = SockIOPool.getInstance();
// 设置服务器信息
pool.setServers(servers);
pool.setWeights(weights);
// 设置初始连接数、最小和最大连接数以及最大处理时间
pool.setInitConn(5);
pool.setMinConn(5);
pool.setMaxConn(250);
pool.setMaxIdle(1000 * 60 * 60 * 6);
// 设置主线程的睡眠时间
pool.setMaintSleep(30);
// 设置TCP的参数,连接超时等
pool.setNagle(false);
pool.setSocketTO(3000);
pool.setSocketConnectTO(0);
// 初始化连接池
pool.initialize();
// 压缩设置,超过指定大小(单位为K)的数据都会被压缩
// mcc.setCompressEnable(true);
// mcc.setCompressThreshold(64 * 1024);
}
/**
* 保护型构造方法,不允许实例化!
*
*/
protected MemCachedManager() {
}
/**
* 获取唯一实例.
*
* @return
*/
public static MemCachedManager getInstance() {
return memCachedManager;
}
/**
* 添加一个指定的值到缓存中.
*
* @param key
* @param value
* @return
*/
public boolean add(String key, Object value) {
return mcc.add(key, value);
}
public boolean add(String key, Object value, Date expiry) {
return mcc.add(key, value, expiry);
}
public boolean replace(String key, Object value) {
return mcc.replace(key, value);
}
public boolean replace(String key, Object value, Date expiry) {
return mcc.replace(key, value, expiry);
}
/**
* 根据指定的关键字获取对象.
*
* @param key
* @return
*/
public Object get(String key) {
return mcc.get(key);
}
public static void main(String[] args) {
MemCachedManager cache = MemCachedManager.getInstance();
cache.add("hello", 234);
System.out.print("get value : " + cache.get("hello"));
}
}