一、Memcached概念

Memcached是NoSQL产品之中的一个,是一个暂时性键值存储NoSQL数据库,过去被大量使用在互联网站点中,作为应用和数据库之间的缓存层,大大提高查询和訪问速度。

Memcached有下面特点:

1、全内存运转:数据从来不保存在硬盘中。机器一重新启动,数据就所有没有了,所有又称暂时性数据库;

2、哈希方式存储:

3、简单文本协议进行数据通信:不须要特定二进制代码,仅仅须要用telnet连通memcached的监听port,打入简单浅显的代码就能操作;

4、仅仅操作字符型数据:不管往memcached放入什么。都是以字节的方式来处理。

还原成数组、哈希表、字符串和数值等都交给应用层来解释。应用读写memcached的数据时,进行序列化和反序列化。把其解释成应用所能理解的数据类型。

5、集群也由应用进行控制,採用一致性散列(哈希)算法。

二、安装Memcached

1、在linux上搭建yum环境

2、使用yum命令进行安装Memcached的rpm包

[root@nn init.d]# yum install memcached

3、启动Memcached,

首先要cd到对应文件夹

[root@nn ~]# cd /etc/rc.d/init.d/

执行memcached安装脚本

[root@nn init.d]# ./memcached start

4、查看Memcached是否启动

[root@nn init.d]# pstree

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzYxNTgwNQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

表示Memcached进程被启动了,以下开了5个线程

或者使用[root@nn init.d]# ps aux命令

memcached -d -p 11211 -u memcached -m 64 -c 1024 -P /var/run/memcached/memcached.pid

-d表示程序要后台化执行,-p指定port。-u表示用memcached这个身份来执行,后面的都是memcached的控制參数

5、连接Memcached

[root@nn init.d]# telnet localhost 11211

三、Memcached经常使用命令

命令格式:

<command name> <key> <flags> <exptime> <bytes>

<data block>

參数说明例如以下:

<command name>

set/add/replace

<key>

查找keyword

<flags>

不压缩,1压缩

<exptime>

表示永远

<bytes>

存储字节数

<data block>

存储的数据块(可直接理解为key-value结构中的value)

1、添加:set、add、cas

2、获取:get、gets、

3、追加:append、prepend

4、删除:delete

5、清除全部:flush_all

6、加减:incr、decr

7、退出:quit

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzYxNTgwNQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

三、用java连接Memcached

眼下java提供了三种API供我们实现与Memcached的连接和存取

1、memcached client for java

较早推出的memcached JAVAclientAPI,应用广泛,执行比較稳定。

2、pymemcached

A simple, asynchronous, single-threaded memcached client written in java. 支持异步。单线程的memcached客户端,用到了java1.5版本号的concurrent和nio,存取速度会高于前者,可是稳定性不好,測试中常报timeOut等相关异常。

3、xmemcached

XMemcached相同是基于java nio的client。java nio相比于传统堵塞io模型来说,有效率高(特别在高并发下)和资源耗费相对较少的长处。传统堵塞IO为了提高效率,须要创建一定数量的连接形成连接池。而nio仅须要一个连接就可以(当然,nio也是能够做池化处理),相对来说降低了线程创建和切换的开销,这一点在高并发下特别明显。因此XMemcached与Spymemcached在性能都很优秀,在某些方面(存储的数据比較小的情况下)Xmemcached比Spymemcached的表现更为优秀,详细能够看这个Java Memcached Clients Benchmark。

本文章使用memcached client for java为例

在使用java连接远程的PC机的Memcached时。记得保证两台机都开启telnet服务。而且本机能telnet通远程机,远程机必须关闭防火墙。

实例代码1:(java连接Memcached并实现数据的存取)

import com.danga.MemCached.MemCachedClient;

import com.danga.MemCached.SockIOPool;

