Memcached 简介及C++,Java客户端例程

       本文对memcached进行简单的介绍,后面附上C++和Java客户端的简单例程,作为memcached入门的一些介绍。

一、memcached启动:

# /usr/local/bin/memcached -d -m 10 -u root -l 192.168.141.64 -p 12000 -c 256 -P /tmp/memcached.pid

-d选项是启动一个守护进程,
-m是分配给Memcache使用的内存数量,单位是MB,我这里是100MB,
-u是运行Memcache的用户,我这里是root,
-l是监听的服务器IP地址,如果有多个地址的话,我这里指定了服务器的IP地址192.168.0.200,
-p是设置Memcache监听的端口,我这里设置了12000,最好是1024以上的端口,
-c选项是最大运行的并发连接数,默认是1024,我这里设置了256,按照你服务器的负载量来设定,
-P是设置保存Memcache的pid文件,我这里是保存在 /tmp/memcached.pid,


二、适用场合
1.分布式应用。由于memcached本身基于分布式的系统,所以尤其适合大型的分布式系统。
2.数据库前段缓存。数据库常常是网站系统的瓶颈。数据库的大并发量访问,常常造成网站内存溢出。当然我们也可以使用Hibernate的缓存机制。但memcached是基于分布式的,并可独立于网站应用本身,所以更适合大型网站进行应用的拆分。
3.服务器间数据共享。举例来讲,我们将网站的登录系统、查询系统拆分为两个应用,放在不同的服务器上,并进行集群,那这个时候用户登录后,登录信息如何从登录系统服务器同步到查询系统服务器呢?这时候,我们便可以使用memcached,登录系统将登录信息缓存起来,查询系统便可以获得登录信息,就像获取本地信息一样。

三、不适用场合
那些不需要“分布”的,不需要共享的,或者干脆规模小到只有一台服务器的应用,memcached不会带来任何好处,相反还会拖慢系统效率,因为网络连接同样需要资源


四、memcached的使用

memcached 修改命令参数

参数 用法
key key 用于查找缓存值
flags 可以包括键值对的整型参数,客户机使用它存储关于键值对的额外信息,发现如果在java中要获取数值,必须flags=32
expiration time 在缓存中保存键值对的时间长度(以秒为单位,0 表示永远)
bytes 在缓存中存储的字节点
value 存储的值(始终位于第二行)
下面时具体的说明一下set、get、add、replace、delete等几个命令的用法

set
set 命令用于向缓存添加新的键值对。如果键已经存在,则之前的值将被替换。

set userId 0 0 5
12345
STORED
如果使用 set 命令正确设定了键值对,服务器将使用单词 STORED 进行响应。本示例向缓存中添加了一个键值对,其键为 userId,其值为 12345。并将过期时间设置为 0,这将向 memcached 通知您希望将此值存储在缓存中直到删除它为止。


add
仅当缓存中不存在键时,add 命令才会向缓存中添加一个键值对。如果缓存中已经存在键,则之前的值将仍然保持相同,并且您将获得响应 NOT_STORED。

set userId 0 0 5
12345
STORED

add userId 0 0 5
55555
NOT_STORED

add companyId 0 0 3
564
STORED

replace
仅当键已经存在时,replace 命令才会替换缓存中的键。如果缓存中不存在键,那么您将从 memcached 服务器接受到一条 NOT_STORED 响应。

replace accountId 0 0 5
67890
NOT_STORED

set accountId 0 0 5
67890
STORED

replace accountId 0 0 5
55555
STORED

get  命令用于检索与之前添加的键值对相关的值。您将使用  get  执行大多数检索操作。

delete 命令用于删除 memcached 中的任何现有值。您将使用一个键调用 delete,如果该键存在于缓存中,则删除该值。如果不存在,则返回一条 NOT_FOUND 消息


gets
gets 命令的功能类似于基本的 get 命令。两个命令之间的差异在于,gets 返回的信息稍微多一些:64 位的整型值非常像名称/值对的 “版本” 标识符。考虑 get 和 gets 命令之间的差异。gets 命令将返回一个额外的值 — 在本例中是整型值 4,用于标识名称/值对。如果对此名称/值对执行另一个 set 命令,则 gets 返回的额外值将会发生更改,以表明名称/值对已经被更新


cas
cas(check 和 set)是一个非常便捷的 memcached 命令,用于设置名称/值对的值(如果该名称/值对在您上次执行 gets 后没有更新过)。它使用与 set 命令相类似的语法,但包括一个额外的值:gets 返回的额外值。

set userId 0 0 5
55555
STORED

gets userId
VALUE userId 0 5 6
55555
END

cas userId 0 0 5 6
33333
STORED

set userId 0 0 5
55555
STORED

gets userId
VALUE userId 0 5 8
55555
END

cas userId 0 0 5 6
33333
EXISTS

注意,我并未使用 gets 最近返回的整型值,并且 cas 命令返回 EXISTS 值以示失败。从本质上说,同时使用 gets 和 cas 命令可以防止您使用自上次读取后经过更新的名称/值对。

