JAVA实现的异步redis客户端

再使用redis的过程中,发现使用缓存虽然好,但是有些地方还是比较难权衡,缓存对象大了,存储对象时的序列化工作很繁重,消耗大量cpu;那么切分成很小的部分吧,存取的次数变多了,redis客户端的交互次数上不去,这是一个矛盾。要是有一个客户端能支持更多的交互次数,那么在完成既定指标的前提下,岂不是可以让我们的建模工作变的更宽松一些?

于是参照redis协议,花了5天时间,做了一个具备基本功能的redis客户端。它的特性:

1.支持异步调用,在getA之后不用等结果,能继续getB,getC,等等。等要做的redis操作都做完了,再来检查结果。

2.单连接,支持断线重连。客户端和任意一个redis服务器只建立一个连接。因为是异步调用,没必要建立更多连接。

3.底层支持pipeline,无论是异步调用,还是阻塞调用,底层使用的都有概率使用到pipeline。对pipeline的支持是在通信层做的,所以无论哪种调用都是隐性的使用pipeline。但是,连续的异步操作,本线程内的操作就有可能使用pipeline。而同步调用,则一般是线程之间的操作使用pipeline。更重要的是,这一切都是在底层完成的,我们在调用redis api的时候根本不用管这些,只管调用即可。只不过是建议采用连续的异步操作,因为这样效率最高。

4.支持shard模式。采用一致性算法的分片。

5.shard模式下仍然支持pipeline。因为对pipeline的支持是做在通信层的,所以,在任何模式下都支持pipeline。

最后看一下,在我机器上跑的结果吧:

机器配置:双核cpu,主频2GHz,8g内存,mac osx

redis运行在本机的虚拟机上,虚拟机单核单线程,2G内存,ubuntu server。

测试场景1(模拟阻塞调用的场景):

80个线程,进行简单的get、set,

每秒执行的get和set总数为:130000次以上。

public class ShardClientTest {

	public static void main(String[] args) throws IOException,
			InterruptedException {
		final int T = 80;
		final int CONTINUOUS = 1;
		final int N = 20000000;

		EzSelector selector = new EzSelector();
		List<BiTuple<String, Integer>> list = new ArrayList<>();
		list.add(new BiTuple<>("10.211.55.5", 6379));

		final ShardClient conn = new ShardClient(selector, list);

		final AtomicLong count = new AtomicLong();
		for (int n = 0; n < T; n++) {
			Thread t = new Thread() {
				public void run() {
					try {
						for (int i = 0; i < N; i++) {
							try {
								Result ret = null;
								for (int cc = 0; cc < CONTINUOUS; cc++) {
									ret = conn.asyncSet(i + "", i + ":" + cc);
									// System.out.println(ret.get());
								}
								ret.get();

								Result ret6 = null;
								for (int cc = 0; cc < CONTINUOUS; cc++) {
									ret6 = conn.asyncGet(i + "");
									// System.out.println(ret6.get());
								}
								ret6.get();

								count.addAndGet(CONTINUOUS * 2);
							} catch (Exception e) {
								e.printStackTrace();
							} finally {
							}
						}
					} catch (Exception e) {
						e.printStackTrace();
					}
				};
			};
			t.start();
		}

		while (true) {
			long start = count.get();
			Thread.sleep(1000);
			System.out.println(count.get() - start);
		}
	}

}

测试场景2(模拟异步调用,连续5次get和set):

每秒可执行的get和set总数是330000次左右

package zhmt.ezredis;

import java.io.IOException;
import java.util.concurrent.atomic.AtomicLong;

import zhmt.eznet.EzSelector;
import zhmt.eznet.EzSocketOption;
import zhmt.eznet.SharedRpcConnection.Result;
import zhmt.ezredis.AsyncClient;

public class RedisClientTest {
	public static void main(String[] args) throws IOException,
			InterruptedException {
		final int T = 100;
		final int CONTINUOUS = 5;
		final int N = 20000000;

		EzSelector selector = new EzSelector();
		final RedisClient conn = new AsyncClient(selector,
				new EzSocketOption("10.211.55.5", 6379));

		final AtomicLong count = new AtomicLong();
		for (int n = 0; n < T; n++) {
			Thread t = new Thread() {
				public void run() {
					try {
						for (int i = 0; i < N; i++) {
							try {
								Result ret = null;
								for (int cc = 0; cc < CONTINUOUS; cc++) {
									ret = conn.asyncSet(i + "", i + ":" + cc);
									// System.out.println(ret.get());
								}
								ret.get();

								Result ret6 = null;
								for (int cc = 0; cc < CONTINUOUS; cc++) {
									ret6 = conn.asyncGet(i + "");
									// System.out.println(ret6.get());
								}
								ret6.get();

								count.addAndGet(CONTINUOUS * 2);
							} catch (Exception e) {
								e.printStackTrace();
							} finally {
							}
						}
					} catch (Exception e) {
						e.printStackTrace();
					}
				};
			};
			t.start();
		}

		while (true) {
			long start = count.get();
			Thread.sleep(1000);
			System.out.println(count.get() - start);
		}
	}
}