public class memcachedTest {

public static void main(String[] args) {

//初始化SockIOPool,管理Memcached的连接池

String[] servers = {"192.183.3.230:11211"};

SockIOPool pool = SockIOPool.getInstance();

pool.setServers(servers);

pool.setFailover(true);

pool.setInitConn(10);

pool.setMinConn(5);

pool.setMaxConn(250);

pool.setMaintSleep(30);

pool.setNagle(false);

pool.setSocketTO(3000);

pool.setAliveCheck(true);

pool.initialize();

//建立MemcachedClient实例

MemCachedClient memCachedClient = new MemCachedClient();

for(int i = 0;i < 100000;i++){

//将对象增加到memcached缓存

boolean success = memCachedClient.set(""+i, "hello!");

}

for(int i = 0;i < 100000;i++){

//从memcached缓存中按key值取对象

String result = (String)memCachedClient.get(""+i);

System.out.println(String.format("get(%d):%s", i,result+i));

}

}

}

四、測试Memcached性能

为性能对照測试准备数据

1、插入数据到oracle

/**

* 插入測试数据到oracle数据库

* @param count插入记录数

* @return

*/

public static boolean insertIntoOracle(int count){

try {

con = dbConn("feng","feng");

if(con == null){

System.out.println("连接失败");

System.exit(0);

}

System.out.println("truncate table memcached_test......");

sql = "truncate table memcached_test";

pstmt = con.prepareStatement(sql);

rs = pstmt.executeQuery();

System.out.println("truncate table memcached_test finish.");

System.out.println("insert "+count+" values");

sql = "insert into memcached_test (memcachedId,memcachedvalues) values (?,?

)";

pstmt = con.prepareStatement(sql);

for(int i = 1;i <= count;i++){

pstmt.setInt(1, i);

pstmt.setString(2, "Memcached is a good thing.I like it very much !-----------"+i);

pstmt.executeUpdate();

}

System.out.println("insert "+count+" values finish.");

rs.close();

pstmt.close();

con.close();

} catch (ClassNotFoundException e) {

e.printStackTrace();

} catch (SQLException e) {

e.printStackTrace();

}

return true;

}

public static Connection dbConn(String name,String pass) throws ClassNotFoundException, SQLException{

Connection conn = null;

Class.forName("oracle.jdbc.driver.OracleDriver");

conn = DriverManager.getConnection("jdbc:oracle:thin:@192.183.3.230:1522:myorcl",name,pass);

return conn;

}

2、插入数据到Memcached

/**

* 插入測试数据到Memcached

* @param count插入记录数

* @return

*/

public static boolean insertIntoMemcached(int count){

//初始化SockIOPool。管理Memcached的连接池

String[] servers = {"192.183.3.230:11211"};

SockIOPool pool = SockIOPool.getInstance();

pool.setServers(servers);

pool.setFailover(true);

pool.setInitConn(10);

pool.setMinConn(5);

pool.setMaxConn(250);

pool.setMaintSleep(30);

pool.setNagle(false);

pool.setSocketTO(3000);

pool.setAliveCheck(true);

pool.initialize();

//建立MemcachedClient实例

MemCachedClient memCachedClient = new MemCachedClient();

System.out.println("insert "+count+" values into memcached......");

for(int i = 1;i < count;i++){

//将对象增加到memcached缓存

boolean success = memCachedClient.set("testData"+i, insertStr+i);

}

System.out.println("insert "+count+" values into memcached finish.");

return true;

}

Main函数调用这两个方法后,会将count条记录,值为insertData,插入到Oracle数据和set进Memcached中。

1、比較同一时候插入100000条数据的时间

从执行结果能够看出,插入10万条数据到Memcached比插10万条数据入Oracle所用时间有一个质的降低。

2、比較查询时间

下面是连接oracle数据并查找10000条数据的方法

/**

* oracle数据库查找

* @param count记录数

* @return

* @throws ParseException

*/