模拟多个Memcached client并发set同一个key的场景。如clientA想把当前key的value set为"x",且操作成功;clientB却把当前key的value值由"x"覆盖set为"y",这时clientA再根据key去取value时得到"y"而不是期望的"x",它使用这个值,但不知道这个值已经被其它线程修改过,就可能会出现问题。

CAS协议解决这种并发修改问题。有线程试图修改当前key-value对的value时,先由gets方法得到item的版本号,操作完成提交数据时,使用cas方法谨慎变更,如果在本地对item操作过程中这个key-value对在Memcached server端被其它线程更改过,就放弃此次修改(乐观锁概念)。

关于cas解决多线程或者多进程并发问题的实例,之前碰到过这样的问题,在另外一篇博客上可以看到详细的代码http://blog.csdn.net/xiaobaismiley/article/details/27208699


memcached  C++客户端使用——libmemcached

(memcached_get()方法获得到一个数据指针后,用完记得释放内存,否则会造成内存泄露:http://docs.libmemcached.org/memcached_get.html)

//============================================================================
// Name        : memcached_cpp.cpp
// Author      : 
// Version     :
// Copyright   : Your copyright notice
// Description : Hello World in C, Ansi-style
//============================================================================

#include <libmemcached/memcached.h>
#include <vector>
#include <sys/msg.h>
#include <errno.h>
#include <string>
#include <iostream>
#include <sys/file.h>
#include <stdio.h>
#include <vector>
#include <sys/time.h>
#include<time.h>
#include <math.h>

using namespace std;

int q2alen=0;
int alertfd=0;


long getCurrentTime()
{
   struct timeval tv;
   gettimeofday(&tv,NULL);
   return tv.tv_sec * 1000 + tv.tv_usec / 1000;
}

/*
 * @author: roger
 * @version: 2014-05-17 17:45:10
 *
 *libmemcached客户端的基本用法,增加,获取,删除数据
 */
int main() {

	memcached_st *memc;
	memcached_return rc;
	memcached_server_st *server;
	time_t expiration = 0 ;   //设置为0表示永不过期
	uint32_t flags ;  //如果与java客户端混用,这个需要设置为32

	memc = memcached_create(NULL);
	server = memcached_server_list_append(NULL, "localhost", 11211, &rc);
	rc = memcached_server_push(memc, server);  //set,get方法都需要这个参数
	memcached_server_list_free(server);
	string value = "nifse";
	size_t value_length = value.length();   //get方法中并不知道value的长度,可填0
	size_t key_length ;

	//Save data
	string key = "dai";
	rc = memcached_set(memc, key.c_str(), key.length(), value.c_str(),value.length(), expiration, flags);
	if (rc == MEMCACHED_SUCCESS) {
		cout << "Save data:" << value << " sucessful!" << endl;
	}

	long a= getCurrentTime();
//	Get data
	int i=0;
	while(i<100000){
		char* result = memcached_get(memc, key.c_str(), key.length(), &value_length,&flags, &rc);
		i++;
	}
	long b= getCurrentTime();
	cout<<b-a<<endl;

//	free,断开连接,释放资源,但未删除memcached中数据
	memcached_free(memc);
	return 0;
}


memcached  Java客户端使用( java客户端中使用memcached需要在get和set方法中将一个flag设置为32,否则会出错。)

import java.util.Calendar;

import com.danga.MemCached.MemCachedClient;
import com.danga.MemCached.SockIOPool;


/**
 * @author roger
 * @version 2014-05-17 17:57:59
 * 
 * 测试java程序中对memcached的连通性,MemCachedClient使用
 * 参考:http://jiaxiaoyuan1204.blog.163.com/blog/static/65553152010520112614157/
 */
public class Test {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		MemCachedClient client=new MemCachedClient();
        String [] addr ={"localhost:11211"};    //ip、端口号
        Integer [] weights = {3};
        
        //SockIOPool是Memcached客户端提供的一个套接字连接池
        SockIOPool pool = SockIOPool.getInstance();  
        pool.setServers(addr);
        pool.setWeights(weights);  
        pool.setInitConn(5);  
        pool.setMinConn(5);  
        pool.setMaxConn(200);  
        pool.setMaxIdle(1000*60*60);  
        pool.setMaintSleep(30);  
        pool.setNagle(false);  
        pool.setSocketTO(30);  
        pool.setSocketConnectTO(0);  
        pool.initialize();
          
        
        client.set("dai","15068808151");
//      获取缓存数据  
        
        client.get("dai");
        
        int i=0;
        Calendar calendar = Calendar.getInstance();
        long time = calendar.getTimeInMillis();
        while (i<100000) {
        	client.set("aa"+i,"1234567890");
        	i++;
		}
        Calendar calendar2 = Calendar.getInstance();
        long time2 = calendar2.getTimeInMillis();
        System.out.println(time2-time);
        
	}

}




两个程序简单说明了一下memcached常用的使用方法,也简单测试了一下读写效率,发现还是挺快的。



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值