一、关于Memcached
1.1 Memcached的介绍
MemCache是一个自由、源码开放、高性能、分布式的内存对象缓存系统,用于动态Web应用以减轻数据库的负载。它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高了网站访问的速度。
MemCache是一个存储键值对的HashMap,在内存中对任意的 数据(比如字符串、对象等)所使用的key-value存储,数据可以来自数据库调用、API调用,或者页面渲染的结果,
1.2 Memcached的工作原理
由于它的工作机制是在 内存中开辟一块空间,然后建立一个HashTable,Memcached管理这些HashTable,所以速度非常快。
1.3 Memcached的作用
使用MemCache的网站一般流量都是比较大的,为了缓解数据库的压力,让MemCache作为一个缓存区域,把部分信息保存在内存中,在前端能够迅速的进行存取。那么一般的焦点就是集中在如何分担数据库压力和进行分布式,毕竟单台MemCache的内存容量是有限的。
二、Memcached服务端的安装(重点)
Memcached的安装
分为两个过程:
memcache服务器端的安装和memcache客户端的安装。
所谓服务器端的安装就是在服务器(一般都是Linux系统)上安装MemCache实现数据的存储。
所谓客户端的安装就是指Java(或者其他程序,memcache还有其他不错的api接口提供)去使用服务器端的memcache提供的函数,需要Java添加扩展。
2.1 Windows安装memcached(服务器端)
官网:下载地址
# 如果之前有MemCache的安装,删除它,启动cmd
sc delete "Memcached Server"
# 获取安装包、以管理员方式启动cmd、并进入安装包目录下:
d:
cd Java\memcache
# 安装MemCache
memcache.exe -d install
# 启动MemCache
memcache.exe -d start
#设置 memcached 最大的缓存配置为512M。
memcache.exe -d runservice -m 512
# 关闭MemCache
memcache.exe -d stop
# 卸载MemCache
memcache.exe -d uninstall
安装成功之后再Windows服务项目中查看是否有启动
测试安装是否成功
在MemCache服务成功启动后,可以使用telnet 127.0.0.1 11211测试连接是否成功;
如果连接成功后则使用stats命令可以查看MemCache的基本信息
(1)什么是Telnet
对于telnet的人事,不同的人持有不同的观点,可以吧telnet当成一种通信协议,但是对于入侵者而言,telnet只是一种远程登录的工具。一旦入侵者与远程主机建立了telnet连接,入侵者便可以使用目标主机上的软、硬件资源,而入侵者的本地机只相当于一个只有键盘和显示器的终端而已
(2)开启telnet功能
打开控制面板——>程序和功能——>启动或者关闭Windows功能——>开启telnet客户端
(3)telnet命令的使用
然后输入命令:
stats 查看memcache服务器的状态
2.2 Linux安装memcached(服务器端)
- 获取memcached的安装包:
官网:下载地址 - 上传文件到Linux根目录software目录下
- 解压安装包
# 基本依赖
mount /dev/cdrom /media/CentOS
yum --disablerepo=\* --enablerepo=c6-media install gcc gcc-c++
# 安装libevent
tar zxvf libevent-2.0.21-stable.tar.gz
cd libevent-2.0.21-stable
./configure --prefix=/usr/local/libevent
make && make install
# 安装memcached
tar zxvf memcached-1.4.27.tar.gz
cd memcached-1.4.27
./configure --prefix=/usr/local/memcached --with-libevent=/usr/local/libevent
make && make install
# 创建一个用户:
useradd memcache
passed memcache
# 从root用户切换到memcached用户:
su - memcache
# 启动memcache服务:
cd /usr/local/memcache
./bin/memcache & #后台启动服务器端memcached
# 查看memcached的服务器端是否启动 7413端口
ps -e |grep memcache
2.3 telnet请求命令格式(Windows下)
<command name> <key> <flags> <exptime> <bytes>\r\n <data block>\r\n
a)<command name>可以是"set","add","replace"。
"set" 表示按照相应的<key>存储该数据,没有的时候增加,有的覆盖。
"add" 表示按照相应的<key>添加该数据,但是如果该<key>已经存在则会操作失败。
"replace" 表示按照相应的<key>替换数据,但是如果该<key>不存在则操作失败。
b)<key>客户端需要保存数据的key username
set username 0 30 5
c)<flags>是一个16位的无符号的整数(以十进制的方式表示)。
该标志将和需要存储的数据一起存储,并在客户端get数据时返回。
客户可以将此标志用做特殊用途,此标志对服务器来说是不透明的。
一般的状态:0(字符串)和1(对象和数组)
d)<exptime>过期的时间。
若为0表示存储的数据永远不过时(但可被服务器算法LRU等替换)。
如果非0(Unix时间或者距离此时的秒数),当过期后,
服务器可以保证用户得不到该数据(以服务器时间为标准)。
e)<block>需要存储的字节数(不包含最后的"\r\n")。
当用户希望存储空数据时,<block>可以为0
f)最后客户端需要加上"\r\n"作为“命令头”的结束标志。
<data block>\r\n:输入的数据
紧接着“命令头”结束之后就要发送数据块(即希望存储的数据内容),
最后加上"\r\n"作为此次通讯的结束。
具体事例1:
打开cmd:
telnet 127.0.0.1 11211
# 设置一个键名:newname;0:字符串;30:过期时间;5:数据的长度
set newname 0 30 5
# 输入数据
peter
# 获取键名的值
get newname
# 返回的数据
peter
# 30秒后、得不到数据
get newname
2.4 memcached在Linux中的操作
XShell支持telnet(远程登录协议),连接MemCached服务器端进行操作。
使用telnet协议的客户端,即可充当memcached的客户端:
XShell可以发出ssh请求,同样也可以telnet请求
三、Java 连接 Memcached 服务
使用 Java 程序连接 Memcached,需要在你的 classpath 中添加 Memcached jar 包。
Google Code jar
包下载地址:spymemcached-2.10.3.jar以下程序假定 Memcached 服务的主机为 127.0.0.1,端口为 11211。
连接实例
Java 连接 Memcached
MemcachedJava.java 文件:
import net.spy.memcached.MemcachedClient;
import java.net.*;
public class MemcachedJava {
public static void main(String[] args) {
try{
// 本地连接 Memcached 服务
MemcachedClient mcc = new MemcachedClient(new InetSocketAddress("127.0.0.1", 11211));
System.out.println("Connection to server sucessful.");
// 关闭连接
mcc.shutdown();
}catch(Exception ex){
System.out.println( ex.getMessage() );
}
}
}
该程序中我们使用 InetSocketAddress 连接 IP 为 127.0.0.1 端口 为 11211 的 memcached 服务。
执行以上代码,如果连接成功会输出以下信息:
Connection to server successful.
set 操作实例
以下使用 java.util.concurrent.Future 来存储数据
MemcachedJava.java 文件:
import java.net.InetSocketAddress;
import java.util.concurrent.Future;
import net.spy.memcached.MemcachedClient;
public class MemcachedJava {
public static void main(String[] args) {
try{
// 连接本地的 Memcached 服务
MemcachedClient mcc = new MemcachedClient(new InetSocketAddress("127.0.0.1", 11211));
System.out.println("Connection to server sucessful.");
// 存储数据
Future fo = mcc.set("runoob", 900, "Free Education");
// 查看存储状态
System.out.println("set status:" + fo.get());
// 输出值
System.out.println("runoob value in cache - " + mcc.get("runoob"));
// 关闭连接
mcc.shutdown();
}catch(Exception ex){
System.out.println( ex.getMessage() );
}
}
}
执行程序,输出结果为:
Connection to server successful.
set status:true
runoob value in cache - Free Education
add 操作实例
MemcachedJava.java 文件:
import java.net.InetSocketAddress;
import java.util.concurrent.Future;
import net.spy.memcached.MemcachedClient;
public class MemcachedJava {
public static void main(String[] args) {
try{
// 连接本地的 Memcached 服务
MemcachedClient mcc = new MemcachedClient(new InetSocketAddress("127.0.0.1", 11211));
System.out.println("Connection to server sucessful.");
// 添加数据
Future fo = mcc.set("runoob", 900, "Free Education");
// 打印状态
System.out.println("set status:" + fo.get());
// 输出
System.out.println("runoob value in cache - " + mcc.get("runoob"));
// 添加
fo = mcc.add("runoob", 900, "memcached");
// 打印状态
System.out.println("add status:" + fo.get());
// 添加新key
fo = mcc.add("codingground", 900, "All Free Compilers");
// 打印状态
System.out.println("add status:" + fo.get());
// 输出
System.out.println("codingground value in cache - " + mcc.get("codingground"));
// 关闭连接
mcc.shutdown();
}catch(Exception ex){
System.out.println(ex.getMessage());
}
}
}
replace 操作实例
MemcachedJava.java 文件:
import java.net.InetSocketAddress;
import java.util.concurrent.Future;
import net.spy.memcached.MemcachedClient;
public class MemcachedJava {
public static void main(String[] args) {
try {
//连接本地的 Memcached 服务
MemcachedClient mcc = new MemcachedClient(new InetSocketAddress("127.0.0.1", 11211));
System.out.println("Connection to server sucessful.");
// 添加第一个 key=》value 对
Future fo = mcc.set("runoob", 900, "Free Education");
// 输出执行 add 方法后的状态
System.out.println("add status:" + fo.get());
// 获取键对应的值
System.out.println("runoob value in cache - " + mcc.get("runoob"));
// 添加新的 key
fo = mcc.replace("runoob", 900, "Largest Tutorials' Library");
// 输出执行 set 方法后的状态
System.out.println("replace status:" + fo.get());
// 获取键对应的值
System.out.println("runoob value in cache - " + mcc.get("runoob"));
// 关闭连接
mcc.shutdown();
}catch(Exception ex){
System.out.println( ex.getMessage() );
}
}
}
append 操作实例
MemcachedJava.java 文件:
import java.net.InetSocketAddress;
import java.util.concurrent.Future;
import net.spy.memcached.MemcachedClient;
public class MemcachedJava {
public static void main(String[] args) {
try{
// 连接本地的 Memcached 服务
MemcachedClient mcc = new MemcachedClient(new InetSocketAddress("127.0.0.1", 11211));
System.out.println("Connection to server sucessful.");
// 添加数据
Future fo = mcc.set("runoob", 900, "Free Education");
// 输出执行 set 方法后的状态
System.out.println("set status:" + fo.get());
// 获取键对应的值
System.out.println("runoob value in cache - " + mcc.get("runoob"));
// 对存在的key进行数据添加操作
fo = mcc.append("runoob", 900, " for All");
// 输出执行 set 方法后的状态
System.out.println("append status:" + fo.get());
// 获取键对应的值
System.out.println("runoob value in cache - " + mcc.get("codingground"));
// 关闭连接
mcc.shutdown();
}catch(Exception ex) {
System.out.println(ex.getMessage());
]
}
}
prepend 操作实例
MemcachedJava.java 文件:
import java.net.InetSocketAddress;
import java.util.concurrent.Future;
import net.spy.memcached.MemcachedClient;
public class MemcachedJava {
public static void main(String[] args) {
try{
// 连接本地的 Memcached 服务
MemcachedClient mcc = new MemcachedClient(new InetSocketAddress("127.0.0.1", 11211));
System.out.println("Connection to server sucessful.");
// 添加数据
Future fo = mcc.set("runoob", 900, "Education for All");
// 输出执行 set 方法后的状态
System.out.println("set status:" + fo.get());
// 获取键对应的值
System.out.println("runoob value in cache - " + mcc.get("runoob"));
// 对存在的key进行数据添加操作
fo = mcc.prepend("runoob", 900, "Free ");
// 输出执行 set 方法后的状态
System.out.println("prepend status:" + fo.get());
// 获取键对应的值
System.out.println("runoob value in cache - " + mcc.get("codingground"));
// 关闭连接
mcc.shutdown();
}catch(Exception ex) {
System.out.println(ex.getMessage());
}
}
}
CAS 操作实例
MemcachedJava.java 文件:
import java.net.InetSocketAddress;
import java.util.concurrent.Future;
import net.spy.memcached.CASValue;
import net.spy.memcached.CASResponse;
import net.spy.memcached.MemcachedClient;
public class MemcachedJava {
public static void main(String[] args) {
try{
// 连接本地的 Memcached 服务
MemcachedClient mcc = new MemcachedClient(new InetSocketAddress("127.0.0.1", 11211));
System.out.println("Connection to server sucessful.");
// 添加数据
Future fo = mcc.set("runoob", 900, "Free Education");
// 输出执行 set 方法后的状态
System.out.println("set status:" + fo.get());
// 使用 get 方法获取数据
System.out.println("runoob value in cache - " + mcc.get("runoob"));
// 通过 gets 方法获取 CAS token(令牌)
CASValue casValue = mcc.gets("runoob");
// 输出 CAS token(令牌) 值
System.out.println("CAS token - " + casValue);
// 尝试使用cas方法来更新数据
CASResponse casresp = mcc.cas("runoob", casValue.getCas(), 900, "Largest Tutorials-Library");
// 输出 CAS 响应信息
System.out.println("CAS Response - " + casresp);
// 输出值
System.out.println("runoob value in cache - " + mcc.get("runoob"));
// 关闭连接
mcc.shutdown();
}catch(Exception ex) {
System.out.println(ex.getMessage());
}
}
}
get 操作实例
MemcachedJava.java 文件:
import java.net.InetSocketAddress;
import java.util.concurrent.Future;
import net.spy.memcached.MemcachedClient;
public class MemcachedJava {
public static void main(String[] args) {
try{
// 连接本地的 Memcached 服务
MemcachedClient mcc = new MemcachedClient(new InetSocketAddress("127.0.0.1", 11211));
System.out.println("Connection to server sucessful.");
// 添加数据
Future fo = mcc.set("runoob", 900, "Free Education");
// 输出执行 set 方法后的状态
System.out.println("set status:" + fo.get());
// 使用 get 方法获取数据
System.out.println("runoob value in cache - " + mcc.get("runoob"));
// 关闭连接
mcc.shutdown();
}catch(Exception ex) {
System.out.println(ex.getMessage());
}
}
}
gets 操作实例、CAS
MemcachedJava.java 文件:
import java.net.InetSocketAddress;
import java.util.concurrent.Future;
import net.spy.memcached.CASValue;
import net.spy.memcached.CASResponse;
import net.spy.memcached.MemcachedClient;
public class MemcachedJava {
public static void main(String[] args) {
try{
// 连接本地的 Memcached 服务
MemcachedClient mcc = new MemcachedClient(new InetSocketAddress("127.0.0.1", 11211));
System.out.println("Connection to server sucessful.");
// 添加数据
Future fo = mcc.set("runoob", 900, "Free Education");
// 输出执行 set 方法后的状态
System.out.println("set status:" + fo.get());
// 从缓存中获取键为 runoob 的值
System.out.println("runoob value in cache - " + mcc.get("runoob"));
// 通过 gets 方法获取 CAS token(令牌)
CASValue casValue = mcc.gets("runoob");
// 输出 CAS token(令牌) 值
System.out.println("CAS value in cache - " + casValue);
// 关闭连接
mcc.shutdown();
}catch(Exception ex) {
System.out.println(ex.getMessage());
}
}
}
delete 操作实例
MemcachedJava.java 文件:
import java.net.InetSocketAddress;
import java.util.concurrent.Future;
import net.spy.memcached.MemcachedClient;
public class MemcachedJava {
public static void main(String[] args) {
try{
// 连接本地的 Memcached 服务
MemcachedClient mcc = new MemcachedClient(new InetSocketAddress("127.0.0.1", 11211));
System.out.println("Connection to server sucessful.");
// 添加数据
Future fo = mcc.set("runoob", 900, "World's largest online tutorials library");
// 输出执行 set 方法后的状态
System.out.println("set status:" + fo.get());
// 获取键对应的值
System.out.println("runoob value in cache - " + mcc.get("runoob"));
// 对存在的key进行数据添加操作
fo = mcc.delete("runoob");
// 输出执行 delete 方法后的状态
System.out.println("delete status:" + fo.get());
// 获取键对应的值
System.out.println("runoob value in cache - " + mcc.get("codingground"));
// 关闭连接
mcc.shutdown();
}catch(Exception ex) {
System.out.println(ex.getMessage());
}
}
}
Incr/Decr 操作实例
MemcachedJava.java 文件:
import java.net.InetSocketAddress;
import java.util.concurrent.Future;
import net.spy.memcached.MemcachedClient;
public class MemcachedJava {
public static void main(String[] args) {
try{
// 连接本地的 Memcached 服务
MemcachedClient mcc = new MemcachedClient(new InetSocketAddress("127.0.0.1", 11211));
System.out.println("Connection to server sucessful.");
// 添加数字值
Future fo = mcc.set("number", 900, "1000");
// 输出执行 set 方法后的状态
System.out.println("set status:" + fo.get());
// 获取键对应的值
System.out.println("value in cache - " + mcc.get("number"));
// 自增并输出
System.out.println("value in cache after increment - " + mcc.incr("number", 111));
// 自减并输出
System.out.println("value in cache after decrement - " + mcc.decr("number", 112));
// 关闭连接
mcc.shutdown();
}catch(Exception ex) {
System.out.println(ex.getMessage());
}
}
}