Zookeeper读写性能测试

本文涉及的产品
性能测试 PTS,5000VUM额度
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
注册配置 MSE Nacos/ZooKeeper,118元/月
简介:
关于Zookeeper,之前有过几篇 文章已经介绍过了,因此本文不赘述。 本次小编对单机部署的Zookeeper的读、写进行了一次简单 性能测试。 性能测试脚本由 java完成,具体请看代码清单:
package com.kiven.test;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import org.apache.log4j.PropertyConfigurator;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;
public class Test{
/**
server列表, 以逗号分割
*/
protected static String hosts = "172.16.217.148:2181";
/**
* 连接的超时时间, 毫秒
*/
private final int SESSION_TIMEOUT = 5000;
private CountDownLatch connectedSignal = new CountDownLatch(1);
protected static ZooKeeper zk;
private static String nodePath = "/Test/test1";
//static String data = "a very long string about data to set to zookeeper";
static int threads = 10;    //线程数
static int runs = 1000;     //迭代次数
static int start = 0;       //none
static int size = 1024*4;   //写入数据的大小,单位:字节
static byte[] testdata;     //测试数据
public static void main(String[] args) throws Exception {
PropertyConfigurator.configure("log4j.properties");
//生成写入的数据,大小size字节
testdata = new byte[size];
for(int i=0;i<size;i++){
testdata[i] = 'A';
}
Test test = new Test();
//连接
test.connect();
WorkerStat[] statArray = new WorkerStat[threads];
Thread[] threadArray = new Thread[threads];
WorkerStat mainStat = new WorkerStat();
mainStat.runs = runs * threads;
long begin = System.currentTimeMillis();
for (int i = 0; i < threads; i++) {
statArray[i] = new WorkerStat();
statArray[i].start = start + i * runs;
statArray[i].runs = runs;
threadArray[i] = new SetterThread(statArray[i]);
threadArray[i].start();
}
for (int i = 0; i < threads; i++) {
threadArray[i].join();
}
mainStat.setterTime = System.currentTimeMillis() - begin;
begin = System.currentTimeMillis();
for (int i = 0; i < threads; i++) {
threadArray[i] = new GetterThread(statArray[i]);
threadArray[i].start();
}
for (int i = 0; i < threads; i++) {
threadArray[i].join();
}
mainStat.getterTime = System.currentTimeMillis() - begin;
WorkerStat totalStat = new WorkerStat();
System.out.println("Test over!!");
System.out.println("Thread("+threads+")\truns\tset time(ms)\tget time(ms)");
for (int i = 0; i < threads; i++) {
totalStat.runs = totalStat.runs + statArray[i].runs;
totalStat.setterTime = totalStat.setterTime + statArray[i].setterTime;
totalStat.getterTime = totalStat.getterTime + statArray[i].getterTime;
}
System.out.println("Total\t\t" + totalStat.runs + "\t"+ totalStat.setterTime + "\t\t" + totalStat.getterTime);
System.out.println("Avg\t\t" + runs + "\t" + totalStat.setterTime/ threads + "\t\t" + totalStat.getterTime / threads);
System.out.println("TPS\t\t\t" + 1000 * totalStat.runs/ totalStat.setterTime + "\t\t" + 1000 * totalStat.runs/ totalStat.getterTime);
System.out.println("\nMain\t\t" + mainStat.runs + "\t"+ mainStat.setterTime + "\t\t" + mainStat.getterTime);
System.out.println("TPS\t\t" + 1000 * mainStat.runs/ mainStat.setterTime + "\t\t" + 1000 * mainStat.runs/ mainStat.getterTime);
}
private static class WorkerStat {
public int start, runs;
public long setterTime, getterTime;
public WorkerStat() {
start = runs = 0;
setterTime = getterTime = 0;
}
}
private static class SetterThread extends Thread {
private WorkerStat stat;
SetterThread(WorkerStat stat) {
this.stat = stat;
}
public void run() {
long begin = System.currentTimeMillis();
for (int i = stat.start; i < stat.start + stat.runs; i++) {
//写入节点数据
try {
zk.setData(nodePath, testdata, -1);
} catch (Exception e) {
e.printStackTrace();
}
}
long end = System.currentTimeMillis();
stat.setterTime = end - begin;
}
}
private static class GetterThread extends Thread {
private WorkerStat stat;
GetterThread(WorkerStat stat) {
this.stat = stat;
}
public void run() {
long begin = System.currentTimeMillis();
for (int i = stat.start; i < stat.start + stat.runs; i++) {
//读取节点数据
try {
zk.getData(nodePath, false, null);
} catch (Exception e) {
e.printStackTrace();
}
}
long end = System.currentTimeMillis();
stat.getterTime = end - begin;
}
}
//===============================================================================
/**
* 连接zookeeper server
*/
public void connect() throws Exception {
zk = new ZooKeeper(hosts, SESSION_TIMEOUT, new ConnWatcher());
// 等待连接完成
connectedSignal.await();
}
/**
*
* @author Kiven
*
*/
public class ConnWatcher implements Watcher{
public void process(WatchedEvent event) {
// 连接建立, 回调process接口时, 其event.getState()为KeeperState.SyncConnected
if (event.getState() == KeeperState.SyncConnected) {
// 放开闸门, wait在connect方法上的线程将被唤醒
connectedSignal.countDown();
}
}
}
/**
以下为各个参数的详细说明:
path. znode的路径.
data. 与znode关联的数据.
acl. 指定权限信息, 如果不想指定权限, 可以传入Ids.OPEN_ACL_UNSAFE.
指定znode类型. CreateMode是一个枚举类, 从中选择一个成员传入即可.
*/
/**
* 创建持久化节点
*/
public void create(String Path, byte[] data) throws Exception {
zk.create(Path, data, Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
System.out.println("创建节点:"+Path);
System.out.println("=================");
}
/**
*
*获取节点信息
*@author kiven
*@createDate 2013-01-16 15:17:22
*@param path
*@throws KeeperException
*@throws InterruptedException
*/
public void getChild(String path) throws KeeperException, InterruptedException{
try{
List list=zk.getChildren(path, false);
if(list.isEmpty()){
System.out.println(path+"中没有节点");
}else{
System.out.println(path+"中存在节点");
for(String child:list){
System.out.println("节点为:"+child);
}
}
}catch (KeeperException.NoNodeException e) {
e.printStackTrace();
}
}
/**
* 设置节点数据
* @throws Exception
*/
public void setData(String path,String data) throws Exception{
zk.setData(path, data.getBytes(), -1);
System.out.println("set Data:"+"testSetData");
}
/**
* 读取节点数据
* @throws Exception
*/
public void getData() throws Exception{
System.out.println("get Data:");
zk.getData(nodePath, false, null);
}
/**
* 删除节点
* @param path
* @throws Exception
*/
public void delete(String path) throws Exception{
System.out.println("删除节点:"+path);
//如果版本号与znode的版本号不一致,将无法删除,是一种乐观加锁机制;如果将版本号设置为-1,不会去检测版本,直接删除;
zk.delete(path, -1);
}
/**
* 关闭连接
*/
public void close() {
try {
zk.close();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
  相关功能代码中都已经注释清楚。我们看一下测试下来的结果: 写入数据: 
  读取数据:
  由上两张图我们可以得知:
  1、写入(set)数据时,单个线程执行是最快的,而读取(get)数据则是4或5个线程并发是最快的。
  2、每个节点存储的数据不能超过1M(在Zookeeper默认配置的情况下,如果写入的数据为1M会报错,无法写入数据,所以所有应用写入的数据必须<1M)
  3、单个写入数据的体积越大,处理速度越慢,响应时间越长。
  4、会管应用中写入的数据最大的是16方画面合成的时候,此时写入的数据可能大于4K,另外16方画面合成时候zk节点存放的数据(json)是包含大量空格和换行的(在zk节点中,空格和换行也是占大小的),因此建议压缩json数据。
  5、测试过程中产生的log文件对磁盘的消耗和占用较大,建议定时删除历史log和shapshot
最新内容请见作者的GitHub页:http://qaseven.github.io/

相关实践学习
基于MSE实现微服务的全链路灰度
通过本场景的实验操作,您将了解并实现在线业务的微服务全链路灰度能力。
相关文章
|
2月前
|
存储 运维 NoSQL
分布式读写锁的奥义:上古世代 ZooKeeper 的进击
本文作者将介绍女娲对社区 ZooKeeper 在分布式读写锁实践细节上的思考,希望帮助大家理解分布式读写锁背后的原理。
|
3月前
|
分布式计算 监控 Hadoop
Hadoop-29 ZooKeeper集群 Watcher机制 工作原理 与 ZK基本命令 测试集群效果 3台公网云服务器
Hadoop-29 ZooKeeper集群 Watcher机制 工作原理 与 ZK基本命令 测试集群效果 3台公网云服务器
63 1
|
3月前
|
分布式计算 Hadoop Unix
Hadoop-28 ZooKeeper集群 ZNode简介概念和测试 数据结构与监听机制 持久性节点 持久顺序节点 事务ID Watcher机制
Hadoop-28 ZooKeeper集群 ZNode简介概念和测试 数据结构与监听机制 持久性节点 持久顺序节点 事务ID Watcher机制
63 1
|
5月前
|
SQL 缓存 关系型数据库
MySQL配置简单优化与读写测试
MySQL配置简单优化与读写测试
|
7月前
|
XML Java 测试技术
《手把手教你》系列技巧篇(六十七)-java+ selenium自动化测试 - 读写excel文件 - 中篇(详细教程)
【6月更文挑战第8天】本文介绍了Java中操作Excel的工具,包括POI和JXL。POI支持处理Office 2003及以下的OLE2格式(.xls)和2007以上的OOXML格式(.xlsx)。而JXL只能处理2003版本的Excel文件。文章详细讲解了如何下载和使用JXL库,并给出了一个简单的Java代码示例,展示如何读取2003版Excel文件中的数据。在实际项目中,由于JXL对新版本Excel的支持限制,通常推荐使用POI。
83 5
|
7月前
|
Java 测试技术 Apache
《手把手教你》系列技巧篇(六十八)-java+ selenium自动化测试 - 读写excel文件 - 下篇(详细教程)
【6月更文挑战第9天】本文介绍了如何使用Java处理Excel文件中的不同数据类型,包括日期、数字、布尔值和标签(常规字符串)。文章提供了两个示例,分别使用JXL库和Apache POI库来读取Excel文件。
56 1
|
7月前
|
Java 测试技术 Apache
《手把手教你》系列技巧篇(六十六)-java+ selenium自动化测试 - 读写excel文件 - 上篇(详细教程)
【6月更文挑战第7天】本文介绍了在Java自动化测试中如何操作Excel数据。文章提到了当测试数据存储在Excel文件时,可以使用Apache的POI库来读写Excel。POI提供了对OLE2(.xls)和OOXML(.xlsx)格式的支持,比JXL库功能更全面。文章还详细讲解了如何下载和添加POI库到项目中,以及准备测试用的Excel文件。最后,给出了一个简单的Java代码示例,演示如何读取Excel文件的内容。
74 1
|
8月前
|
网络协议 中间件 数据库
Zookeeper学习系列【三】Zookeeper 集群架构、读写机制以及一致性原理(ZAB协议)
Zookeeper学习系列【三】Zookeeper 集群架构、读写机制以及一致性原理(ZAB协议)
300 0
|
缓存 开发工具 内存技术
ZYNQ-使用自定义AXI总线IP核进行DDR读写测试(二)
ZYNQ-使用自定义AXI总线IP核进行DDR读写测试
913 0
ZYNQ-使用自定义AXI总线IP核进行DDR读写测试(二)
|
异构计算
FPGA片内RAM读写测试实验 2
FPGA片内RAM读写测试实验
232 0

热门文章

最新文章