到目前为止,只实现了十几命令。

接下来,准备优先实现用户自定义shard key。使数据按照用户的意图去分片。以最大化pipeline的使用。

其次,继续实现常用命令。

源码:

https://github.com/zhmt/ezredis

JAVA实现的异步redis客户端

时间: 2024-10-25 20:59:21

JAVA实现的异步redis客户端的相关文章

PHP的异步Web服务器+异步Redis客户端

PHP的异步并行swoole扩展在1.7.7中内置了一个Http服务器,利用swoole_http_server可以轻松实现一个PHP的异步Web服务器,性能比php-fpm/Apache等同步阻塞的服务器高出数倍. swoole官方还提供了redis-async,一个异步IO+连接池的Redis客户端.这2个功能结合起来就可以打造一个并发请求数万的Web应用. 使用方法 1. 下载安装swoole扩展 可以使用pecl安装或者从github下载swoole最新的stable版本. pecl i

java里常用的redis客户端简介

Redis的各种语言客户端列表,请参见Redis Client.其中Java客户端在github上start最高的是Jedis和Redisson.Jedis提供了完整Redis命令,而Redisson有更多分布式的容器实现. 原文地址:https://www.cnblogs.com/shamo89/p/8794734.html

SWOOLE异步REDIS安装

SWOOLE的异步REDIS客户端一,安装hiredis    wget https://github.com/redis/hiredis/archive/v0.13.3.tar.gz    直接 make make install就可以了    就是把相关的头文件放到相应的目录里    二,升级swoole版本为1.8.0    github地址:        git clone https://github.com/swoole/swoole-src.git    或者tar.gz包  

Java的Redis客户端Jedis

Java的Redis客户端Jedis 一.用windows中的Eclipse连接虚拟机的Redis的注意事项 禁用Linux的防火墙:Linux里执行命令 service iptables  stop 我的是已经禁用的, 修改redis.conf中注释掉bind 127.0.0.1 ,然后 protect-mode no 二.新建动态java工程, ① 导包 吐槽一下,这个workspace里都是Maven工程,去别的工程复制个junit jar包都找不到,好不容易找到包导入后运行又报错, ja

Redis02 Redis客户端之Java

1 查看支持Java的redis客户端 本博文采用 Jedis 作为redis客户端,采用 commons-pool2 作为连接redis服务器的连接池 2 下载相关依赖与实战 2.1 到 Repository官网下载jar包 jedis <!-- https://mvnrepository.com/artifact/redis.clients/jedis --> <dependency> <groupId>redis.clients</groupId> &

Redis笔记整理(二):Java API使用与Redis分布式集群环境搭建

[TOC] Redis笔记整理(二):Java API使用与Redis分布式集群环境搭建 Redis Java API使用(一):单机版本Redis API使用 Redis的Java API通过Jedis来进行操作,因此首先需要Jedis的第三方库,因为使用的是Maven工程,所以先给出Jedis的依赖: <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactI

一个使用高并发高线程数 Server 使用异步数据库客户端造成的超时问题

现象 今天在做一个项目时, 将 tomcat 的 maxThreads 加大, 加到了 1024, tomcat 提供的服务主要是做一些运算, 然后插入 redis, 查询 redis, 最后将任务返回给客户端 在做压测时, 同时开了 1000 个线程, 并发发起 http 请求去访问 tomcat 的服务, 结果在第一次访问 tomcat 时出现了一系列的 redis 查询超时, 例如 1000 个并发发起 10W 次请求, 可能头 1W 次请求会有 2000 次左右的 redis 超时造成服

Redisson Redis 客户端

Redisson 2.3.0 发布了,勤快学qkxue.net发现Redisson 是基于 Redis 服务之上构建的分布式.可伸缩的 Java 数据结构,高级的 Redis 客户端. 该版本更新内容如下: Feature - new service added RExecutorService. More info about it hereFeature - new service added RScheduledExecutorService. More info about it her

spring整合redis客户端及缓存接口设计(转)

一.写在前面 缓存作为系统性能优化的一大杀手锏,几乎在每个系统或多或少的用到缓存.有的使用本地内存作为缓存,有的使用本地硬盘作为缓存,有的使用缓存服务器.但是无论使用哪种缓存,接口中的方法都是差不多.笔者最近的项目使用的是memcached作为缓存服务器,由于memcached的一些限制,现在想换redis作为缓存服务器.思路就是把memached的客户端换成redis客户端,接口依然是原来的接口,这样对系统可以无损替换,接口不变,功能不变,只是客户端变了.本文不介绍缓存的用法,不介绍redis