public static long searchOracle(int count) throws ParseException{

long useTime = 0;

try {

con = dbConn("feng","feng");

if(con == null){

System.out.println("连接失败");

System.exit(0);

}

StringBuffer sql =new StringBuffer("select memcachedid,memcachedvalues from memcached_test where memcachedid = ?");

pstmt = con.prepareStatement(sql.toString());

String memcachedvalues = "";

System.out.println("search table memcached_test......");

String beginTime = d.format(new Date());

for(int i = 1;i <= count;i++){

if(i%10 == 0){

pstmt.setInt(1, i);

rs = pstmt.executeQuery();

while(rs.next()){

memcachedvalues = rs.getString(2);

}

}

}

System.out.println("search table memcached_test finish.");

String endTime = d.format(new Date());

useTime = d.parse(endTime).getTime() - d.parse(beginTime).getTime();

long ss = (useTime/1000)%60;//秒

long MM = useTime/60000;//分

System.out.println("Oracle中查找10000条记录的開始时间:"+beginTime);

System.out.println("Oracle中查找10000条记录的结束时间:"+endTime);

System.out.println("Oracle中查找10000条记录的所用时间:  "+MM+"分"+ss+"秒");

rs.close();

pstmt.close();

con.close();

} catch (ClassNotFoundException e) {

e.printStackTrace();

} catch (SQLException e) {

e.printStackTrace();

}

return useTime;

}

下面是连接Memcached并查找10000条数据的方法

/**

* Memcached查找

* @param count

* @return

* @throws ParseException

*/

public static long searchMemcached(int count) throws ParseException{

//初始化SockIOPool。管理Memcached的连接池

String[] servers = {"192.183.3.230:11211"};

SockIOPool pool = SockIOPool.getInstance();

pool.setServers(servers);

pool.setFailover(true);

pool.setInitConn(10);

pool.setMinConn(5);

pool.setMaxConn(250);

pool.setMaintSleep(30);

pool.setNagle(false);

pool.setSocketTO(3000);

pool.setAliveCheck(true);

pool.initialize();

//建立MemcachedClient实例

MemCachedClient memCachedClient = new MemCachedClient();

System.out.println("search 10000 data in Memcached......");

String memcachedvalues = "";

String beginTime = d.format(new Date());

for(int i = 1;i <= count;i++){

//从memcached缓存中按key值取对象

if(i%10 == 0){

memcachedvalues = (String)memCachedClient.get("testData"+i);

}

}

System.out.println("search 10000 data in Memcached finish.");

String endTime = d.format(new Date());

long useTime = d.parse(endTime).getTime() - d.parse(beginTime).getTime();

long ss = (useTime/1000)%60;//秒

long MM = useTime/60000;//分

System.out.println("从Memcached查找10000条记录的開始时间:"+beginTime);

System.out.println("从Memcached查找10000条记录的结束时间:"+endTime);

System.out.println("从Memcached查找10000条记录的所用时间:  "+MM+"分"+ss+"秒");

return useTime;

}

执行结果例如以下:

从执行结果能够看出,同一时候查找10000条数据,Memcached所用时间比1Oracle所用时间降低了29秒。

四、启动多个节点的Memcached

因为实验器材有限,如今在同一台pc机中启动多个Memcached,仅仅要设定port不一样,这些Memcached之间互相不会干扰。

启动命令例如以下:

[root@nn init.d]# memcached -d -p 11212 -u memcached -m 64 -c 1024

[root@nn init.d]# memcached -d -p 11213 -u memcached -m 64 -c 1024

当中-d表示在后台执行,-p表示port号,-u表示用户

启动之后用pstree查看

[root@nn init.d]# pstree

3*[memcached───5*[{memcached}]]表示有3组Memcached的进程。

或者用ps aux命令

[root@nn init.d]# ps aux

往多节点的Memcached中插入数据的java代码

/**

* 往节点Memcached插入数据

* @param count

*/

public static void testManyNode(int count){

//初始化SockIOPool,管理Memcached的连接池

String[] servers = {"192.183.3.230:11211","192.183.3.230:11212","192.183.3.230:11213"};

SockIOPool pool = SockIOPool.getInstance();

pool.setServers(servers);

pool.setFailover(true);

pool.setInitConn(10);

pool.setMinConn(5);

pool.setMaxConn(250);

pool.setMaintSleep(30);

pool.setNagle(false);

pool.setSocketTO(3000);

pool.setAliveCheck(true);

pool.initialize();

//建立MemcachedClient实例

MemCachedClient memCachedClient = new MemCachedClient();

String beginTime = d.format(new Date());

for(int i = 1;i <= count;i++){

//将对象增加到memcached缓存

boolean success = memCachedClient.set("node"+i, insertStr+i);

}

}

Memcached的查询结果:

从结果中能够看出,数据分布到Memcached的不同节点上。

五、高可用方案repcached

