Memcached简介
作者:互联网
一、关于Memcached
1.1 Memcached的介绍
Memcached是一个自由开源的,高性能,分布式内存对象缓存系统。一般的使用目的是,通过缓存数据库查询结果,减少数据库访问次数,以提高动态Web应用的速度、提高可扩展性。
1.2 Memcached的工作流程
MemCache的工作流程如下:先检查客户端的请求数据是否在memcached中,如有,直接把请求数据返回,不再对数据库进行任何操作;如果请求的数据不在memcached中,就去查数据库,把从数据库中获取的数据返回给客户端,同时把数据缓存一份到memcached中;每次更新数据库的同时更新memcached中的数据,保证一致性;当分配给memcached内存空间用完之后,会使用LRU
(Least Recently Used,最近最少使用)策略加上到期失效策略,失效数据首先被替换,然后再替换掉最近未使用的数据。
1.3 Memcached的安装
1.下载地址:
1. 32位系统 1.4.5版本:http://static.runoob.com/download/memcached-1.4.5-x86.zip
2. 64位系统 1.4.5版本:http://static.runoob.com/download/memcached-1.4.5-amd64.zip
2.安装步骤
1、解压下载的安装包到指定目录。
2、在 memcached1.4.5 版本之后,memcached 不能作为服务来运行,需要使用任务计划中来开启一个普通的进程,在 window 启动时设置 memcached自动执行。
我们使用管理员身份执行以下命令将 memcached 添加来任务计划表中:
bash schtasks /create /sc onstart /tn memcached /tr "'c:\memcached\memcached.exe' -m 512"
然后再解压的目录中打开cmd,并输入:bash memcached -m 128 -p 11211 -vvv
运行Memcached。
我们通过telnet客户端就可以连接Memcached,在命令串口输入:cmd telnet 127.0.0.1 11211
二、Memcached相关命令
2.1 存储命令
1.Memcached set 命令
作用:Memcached set 命令用于将 value(数据值) 存储在指定的 key(键) 中。如果set的key已经存在,该命令可以更新该key所对应的原来的数据,也就是实现更新的作用。
语法:
set key flags exptime bytes [noreply]
value
**参数说明如下:**
1.key:键值 key-value 结构中的 key,用于查找缓存值。
2.flags:可以包括键值对的整型参数,客户机使用它存储关于键值对的额外信息 。
3.exptime:在缓存中保存键值对的时间长度(以秒为单位,0 表示永远)
4.bytes:在缓存中存储的字节数
5.noreply(可选): 该参数告知服务器不需要返回数据
6.value:存储的值(始终位于第二行)(可直接理解为key-value结构中的value)
2.Memcached add 命令
作用:Memcached add 命令用于将 value(数据值) 存储在指定的 key(键) 中。如果 add 的 key 已经存在,则不会更新数据(过期的 key 会更新),之前的值将仍然保持相同,并且您将获得响应 NOT_STORED。
语法:
add key flags exptime bytes [noreply]
value
3.Memcached replace 命令
作用:Memcached replace 命令用于替换已存在的 key(键) 的 value(数据值)。如果 key 不存在,则替换失败,并且您将获得响应 NOT_STORED。
语法:
replace key flags exptime bytes [noreply]
value
4.Memcached append 命令
作用:Memcached append 命令用于向已存在 key(键) 的 value(数据值) 后面追加数据 。
语法:
append key flags exptime bytes [noreply]
value
5.Memcached prepend 命令
作用:Memcached prepend 命令用于向已存在 key(键) 的 value(数据值) 前面追加数据 。
语法:
prepend key flags exptime bytes [noreply]
value
2.2 查找命令
1.Memcached get 命令
作用:Memcached get 命令获取存储在 key(键) 中的 value(数据值) ,如果 key 不存在,则返回空。
语法:
get key [,key1,....keyn]
2.Memcached delete命令
作用:Memcached delete 命令用于删除已存在的 key(键)。
语法:
delete key
2.Memcached 自增/自减命令
作用:Memcached incr 与 decr 命令用于对已存在的 key(键) 的数字值进行自增或自减操作。incr 与 decr 命令操作的数据必须是十进制的32位无符号整数。如果 key 不存在返回 NOT_FOUND,如果键的值不为数字,则返回 CLIENT_ERROR,其他错误返回 ERROR。
语法:
incr key increment_value // 让key增加 increment_value
decr key decrement_value // 让key减少 decrement_value
Memcached, Redis三者的区别
Memcached
是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态、数据库驱动网站的速度。Memcached基于一个存储键/值对的hashmap。其守护进程(daemon )是用C写的,但是客户端可以用任何语言来编写,并通过memcached协议与守护进程通信。
Memcached的优点:
1.Memcached可以利用多核优势,单实例吞吐量极高,可以达到几十万QPS(取决于key、value的字节大小以及服务器硬件性能,日常环境中QPS高峰大约在4-6w左右)。适用于最大程度扛量。
2.支持直接配置为session handle。
Memcached的局限性:
1.只支持简单的key/value数据结构,不像Redis可以支持丰富的数据类型。
2.无法进行持久化,数据不能备份,只能用于缓存使用,且重启后数据全部丢失。
3.无法进行数据同步,不能将MC中的数据迁移到其他MC实例中。
redis
是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。 它支持多种类型的数据结构,如 字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets) 与范围查询, bitmaps, hyperloglogs 和 地理空间(geospatial) 索引半径查询。 Redis 内置了 复制(replication),LUA脚本(Lua scripting), LRU驱动事件(LRU eviction),事务(transactions) 和不同级别的 磁盘持久化(persistence), 并通过 Redis哨兵(Sentinel)和自动 分区(Cluster)提供高可用性(high availability)。
redis 的优点:
1.支持多种数据结构,如 string(字符串)、 list(双向链表)、dict(hash表)、set(集合)、zset(排序set)、hyperloglog(基数估算)。
2.支持持久化操作,可以进行aof及rdb数据持久化到磁盘,从而进行数据备份或数据恢复等操作,较好的防止数据丢失的手段。
3.单线程请求,所有命令串行执行,并发情况下不需要考虑数据一致性问题。
4.支持pub/sub消息订阅机制,可以用来进行消息订阅与通知。
redis 的缺点:
1.Redis在string类型上会消耗较多内存,可以使用dict(hash表)压缩存储以降低内存耗用。
2.Mc和Redis都是Key-Value类型,不适合在不同数据集之间建立关系,也不适合进行查询搜索。比如redis的keys pattern这种匹配操作,对redis的性能是灾难。
实际案例
假设我们有一个web应用,里面有商品信息,文章信息,评论信息,其他信息,我们希望对其做缓存,那么我们在ServiceImpl层就不在调用DAOmpl层,而是调用CacheImpl层,在CacheImpl层中判断要取出的商品信息是否已经在缓存中,如果在了,那么直接从缓存中去,如果没有这个时候还是从数据库中取,同时将它放到缓存中,以便下次使用。
第一步、新建一个常量类,用于上面的四种信息的在数组中的索引。
public class MemcachedConstant {
public static final int MEMCACHED_GOODSDETAIL = 0;
public static final int MEMCACHED_ARTICLEDETAIL = 1;
public static final int MEMCACHED_COMMENTDETAIL = 2;
public static final int MEMCACHED_OTHERDETAIL = 3;
}
第二步、由于有大量的商品信息,我们在放入缓存时必须给定一个key,那么我们最好规范的命名不同类别的key,如商品的key就是商品的前缀加上商品的编号。
public class MemcachedKeyUtil {
private static final String GOODS_KEY_PREFIX = "goods_";
public static String getGoodsKey(long goodsId) {
return GOODS_KEY_PREFIX + goodsId;
}
}
第三步、使用工具类来操作memcached
public class MemcachedUtil {
private int MEMCACHED_SERVER_NUM = 4;
private SockIOPool[] pools = new SockIOPool[MEMCACHED_SERVER_NUM];
private MemCachedClient[] mcs = new MemCachedClient[MEMCACHED_SERVER_NUM];
private final String[] poolNames = new String[] { "GOODSDETAIL_POOL", "", "", "" };
private static MemcachedUtil instance;
private MemcachedUtil() {
this.init();
}
// 单例
public static MemcachedUtil getInstance() {
if (MemcachedUtil.instance == null) {
synchronized (MemcachedUtil.class) {
if (MemcachedUtil.instance == null) {
MemcachedUtil.instance = new MemcachedUtil();
}
}
}
return MemcachedUtil.instance;
}
public Object get(int index, String key) {
return this.mcs[index].get(key);
}
public boolean set(int index, String key, Object value) {
return this.mcs[index].set(key, value);
}
public boolean delete(String key) {
return this.mcs[index].delete(key);
}
public MemCachedClient getMemCachedClient(int index) {
return this.mcs[index];
}
public void init() {
for (int i = 0; i < MEMCACHED_SERVER_NUM; ++i) {
this.pools[i] = SockIOPool.getInstance(poolNames[i]);
this.pools[i].setServers(servers);
this.pools[i].setWeights(weights);
this.pools[i].setInitConn(initConn);
this.pools[i].setMinConn(minConn);
this.pools[i].setMaxConn(maxConn);
this.pools[i].setMaxIdle(maxIdle);
this.pools[i].setMaxBusyTime(maxBusyTime);
this.pools[i].setMaintSleep(maintSleep);
this.pools[i].setNagle(ifNagle);
this.pools[i].setSocketTO(socketTO);
this.pools[i].setSocketConnectTO(socketConnectTO);
this.pools[i].setFailover(ifFailOver);
this.pools[i].setFailback(ifFailback);
this.pools[i].setAliveCheck(ifAliveCheck);
this.pools[i].initialize();
this.mcs[i] = new MemCachedClient(poolNames[i]);
}
}
}
第四步、新建一个基类以供所用继承它的CacheImpl直接调用MemcachedUtil里的方法,如果不写该类那么在CacheImpl中会有很多重复的操作MemcachedUtil的代码。
public class MemcachedSupport {
public boolean setDetailData(String key, Object value) {
return MemcachedUtil.getInstance().set(MemcachedConstant.MEMCACHED_DETAIL, key, value);
}
public Object getDetailData(String key) {
return MemcachedUtil.getInstance().get(MemcachedConstant.MEMCACHED_DETAIL, key);
}
public boolean deleteDetailData(String key) {
return MemcachedUtil.getInstance().delete(MemcachedConstant.MEMCACHED_DETAIL);
}
}
第五步、新建一个GoodsCacheImpl,该类的作用就是一开始所说的,娶不到缓存,就调用DAO查询并放入缓存,如果缓存中有就直接从缓存中拿。
public class GoodsCacheImpl extends MemcachedSupport{
@Resource(name = "goodsDaoImpl")
private GoodsDao goodsDao;
public Goods selectGoodsById(long goodsId) {
Goods goods = null;
String goodsKey = MemcachedKeyUtil.getGoodsKey(goodsId);
goods = (Goods) getDetailData(goodsKey);
if (goods == null) {
goods = goodsDao.selectGoodsById(goodsId, false);
if (goods != null) {
setDetailData(goodsKey, goods);
}
}
return goods;
}
}
标签:缓存,简介,value,key,pools,Memcached,public 来源: https://www.cnblogs.com/cyoking/p/14128242.html