Memcached 入门

1.什么是Memcached 

a.在Web服务开发中,服务端缓存是服务实现中所常常采用的一种提高服务性能的方法。其通过记录某部分计算结果来尝试避免再次执行得到该结果所需要的复杂计算,从而提高了服务的运行效率。

   除了能够提高服务的运行效率之外,服务端缓存还常常用来提高服务的扩展性。因此一些大规模的Web应用,如Facebook,常常构建一个庞大的服务端缓存。而它们所最常使用的就是Memcached。

b.Memcached简介

 在介绍Memcached之前,让我们首先通过一个示例了解什么是服务端缓存。

  相信大家都玩过一些网络联机游戏吧。在我那个年代(03年左右),这些游戏常常添加了对战功能,并提供了天梯来显示具有最优秀战绩的玩家以及当前玩家在天梯系统中的排名。这是游戏开发商所常常采用的一种聚拢玩家人气的手段。而希望在游戏中证明自己的玩家则会由此激发斗志,进而花费更多时间来在天梯中取得更好的成绩。

  就天梯系统来说,其最主要的功能就是为玩家提供天梯排名的信息,而并不允许玩家对该系统中所记录的数据作任何修改。这样设定的结果就是,整个天梯系统的读操作居多,而写操作很少。反过来,由于一个游戏中的玩家可能有上千万甚至上亿人,而且在线人数常常达到上万人,因此对天梯的访问也会是非常频繁的。这样的话,即使每秒钟只有10个人访问天梯中的排名,对这上亿个玩家的天梯排名进行读取及排序也是一件非常消耗性能的事情。

  一个自然而然的想法就是:在对天梯排名进行一次计算后,我们在服务端将该天梯排名缓存起来,并在其它玩家访问的时候直接返回该缓存中所记录的结果。而在一定时间段之后,如一个小时,我们再对缓存中的数据进行更新。这样我们就不再需要每个小时执行成千上万次的天梯排名计算了。

  而这就是服务端缓存所提供的最重要功能。其既可以提高单个请求的响应速度,又可以降低服务层及数据库层的压力。除此之外,多个服务实例都可以读取该服务端缓存所缓存的信息,因此我们也不再需要担心这些数据在各个服务实例中都保存了一份进而需要彼此同步的问题,也即是提高了扩展性。

c.Memcached是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。

它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提供动态、数据库驱动网站的速度。

Memcached基于一个存储键值对的hashmap。其守护进程(daemon )是用C写的,但是客户端可以用任何语言来编写,并通过memcached协议与守护进程通信。

d.Memcache和Memcached到底有什么区别?

Memcache 是 danga.com 的一个项目,最早是为 LiveJournal 服务的,目前全世界不少人使用这个缓存项目来构建自己大负载的网站,来分担数据库的压力。

Memcached 是一个开源、高性能、分布式内存对象缓存系统 。

Memcache 是这个项目的名称,而 memcached 是它服务器端的主程序文件名 。

二、Memcached 作用

Memcached 是以守护程序方式运行于一个或多个服务器中,随时接受客户端的连接操作。客户端首先与 Memcached

服务建立连接,然后存取对象。保存在 Memcached 中的对象是放置在内存中的,而不是在硬盘上。

Memcached 进程运行之后,会预申请一块较大的内存空间,自己进行管理,用完之后再申请,不是每次需要的

时候去向操作系统申请。Memcached将对象保存在一个巨 大的Hash表中,它还使用NewHash算法来管理Hash表,

从而获得进一步的性能提升。所以当分配给Memcached的内存足够大的时 候,Memcached的时间消耗基本上只是

网络Socket连接了。

总之,Memcached用于动态Web应用以减轻数据库负载。它通过在内存中缓存数据和对象来减少读取数据库的次

数,从而提高动态、数据库驱动网站的速度。

三、Memcached 运行原理

Memcached处理的原子是每一个(key,value)对(以下简称kv对),key会通过一个hash算法转化成hash-key,

便于查找、对比以及做到尽可能的散列。同时,memcached用的是一个二级散列,通过一张大hash表来维护。