假如Memcached中有一个节点失效了,这个节点所管辖的数据都没有,我们必须又一次去数据库中获取数据放入新的节点中。这样会引发数据库性能的波动。这里就须要我们做一个高可用的Memcached,使得Memcached中的每个节点都有另外一个节点与之中的一个一相应。这两个一一相应的节点中的数据是一模一样的。这样当当中一个节点失效了,另外一个节点就能立即接管缓存的工作,这样就不须要又一次从数据库中获取数据库。

以下我们使用repcached来实现Memcached的高可用

1、下载repcached

[root@nn ~]# wget http://downloads.sourceforge.net/repcached/memcached-1.2.8-repcached-2.2.tar.gz

2、杀死本机上的全部Memcached

[root@nn ~]# killall memcached

3、解压下载的repcached

[root@nn ~]# tar zxvf memcached-1.2.8-repcached-2.2.tar.gz

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzYxNTgwNQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

4、进入所解压的文件夹

[root@nn ~]# cd memcached-1.2.8-repcached-2.2

5、安装依赖包,执行编译repcached所须要的

[root@nn memcached-1.2.8-repcached-2.2]# yum install libevent-devel

6、開始安装repcached

[root@nn memcached-1.2.8-repcached-2.2]# ./config --enable-replication --program-transform-name=s/memcached/repcached/

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzYxNTgwNQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

安装好之后就会产生一个Makefile文件

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzYxNTgwNQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

7、能够使用Makefile来编译

[root@nn memcached-1.2.8-repcached-2.2]# make

[root@nn memcached-1.2.8-repcached-2.2]# make install

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzYxNTgwNQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

能够看到主要安装的程序有repcached和repcached-debug

8、启动Memcached的高可用集群(注意不能用root用户来启动)

[oracle@nn ~]$ /usr/local/bin/repcached -p 11211 -v -d

[oracle@nn ~]$ /usr/local/bin/repcached -p 11212 -x localhost -v -d

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzYxNTgwNQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

当中-x表示要监听高可用机器,假设是其它port要写上“:port号”,假设是默认port(11211)。就不须要写。

9、測试:从11211port插入数据,到11212port去查找;从11212port插入数据,到11211port去查找

从測试结果能够看出。这个高可用复制是双向的。不管在哪一个节点插入数据,都能够在另外一个节点中查到。

六、Memcached的一致性

假设有两个不同终端连接同一Memcached服务,对同一key值进行改动,结果会怎样呢?

以下来做实验

1、A终端连接Memcached并set入key为counter的一个值1

用gets命令看出。比用get命令多最后一个数字,这个数字表示这个key的版本

2、B终端连接Memcached并set入key为counter的一个值2

3、用set命令去改会改变一致性,这里改用cas命令

我们用gets查看当前的版本是3

用cas最后一个參数表示版本,假设版本不一样。不能改动。会有EXISTS提示。表示改动失败;假设版本一致,就能改动成功。

Memcached的缺点

1、纯内存操作的数据库。关机或者关闭Memcached进程后数据所有丢失;

2、保存字节数,数据类型贫乏,其它数据类型都要通过应用程序来解释,这样应用端要做的事情会非常多,server端要做的事情就非常好非常好了;

3、兼容性差。不同编程语言之间不能相互调用;

4、LRU算法导致数据不可控的丢失。

5、一致性处理简单。

6、应用场景有限,难以被看成是完整的数据库产品,只用来做数据库和应用之间的缓存层。

