JAVA实现的异步redisclient
再使用redis的过程中,发现使用缓存尽管好,可是有些地方还是比較难权衡,缓存对象大了,存储对象时的序列化工作非常繁重,消耗大量cpu;那么切分成非常小的部分吧,存取的次数变多了,redisclient的交互次数上不去,这是一个矛盾。要是有一个client能支持很多其它的交互次数,那么在完毕既定指标的前提下,岂不是能够让我们的建模工作变的更宽松一些?
于是參照redis协议,花了5天时间,做了一个具备基本功能的redisclient。它的特性:
1.支持异步调用,在getA之后不用等结果,能继续getB,getC,等等。等要做的redis操作都做完了,再来检查结果。
2.单连接,支持断线重连。client和随意一个redisserver仅仅建立一个连接。由于是异步调用,不是必需建立很多其它连接。
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实现的异步redisclient的更多相关文章
- Java多线程实现异步调用
在Java平台,实现异步调用的角色有如下三个角色:调用者. 提货单 .真实数据,一个调用者在调用耗时操作,不能立即返回数据时,先返回一个提货单 .然后在过一断时间后凭提货单来获取真正的数据.去蛋糕店买 ...
- java网络通信:异步非阻塞I/O (NIO)
转: java网络通信:异步非阻塞I/O (NIO) 首先是channel,是一个双向的全双工的通道,可同时读写,而输入输出流都是单工的,要么读要么写.Channel分为两大类,分别是用于网络数据的S ...
- Java回调实现异步 (转)
出处: Java回调实现异步 在正常的业务中使用同步线程,如果服务器每处理一个请求,就创建一个线程的话,会对服务器的资源造成浪费.因为这些线程可能会浪费时间在等待网络传输,等待数据库连接等其他事情上, ...
- 深入浅出: Java回调机制(异步)
一.什么是回调 回调,回调.要先有调用,才有调用者和被调用者之间的回调.所以在百度百科中是这样的: 软件模块之间总是存在着一定的接口,从调用方式上,可以把他们分为三类:同步调用.回调和异步调用. 回调 ...
- java 中的异步回调
异步回调,本来在c#中是一件极为简单和优雅的事情,想不到在java的世界里,却如此烦琐,先看下类图: 先定义了一个CallBackTask,做为外层的面子工程,其主要工作为start 开始一个异步操作 ...
- 【转载】高性能IO设计 & Java NIO & 同步/异步 阻塞/非阻塞 Reactor/Proactor
开始准备看Java NIO的,这篇文章:http://xly1981.iteye.com/blog/1735862 里面提到了这篇文章 http://xmuzyq.iteye.com/blog/783 ...
- wemall app商城源码中基于JAVA的Android异步加载图片管理器代码
wemall doraemon是Android客户端程序,服务端采用wemall微信商城,不对原商城做任何修改,只需要在原商城目录下上传接口文件即可完成服务端的配置,客户端可随意定制修改.本文分享其中 ...
- Java中的异步通知
在我们的日常开发中,经常会遇到这样的问题--"我让你做一件事情,但是你做得很慢,并不能够立马返回给我结果,害我一直在那儿等着你给我返回结果,什么都做不了". 程序是自上而下顺序执行 ...
- java CountDownLatch 控制异步和同步
应用场景举例: 执行A项目的方法,需要调用B项目.C项目.D项目的接口方法. 需求: 异步调用B.C.D项目的接口方法,且每个接口都调用结束后,A项目的方法才可以结束. 注:如果需要获取接口返回结果, ...
随机推荐
- [转] LCA与Tarjan
转载:http://m.blog.csdn.net/blog/u013076044/41875009# 在线算法与离线算法的定义 在计算机科学中,一个在线算法是指它可以以序列化的方式一个个的处理输入, ...
- 解决angular的post请求后SpringMVC后台接收不到参数值问题的方法
这是我后台SpringMVC控制器接收isform参数的方法,只是简单的打出它的值: @RequestMapping(method = RequestMethod.POST) @ResponseBod ...
- poj 3279 Fliptile
题意:一个n * m的棋盘,0或1,每次改变一个格子时同时改变上下左右的格子,问用最少次数将棋盘全变成0的策略. 题解:用二进制压缩第一行更改的状态,之后遍历棋盘,如果当前格子为1则改变下方的格子,记 ...
- Delphi 打印
procedure TForm1.PrinterSetupExecute(Sender: TObject);begin PrinterSetupDialog1.Execute;end; procedu ...
- FZU 2105-Digits Count(线段树延时标记)
题意: 每次操作区间每个数进行一种(&或|.或^ )给定的一个数,到sum时统计给定区间的和. 分析: 这个题让我觉得我的思维很不活跃,对懒惰标记理解,还远远不够,通过这道题我对懒惰标记加深了 ...
- e2e 自动化集成测试 架构 实例 WebStorm Node.js Mocha WebDriverIO Selenium Step by step (二) 图片验证码的识别
上一篇文章讲了“e2e 自动化集成测试 架构 京东 商品搜索 实例 WebStorm Node.js Mocha WebDriverIO Selenium Step by step 一 京东 商品搜索 ...
- Java WebService简单使用
一直在写java但从来没有使用webservice,在网上查了下资料写个简单的使用放这里做备份 具体步骤: 1.新建一个java工程在里面写一个类(服务端)如下: package com.webser ...
- NOIP2008 双栈队列
1. 双栈排序 (twostack.pas/c/cpp) Tom 最近在研究一个有趣的排序问题.如图所示,通过 2 个栈 S1 和 S2,Tom 希望借助 以下 4 种操作实现将输入序列升序 ...
- Cppcheck代码分析(1)
一.检查点 1.自动变量检查: 返回自动变量(局部变量)指针 2.越界检查: 数组越界返回自动变量(局部变量)指针 3.类检查: 构造函数初始化 4.内存泄露检查: 5.空指针检查: 6.废弃函数检查 ...
- 字符串旋转(str.find()---KMP)
此题旋转带有技巧性,问题转化为常见的问题,熟练STL可以直接用str.find()函数,其是主要想用KMP算法实现字符串的查找算法... //如果对于一个字符串A,将A的前面任意一部分挪到后边去形成的 ...