Memcached有两个核心组件组成:服务端(Server)和客户端(Client),在一个memcached的查询中,Client

先通 过计算key的hash值来确定kv对所处在的Server位置。当Server确定后,客户端就会发送一个查询请求给

对应的Server,让它来查找确 切的数据。因为这之间没有交互以及多播协议,所以 memcached交互带给网络的

影响是最小化的。

 

 


2.主要用在哪里

1.通过在内存中缓存数据和对象来减少读取数据库的次数,从而提供动态、数据库驱动网站的速度;

2.在一个memcache组件查询中,client先通过key的hash值来确定kv在service端的位置,当server端确定后,客户端就会发一个请求个server端。让它来查找出确切数据,因为这之间没有交互以及多播协议,因此带给网络的影响最小;

3.Memcached使用了一种叫Slab的结构。在该分配算法中,内存将按照1MB的大小划分为页,而该页内存则会继续被分割为一系列具有相同大小的内存块。

如果您一旦知道了您所需要缓存的数据的特征,如通常情况下数据的大小以及各个数据的差异幅度,那么您就可以根据这些数据的特征来设置上面所提到的各个参数。如果数据在通常情况下都比较小,那么我们就需要将最小块的大小调整得小一些。如果数据的大小变动不是很大,那么我们可以将块大小的递增倍数设置得小一些,从而使得各个块的大小尽量地贴近需要存储的数据,以提高内存的利用率。

 


3.怎么使用

linux安装

1.Linux系统安装memcached,首先要先安装libevent库。
yum install libevent libevent-devel                    自动下载安装(Redhat/Fedora/Centos)

2.安装 Memcached
yum install memcached
源代码安装
wget http://memcached.org/latest                    下载最新版本

tar -zxvf memcached-1.x.x.tar.gz                    解压源码

cd memcached-1.x.x                                  进入目录

./configure --prefix=/usr/local/memcached           配置

make && make test                                   编译

sudo make install                                   安装

3.Memcached 运行
memcached -d -m 64M -u root -l 192.168.0.38 -p 11211

-d 守护线程

-m 内存

-u 用户

-l ip

-p 端口

4.连接

# telnet 192.168.0.38 11211

常用指令 

 http://www.runoob.com/memcached/memcached-set-data.html

set key flags exptime bytes [noreply] 
value 

等等 ..


5.java连接memched

1.导入jar包

		<dependency>      
		    <groupId>net.spy</groupId>
		    <artifactId>spymemcached</artifactId>
		    <version>2.12.0</version>
		</dependency> 

2.新建类 

package com.xxq.qianniu.rest.framework.system;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.Date;
import java.util.concurrent.atomic.AtomicBoolean;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.xxq.qianniu.rest.util.DateUtil;

import net.spy.memcached.MemcachedClient;

public class MemcacheClient {
	
	private static Log LOG = LogFactory.getLog(MemcacheClient.class);
	  
	private static final String APP_NAME = "QINNIU";

	private static MemcacheClient memcacheClient = null;
	
	private MemcachedClient memcachedClient = null;
	
	private volatile AtomicBoolean initFlage = new AtomicBoolean(false);
	
	private static final MemcacheClient getInstance() {
		if (null == memcacheClient) {
			memcacheClient = new MemcacheClient();
		}
		return memcacheClient;
	}
	
	private MemcacheClient() {
		;
	}
	
	public void init() {
		// 摄像新值跟旧值比较,如果一直正在初始化,原子性的
		if (initFlage.getAndSet(true)) {
			return ;
		}
		if (null != memcachedClient) {
			memcachedClient.shutdown();
		}
		try {
			memcachedClient = new MemcachedClient(new InetSocketAddress("192.168.0.38", 11211));
		} catch (IOException e) {
			LOG.error(e.getMessage(), e);
			throw new RuntimeException(e);
		} 
		if(checkCacheAvailable()) {
			 memcachedClient.delete("testKey");
			 LOG.info("MemcacheClient componenet init success , addrss is : " + "192.168.0.38:11211");
		} else {
			 LOG.error("MemcacheClient componenet init fail , addrss is : " + "192.168.0.38:11211");
		}
		initFlage.set(false);// 初始化完成
	}
	
	
    private boolean checkCacheAvailable() {
    	memcachedClient.set("testKey", 0, "testValue");
        return "testValue".equals(memcachedClient.get("testKey"));
    }
    