NoSQL之Memcached的更多相关文章

  1. NoSQL、memcached介绍、安装memcached、查看memcached状态

    1.NoSQL 2.memcached介绍     3.安装memcached(二进制包安装) yum install -y memcached libmemcached libevent (若没有安 ...

  2. 三、NOSQL之Memcached缓存服务实战精讲第二部

    1.Memcached服务安装 Memcached的安装比较简单,很多平台都是支持Memcached,常见的有:Linux .Windows 服务端端:                cd /home ...

  3. 二、NOSQL之Memcached缓存服务实战精讲第一部

    1.Memcached是一套数据缓存系统或软件. 用于在动态应用系统中缓存数据库的数据,减少数据库的访问压力,达到提升网站系统性能的目的:Memcached在企业应用场景中一般是用来作为数据库的cac ...

  4. Memcached的安装(Linux)、操作、命令

    最近在整理有关分布式缓存的服务器,做了一下老牌nosql服务器memcached的学习总结.文中所述的所有安装均是在联网的情况下进行的. 序: 什么是memcached: Free & ope ...

  5. memcached 缓存数据库应用实践

    1.1 数据库对比 缓存: 将数据存储到内存中,只有当磁盘胜任不了的时候,才会启用缓存   缺点:断电数据丢失(双电),用缓存存储数据的目的只是为了应付大并发的业务. 数据库: mysql(关系型数据 ...

  6. Python学习笔记 - day12 - Python操作NoSQL

    NoSQL(非关系型数据库) NoSQL,指的是非关系型的数据库.NoSQL有时也称作Not Only SQL的缩写,是对不同于传统的关系型数据库的数据库管理系统的统称.用于超大规模数据的存储.(例如 ...

  7. NoSQL和SQL怎么选用?

    NoSQL 有分很多种,其中key-value NoSQL (Redis, MemcacheD, etc) 的选用相对比较清楚些,大多是当后端Data storage的cache层来用.这篇主要想请教 ...

  8. 高级php面试题(转)

    一.mysql相关知识    1. mysql优化方式            MYSQL 优化常用方法            mysql 性能优化方案      2.如何分库分表            ...

  9. 高级php面试题

    在网上看到一些高级php 的面试题目.. 最近接连面试了几家公司,有些重要问题记录一下,督促自己学习提高,同时希望给朋友们一些帮助.内容很多,一点点完善,一步步学习..有些是面试被问,有些是招聘要求, ...

随机推荐

  1. Python3简明教程(六)—— 数据结构

    简单的来说,数据结构(data structure)是计算机中存储.组织数据的方式.比如我们之前使用过的列表就是一种数据结构,在这里我们还会深入学习它.之前也有简单的介绍. 列表 >>&g ...

  2. hard fault 学习记录

    使用 segger 的 hard fault 的源文件后,当调试时,发生硬件错误的时候,可以查看 HardFaultRegs 中的内容,并对比 segger_HardFaultHandler.c 中的 ...

  3. Deep_into_iris

    具体ipynb文件请移步Github #各种所需要的库函数首先加载 import numpy as np import pandas as pd import matplotlib.pyplot as ...

  4. 关于C/C++的一些思考(5)

    运算符重载函数的限制: 五个不能实现重载的符号:".", ".*", "::", "?", "sizeof&q ...

  5. centos7 中源码安装nginx

    使用nginx有一段时间了,还是有很多东西不懂的,在这里做一下自己学习过程中的一些整理,能使自己得到提升. 1.环境:centos7 1511  最小化安装 2.下载nginx,可以在系统中下载,也可 ...

  6. (4) openssl rsa/pkey(查看私钥、从私钥中提取公钥、查看公钥)

    openssl  rsa      是RSA对称密钥的处理工具 openssl  pkey   是通用非对称密钥处理工具,它们用法基本一致,所以只举例说明openssl rsa. 它们的用法很简单,基 ...

  7. STM32——输入捕获实验原理及配置步骤

    输入捕获实验原理及配置步骤 一.输入捕获概念 STM32的输入捕获,简单的说就是通过检测 TIMx_CHx (定时器X的通道X)上的 边沿信号,在边沿信号发生跳变(比如上升沿/下降沿)的时候,将当前定 ...

  8. Java学习之接口概念

    Java语言只支持单重继承,不支持多继承,即一个类只能有一个父类.但是在实际应用中,又经常需要使用多继承来解决问题.为了解决该问题,Java语言提供接口来实现类的多继承问题. 接口(英文interfa ...

  9. Ext.js双击事件

    /** * 联系人列表panel */ Ext.define('Op.OpBill.OpBillCustLinkGridPanel', { extend: 'Ext.grid.Panel', id: ...

  10. mybatis插件 mybatis插件-------从dao快速定位到mapper的sql语句

    步骤一:打开settings,点击plugins 快捷键ctrl+alt+s打开settings 步骤二.点击ClearCase Integration,并点击下面中间的按钮(browse repos ...