memcache的java客户端com.danga.MemCached.MemCachedClient的实现过程
其实很简单,就是一个socket通信过程
最后附上一个山寨版本的MemCachedClient
SockIOPool负责管理socket的pools
SockIO是SockIOPool的一个内部类,功能相当于Socket,可以读写数据
MaintThread是SockIOPool内部类,负责pool的runing和stop
MemCachedClient客户端调用类,拥有各种memcached的操作
NIOLoader是MemCachedClient的内部类,负责各种批量操作
以下是其实现中的一些罗列点
1.SockIOPool.getInstance()是取得名为default的pool
2.简单的一个创建SockIOPool 初始化pool
String[] serverlist = { "cache0.server.com:12345", "cache1.server.com:12345" };
SockIOPool pool = SockIOPool.getInstance();
pool.setServers(serverlist);
pool.initialize();
3.MemCachedClient mcc = new MemCachedClient();就可以使用mcc了
4.get时的socket,向memcache服务器发送socket请求
String cmd = "get " + key + "\r\n";
sock.write( cmd.getBytes() );
sock.flush();
5.getMulti时,按不同的host,组装成get key1 key2,再向服务端发送socket请求
if ( !cmdMap.containsKey( sock.getHost() ) )
{
cmdMap.put( sock.getHost(), new StringBuilder( "get" ) );
}
cmdMap.get( sock.getHost() ).append( " " + cleanKey );
6.NATIVE_HASH模式下取得server(另外它还支持OLD_COMPAT_HASH ,NEW_COMPAT_HASH ,CONSISTENT_HASH)
(long)key.hashCode()再取模
7.初始化socket
SocketChannel sock = SocketChannel.open();
sock.socket().connect( new InetSocketAddress( host, port ), timeout );
return sock.socket();
8.省略N点
下面是一个山寨的MemCachedClient的实现
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 简单的MemcachedClient
*
* @author gaoliang
* @date 2011-3-11
*/
public class MemcachedClient {
public static void main(String[] args) {
MemcachedClient client = new MemcachedClient(new String[] {
"127.0.0.1:11211", "127.0.0.1:12000" });
client.add("aa", "aa");
System.out.println(client.get("aa"));
client.set("aa", "bb");
System.out.println(client.get("aa"));
client.replace("aa", "cc");
System.out.println(client.get("aa"));
client.delete("aa");
System.out.println(client.get("aa"));
}
private Map<String, Socket> socketMap = new HashMap<String, Socket>();
private List<String> hosts = new ArrayList<String>();
private int num = 0; // 服务器数量
public MemcachedClient(String[] servers) {
init(servers);// 初始化并创建socket连接
}
public boolean add(String key, Object obj) {
return Boolean.valueOf(write("add", key, obj, null));
}
public boolean add(String key, Object obj, Date date) {
return Boolean.valueOf(write("add", key, obj, date));
}
public Object get(String key) {
return write("get", key, null, null);
}
public boolean delete(String key) {
return Boolean.valueOf(write("delete", key, null, null));
}
public boolean replace(String key, Object obj) {
return Boolean.valueOf(write("replace", key, obj, null));
}
public boolean set(String key, Object obj) {
return Boolean.valueOf(write("set", key, obj, null));
}
public Map<String,Object> getMulti(String[] keys){
//省略100字
//拼接get a b c
//对返回的value做判断
return null;
}
// 初始化并创建socket连接
private void init(String[] servers) {
try {
for (String server : servers) {
if (server.contains(":")) {
String[] strs = server.split(":");
socketMap.put(strs[0], new Socket(strs[0], Integer
.valueOf(strs[1])));
hosts.add(strs[0]);
num++;
}
}
} catch (Exception e) {
System.out.println("init error");
}
}
// 按hash取server的socket连接
private Socket getSocket(String key) {
int t = key.hashCode() % num;
return socketMap.get(hosts.get(t));
}
// 向server发送命令,并返回结果
private String write(String cmd, String key, Object obj, Date date) {
byte[] value = null;
if (obj != null) {
value = obj.toString().getBytes();
}
//命令字符串
String cmdStr = "";
if ("add".equals(cmd) || "set".equals(cmd) || "replace".equals(cmd)) {
cmdStr = String.format("%s %s %d %d %d\r\n", cmd, key, 32,
date != null ? date.getTime() / 1000 : 0, value.length);
}
if ("get".equals(cmd)) {
cmdStr = String.format("%s %s\r\n", cmd, key);
}
if ("delete".equals(cmd)) {
cmdStr = String.format("%s %s\r\n", cmd, key);
}
Socket socket = getSocket(key);
return getResponse(cmd, obj, cmdStr, socket);
}
//从数据器读取数据
private String getResponse(String cmd, Object obj, String cmdStr,
Socket socket) {
try {
BufferedOutputStream out = new BufferedOutputStream(socket
.getOutputStream());
DataInputStream in = new DataInputStream(socket.getInputStream());
out.write(cmdStr.getBytes());
if (obj != null) {
out.write(obj.toString().getBytes());
out.write("\r\n".getBytes());
}
out.flush();
String response = readLine(in);
if (("add".equals(cmd) || "set".equals(cmd) || "replace"
.equals(cmd))
&& "STORED".equals(response)) {
return "TRUE";
}
if (("get".equals(cmd))) {
if (response.contains("VALUE")) {
String str = readLine(in);
readLine(in);
return str;
} else {
return null;
}
}
if (("delete".equals(cmd)) && "DELETED".equals(response)) {
return "TRUE";
}
} catch (Exception e) {
System.out.println("write error");
return "FALSE";
}
return "FALSE";
}
public String readLine(DataInputStream in) throws IOException {
byte[] b = new byte[1];
ByteArrayOutputStream bos = new ByteArrayOutputStream();
boolean eol = false;
while (in.read(b, 0, 1) != -1) {
if (b[0] == 13) {
eol = true;
} else {
if (eol) {
if (b[0] == 10)
break;
eol = false;
}
}
bos.write(b, 0, 1);
}
return bos.toString().trim();
}
}