	public static void main(String[] args) {
		MemcacheClient.getInstance().init();
	}
    
    
    public Object get(String key) throws IOException {
        key = APP_NAME + "_" + key;
        Object value = null;
        Long sTime = System.currentTimeMillis();
        try {
            value = memcachedClient.get(key);
        } catch (Throwable e) {
            LOG.error("【" + (System.currentTimeMillis() - sTime) / 1000D + "】GET error for " + e.getMessage() + ", key = " + key, e);
            init();
        }
        return value;
    }
    
    public Object getWithoutAppName(String key) throws IOException {
        Object value = null;
        Long sTime = System.currentTimeMillis();
        try {
            value = memcachedClient.get(key);
        } catch (Throwable e) {
            LOG.error("【" + (System.currentTimeMillis() - sTime) / 1000D + "】GET error for " + e.getMessage() + ", key = " + key, e);
            init();
        }
        return value;
    }

    public boolean delete(String key) {
        key = APP_NAME + "_" + key;
        boolean res = false;
        try {
            memcachedClient.delete(key);
            res = true;
        } catch (Throwable e) {
            LOG.error("DELETE error for " + e.getMessage() + ",key = " + key, e);
        }
        return res;
    }

    public boolean put(String key, Object obj) {
        key = APP_NAME + "_" + key;
        boolean res = false;
        try {
            memcachedClient.set(key, 0, obj);
            res = true;
        } catch (Throwable e) {
            LOG.error("PUT error for " + e.getMessage() + ",key = " + key + ", value = " + obj, e);
        }
        return res;
    }
    
    public boolean putWithoutAppName(String key, Object obj) {
        boolean res = false;
        try {
            memcachedClient.set(key, 0, obj);
            res = true;
        } catch (Throwable e) {
            LOG.error("PUT error for " + e.getMessage() + ",key = " + key + ", value = " + obj, e);
            init();
        }
        return res;
    }

    public boolean put(String key, Object obj, Date expireDate) {
        key = APP_NAME + "_" + key;
        boolean res = false;
        try {
            if (expireDate == null) {
                res = put(key, obj);
            } else {
                Long expireSeconds = DateUtil.calcDateBalance(DateUtil.getCurrentDate(), expireDate) / 1000;
                memcachedClient.set(key, expireSeconds.intValue(), obj);
                res = true;
            }
        } catch (Throwable e) {
            LOG.error("PUT error for " + e.getMessage() + ",key = " + key + ", value = " + obj, e);
        }
        return res;
    }

    public boolean put(String key, Object obj, Integer expireTime) {
        key = APP_NAME + "_" + key;
        boolean res = false;
        try {
            if (expireTime == null) {
                res = put(key, obj);
            } else {
                memcachedClient.set(key, expireTime, obj);
                res = true;
            }
        } catch (Throwable e) {
            LOG.error("PUT error for " + e.getMessage() + ",key = " + key + ", value = " + obj, e);
        }
        return res;
    }
    
}

6.memcached 攻击

如何控制memcached,攻击其他服务器

https://baijiahao.baidu.com/s?id=1594069046565606543&wfr=spider&for=pc


参考文档:

https://www.cnblogs.com/loveis715/p/4681643.html

https://www.cnblogs.com/yejg1212/p/3186179.html

https://www.2cto.com/database/201710/692324.html

http://www.runoob.com/memcached/memcached-set-data.html

https://blog.csdn.net/zmx729618/article/details/54613373 spring 整合

https://blog.csdn.net/xuke6677/article/details/38706501 三种方式

https://blog.csdn.net/u013425577/article/details/73730899  spymemcache java的demo 推荐

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值