`
snowyregion
  • 浏览: 11765 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

为memcahed官方java client 添加使用getMulti协议的getMulti方法

阅读更多

memcahe本身提供有对getMulti的支持 但是memecahed java client中的getMulti方法是使用多线程并发请求来实现的 为了减少socket的消耗添加了一个对getMulti(协议中为get key1 key2 ...)协议支持的方法

 

在AscIIClient中增加下面方法

 

	private Map<String, Object> doMget(MultiKeyBuffer multiKeyBuffer) {
		Map<String, Object> valuesMap = new HashMap<String, Object>();

		while(multiKeyBuffer.hasNext()) {
			String multiKey = multiKeyBuffer.next();
			
			if(multiKey == null) return null;
			
			// get SockIO obj using cache key
			SchoonerSockIO sock = pool.getSock(multiKey, null);

			if (sock == null) {
				if (errorHandler != null)
					errorHandler.handleErrorOnGet(this, new IOException("no socket to server available"), multiKey);
				return null;
			}

			String cmdLine = "get " + multiKey;

			try {
				sock.writeBuf.clear();
				sock.writeBuf.put(cmdLine.getBytes());
				sock.writeBuf.put(B_RETURN);
				// write buffer to server
				sock.flush();

				SockInputStream input = new SockInputStream(sock, Integer.MAX_VALUE);
				int oneTimeReadMaxCount = 32;
				jump:
				while(oneTimeReadMaxCount-- > 0){
					String responseKey = "";
					int dataSize = 0;
					int flag = 0;
					boolean stop = false;
					StringBuilder sb = new StringBuilder();
					int b;
					int index = 0;
					while (!stop) {
						/*
						 * Critical block to parse the response header.
						 */
						b = input.read();
						if (b == ' ' || b == '\r') {
							switch (index) {
							case 0:
								if (END.startsWith(sb.toString()))
									break jump;
							case 1:
								responseKey = sb.toString();
								break;
							case 2:
								flag = Integer.parseInt(sb.toString());
								break;
							case 3:
								// get the data size
								dataSize = Integer.parseInt(sb.toString());
								break;
							}
							index++;
							sb = new StringBuilder();
							if (b == '\r') {
								input.read();
								stop = true;
							}
							continue;
						}
						sb.append((char) b);
					}

					Object o = null;
					input.willRead(dataSize);
					// we can only take out serialized objects
					if (dataSize > 0) {
						if (NativeHandler.isHandled(flag)) {
							// decoding object
							byte[] buf = input.getBuffer();
							if ((flag & F_COMPRESSED) == F_COMPRESSED) {
								GZIPInputStream gzi = new GZIPInputStream(new ByteArrayInputStream(buf));
								ByteArrayOutputStream bos = new ByteArrayOutputStream(buf.length);
								int count;
								byte[] tmp = new byte[2048];
								while ((count = gzi.read(tmp)) != -1) {
									bos.write(tmp, 0, count);
								}
								// store uncompressed back to buffer
								buf = bos.toByteArray();
								gzi.close();
							}
							if (primitiveAsString) {
								o = new String(buf, defaultEncoding);
							} else
								o = NativeHandler.decode(buf, flag);
						} else if (transCoder != null) {
							// decode object with default transcoder.
							InputStream in = input;
							if ((flag & F_COMPRESSED) == F_COMPRESSED)
								in = new GZIPInputStream(in);
							if (classLoader == null)
								o = transCoder.decode(in);
							else
								o = ((ObjectTransCoder) transCoder).decode(in, classLoader);
						}
						valuesMap.put(responseKey, o);
					}
					input.willRead(Integer.MAX_VALUE);
					input.getLine();//跳过每一个value发送完成的\r\n
				}
			} catch (Exception ce) {
				try {
					sock.trueClose();
				} catch (IOException e) {
					log.error("++++ failed to close socket : " + sock.toString());
				}
				sock = null;
			} finally {
				if (sock != null) {
					sock.close();
					sock = null;
				}
			}
		}
		return valuesMap;
	}

	@Override
	public Map<String, Object> mget(String[] keys) {
		if (keys == null || keys.length == 0) {
			log.error("keys is null for mget()");
			return null;
		}
		MultiKeyBuffer buf = new MultiKeyBuffer(keys);
		return doMget(buf);
	}
	/*这里设置每次使用getMulti最多执行多少个key(忘了memcache支持一次多少个key了...)*/
	private static int per_multikey_max_size = 32;
	class MultiKeyBuffer{
		
		/**原始数据*/
		private final String[] keys;
		
		/**当前已经取到了哪个位置(从0开始)*/
		private int position;
		
		/**数组的长度*/
		private final int size;
		
		public MultiKeyBuffer(String[] keys) {
			this.keys = keys;
			size = keys.length;
		}
		
		/**
		 * 获取下一个multiKey
		 * @return
		 */
		public String next(){
			if(hasNext()){
				int limit = Math.min(size, position + per_multikey_max_size);
				StringBuilder multiKeySb = new StringBuilder();
				while(position < limit){
					String key = keys[position];
					try {
						key = sanitizeKey(key);
					} catch (UnsupportedEncodingException e) {
						log.error("failed to sanitize your key!", e);
						return null;
					}
					multiKeySb.append(" ").append(key);
					position ++;
				}
				return multiKeySb.substring(1);
			}
			return null;//调用hasNext()防止执行到该行
		}
		
		public boolean hasNext(){
			return position < size;
		}
		
	}

 

 在父类MemcachdClient中增加

 

	public Map<String, Object> mget(String[] keys) {
		return client.mget(keys);
	}

 

 

 

分享到:
评论

相关推荐

    普通java工程测试java使用memcached连接服务端

    例如,使用`getMulti()`方法可以一次性获取多个键对应的值: ```java Collection&lt;String&gt; keys = Arrays.asList("key1", "key2", "key3"); Map, Object&gt; values = memcachedClient.getMulti(keys); for (Map.Entry,...

    Memcached之java客户端开发

    - **批量操作**:`getMulti`方法支持一次性获取多个键的值,`setMulti`用于批量设置键值对。 - **过期时间**:除了固定的过期时间,还可以设置相对时间,如`client.set("key", 0, "value")`表示永不超时。 - **操作...

    spymemcached-2.7.3应用的演示工程

    在Java项目中使用`spymemcached`,首先需要将其添加为项目依赖。通常,这可以通过Maven或Gradle的依赖管理完成。在Maven的`pom.xml`文件中,添加如下依赖: ```xml &lt;groupId&gt;net.spy&lt;/groupId&gt; &lt;artifactId&gt;...

    memcached全部的jar包2.5.1.rar

    - **添加数据**:使用`MemcachedClient`的`set`方法可以将数据存储到缓存中,指定一个键和一个过期时间。 - **获取数据**:通过键来检索数据,使用`get`方法。 - **删除数据**:如果不再需要某个缓存项,可以使用...

    mencach文档以及使用方法

    **Mencache 使用指南** Mencache,全称为“Memory Cache”,是一款高性能、轻量级的内存缓存系统...理解其工作原理和使用方法,能够帮助开发者有效地利用这一工具,为网站或应用带来更快的响应速度和更好的用户体验。

    易语言Memcached协议客户端模块

    易语言Memcached协议客户端模块源码,Memcached协议客户端模块,Initialize,Connect,Timeout,Exptime,IsRunning,RunStorageCommand,AnalyzeMessage,Set,Add,Replace,Delete,Incr,Decr,Version,Get,GetMulti,...

    node-memcached

    例如,可以使用`client.setMulti()`和`client.getMulti()`进行批量设置和获取多个键值对。 六、异常处理与最佳实践 在使用`node-memcached`时,应妥善处理异常,避免程序因网络问题或Memcached服务器故障而中断。...

    PHP100视频教程73:PHP.MemCached高级缓存配置.rar

    - 创建`Memcached`实例,通过`new Memcached()`来初始化连接,并使用`addServer()`方法添加服务器地址和端口。 3. **Memcached的高级配置** - **持久连接**:使用`pconnect()`代替`connect()`,保持客户端与...

    php_memcache-3.0.8-5.3-ts-vc9-x86.zip

    3. **LICENSE**:文件包含了该扩展的授权协议,规定了如何使用、修改和分发代码的规则,对于开源软件而言,理解许可协议是遵守法律的基础。 4. **php_memcache.pdb**:这是一个程序数据库文件,用于在开发阶段调试...

    易语言Memcached协议客户端模块源码-易语言

    开源+示例(模块代码中有详细的使用方法) 参照网上的 Memcached 协议实现的客户端,可靠性方面应该还是不错的,和昨天的 Redis 协议一样,应该能适用于正式项目。 总共耗费 2 个多小时完成,不可否认,用纯易语言实现...

    memcached-2.3.1 api

    通过深入理解和熟练使用 Memcached-2.3.1 API,开发者能够构建高效、可靠的分布式缓存系统,为应用程序提供快速的数据访问和减轻数据库压力。在阅读 `memcached-2.3.1-javadoc` 文档时,应重点理解每个方法的功能、...

    PHP100视频教程74:PHP.MemCached.高级缓存应用.rar

    使用`setMulti()`和`getMulti()`方法进行批量操作。 2. 自动过期: 除了手动设置过期时间,还可以使用`add()`方法,当键已存在时,数据将不会被添加,这可以避免覆盖已存在的缓存。 3. 缓存预热: 在高流量网站上...

    nds:具有高度一致的缓存的Go(golang)Google App Engine数据存储区程序包

    nds 软件包github.com/qedus/nds是Google App ... 标准的datastore.GetMulti , datastore.PutMulti和datastore.DeleteMulti函数的另一个好处是,每个调用最多只能使用1000、500和500个实体。 此包中的nds.GetMulti

    批量获取memcache值并按key的顺序返回的实现代码

    Memcache提供了一个名为`getMulti`的函数,用于批量获取多个键的值。在上述描述中,我们看到一个示例,尝试通过`getMulti`获取15个特定ID(如31639, 33878等)的值。然而,当使用单台Memcache服务器时,`getMulti`...

    php的memcached客户端memcached

    `Memcache`是较早的客户端,支持非面向对象的接口,而`Memcached`则使用libmemcached库,仅支持面向对象接口,提供了更多方法,例如`getMulti`、`getByKey`和`addServers`。`Memcached`还支持二进制协议,这使得它在...

    用JavaScript实现字符串切分功能

    如果没有任何分隔符被找到,函数会设置`t`为0,并将整个原始字符串添加到`linkstr`中,表示字符串没有被切割。 需要注意的是,`getmulti`函数并没有使用`split()`函数,而是通过比较和查找分隔符的方式来实现字符串...

Global site tag (gtag.js) - Google Analytics