Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >工具包 java-dataloader 异步批处理装载数据

工具包 java-dataloader 异步批处理装载数据

作者头像
兜兜毛毛
发布于 2022-09-19 09:55:17
发布于 2022-09-19 09:55:17
76100
代码可运行
举报
文章被收录于专栏:兜兜毛毛兜兜毛毛
运行总次数:0
代码可运行

一个小巧简单的工具包,主要解决应用程序组装数据,提供一个简单的通用的API,通过异步批处理方式,减少通信问题。

该工具包是从graphql工具中抽出,在graphql里查询数据,很容易导致"n+1"获取问题。比如用户列表需要查询对应的部门,有些用户的部门相同,会被多次查询。

Github:源码地址

特点

  • 使用简单直观
  • 使用队列临时存储查询健,之后进行批量查询,减少查询开销
  • 请求返回CompleteableFuture<V>可以做后续处理
  • 支持缓存,数据可以只获取一次
  • 可自定义缓存

原理

使用CompletableFuture异步加载实现。通过API将每组结果使用CompletableFuture包装,并将关键Key存储到队列中, 当Key的数量达到一定量或一定时间时后,再调用异步批量查询方法,然后再把结果回调给每组结果的CompletableFuture。

如何使用

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
BatchLoader<Long, Department> departmentBatchLoader = new BatchLoader<Long, Department>() {
	@Override
	public CompletionStage<List<Department>> load(List<Long> departmentIds) {
		return CompletableFuture.supplyAsync(() -> {
			return departmentManager.loadDepartmentById(departmentIds);
		});
	}
};

DataLoader<Long, Department> departmentLoader = DataLoaderFactory.newDataLoader(departmentBatchLoader);
List<User> userList = userManager.getAllUser();
userList.foreach(user ->{
		departmentLoader.loader(user.getDepartmentId).thenAccept(department ->{
			user.setDepartment(department);
		});
});

避坑

批量处理BatchLoader

该方式是以List<key>形式入参,返回结果顺序,需要与入参时的Key顺序形同,否则会因顺序不同或返回数量不同,导致错误。 如对List结果无法确定,推荐MappedBatchLoader实现,该方式通过key进行匹配,无需担心顺序与结果。

使用List形式如传入key为:[2, 9, 6, 1]

正确例子

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  [
     { id: 2, name: '张三' },
     { id: 9, name: '李四' },
     { id: 6, name: '王五' },
     { id: 1, name: '赵六' }
  ][
     { id: 2, name: '张三' },
     null,
     { id: 6, name: '王五' },
     { id: 1, name: '赵六' }
  ]

错误例子

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//传入key与结果数量不符,直接报错
  [
     { id: 2, name: '张三' },
     { id: 6, name: '王五' },
     { id: 1, name: '赵六' }
  ]

//传入key与结果顺序不同,会导致数据关联错误,如第一个2实际关联的是1
 [
    { id: 1, name: '赵六' },
    { id: 2, name: '张三' },
    { id: 6, name: '王五' },
    { id: 9, name: '李四' }
 ]

缓存

使用dataloader缓存尽量保证所查数据是无状态化,避免因状态数据实时要求高导致业务异常。

Dataloader中使用了两个缓存

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//结果缓存成功执行批处理后返回的CompletableFuture结果。
//如果你在设计中DataLoader是单例模式,该缓存因在内存常驻无法清除,会导致永远使用缓存数据,建议不使用CacheMap,只使用ValueCache
private final CacheMap<Object, V> futureCache;

//是批处理结果值的缓存,在执行批处理之前,会先在valueCache中查找,减少IO请求
private final ValueCache<K, V> valueCache;
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-08-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Python:轻量级 ORM 框架 peewee 用法详解
SQLite 中,当批量插入的行数超过 999 时,就需要使用循环来将数据批量分组:
丹枫无迹
2019/03/04
6K0
Spring Data JPA的使用及开启二级缓存
Hibernate 是一个广泛使用的 Java ORM(对象关系映射)框架,它提供了对关系型数据库的映射和操作功能,使开发者能够以面向对象的方式来处理数据库操作,而不用直接编写 SQL 语句。
码客说
2024/01/17
1.2K0
快速入门Flink (5) ——DataSet必知必会的16种Transformation操作(超详细!建议收藏!)
写在前面: 博主是一名大数据的初学者,昵称来源于《爱丽丝梦游仙境》中的Alice和自己的昵称。作为一名互联网小白,写博客一方面是为了记录自己的学习历程,一方面是希望能够帮助到很多和自己一样处于起步阶段的萌新。由于水平有限,博客中难免会有一些错误,有纰漏之处恳请各位大佬不吝赐教!个人小站:http://alices.ibilibili.xyz/ , 博客主页:https://alice.blog.csdn.net/ 尽管当前水平可能不及各位大佬,但我还是希望自己能够做得更好,因为一天的生活就是一生的缩影。
大数据梦想家
2021/01/27
1.2K1
快速入门Flink (5) ——DataSet必知必会的16种Transformation操作(超详细!建议收藏!)
Java8 Stream 中 Collectors 的24个操作
Collectors,可以说是Java8的最常用操作了,用来实现对队列的各种操作,包括:分组、聚合等,官方描述是:
用户4396583
2024/08/13
1210
Java一分钟之-GraphQL:查询语言与API设计
在现代Web开发中,GraphQL作为一种革命性的查询语言和API设计规范,正逐步改变我们构建和消费API的方式。它允许客户端精确请求所需的数据,从而减少了过载和冗余,提高了应用的性能和灵活性。本文将快速概述GraphQL的核心概念、Java开发者在实践中可能遇到的常见问题与易错点,并提供解决方案,辅以简洁的代码示例,助你在一分钟内掌握GraphQL的精髓。
Jimaks
2024/06/12
2870
MySQL员工打卡日志表——数据库练习
简单的员工打卡日志表的建表语句以及对应的测试数据。为了简单明了,我们将使用一个包含以下字段的表:
红目香薰
2024/01/14
2450
MySQL员工打卡日志表——数据库练习
java8 stream().map().collect()的Collectors.toList()、Collectors.toMap()、Collectors.groupingBy()的用法[通俗易
  现在需要将这些user的id提取出来。这个很简单,for循环嘛,谁不会啊(不会吧不会吧,不会有人还不会用for循环的吧)。
全栈程序员站长
2022/09/24
2.7K0
java8 stream().map().collect()的Collectors.toList()、Collectors.toMap()、Collectors.groupingBy()的用法[通俗易
大数据-Flink环境部署(Windows)及Flink编程
Flink有个UI界面,可以用于监控Flilnk的job运行状态 http://localhost:8081/
码客说
2022/10/04
1.5K0
大数据-Flink环境部署(Windows)及Flink编程
04-Spring5 JdbcTemplate
Spring框架对JDBC进行封装,使用JdbcTemplate方便实现对数据库操作
彼岸舞
2021/12/14
3960
04-Spring5 JdbcTemplate
HashMap的这个小“坑”;老司机也容易翻车
昨天一位粉丝朋友和我聊天,说遇到了一个莫名奇妙的问题,让我帮着分析一下;经过他的一轮描述,发现是一个HashMap元素顺序小'坑';但是一不留神,老司机也容易在这里翻车。
一行Java
2022/04/07
2530
HashMap的这个小“坑”;老司机也容易翻车
Mybatis foreach标签含义
这种方式非常方便,我们只要把查询条件写出来,剩下的操作都由mysql来处理。而在实际场景中,为了减少底层耦合,我们一般不通过mysql中的子查询方式联表查询,而是先执行子查询得到结果集,再以结果集作为条件执行外层查询。通常情况下,子查询和外层查询由上层的不同服务执行,这样就在一定程度上达到了底层数据库解耦的目的。注意这种实现方式将mysql内部的一部分复杂操作抛给了我们。这时,Mybatis中的foreach标签就有了用武之地。
xiaoxi666
2018/10/29
1.2K0
Java8 stream流之分组 groupingBy 的使用
众所周知,使用stream流可以让我们的代码看上去很简洁,现在我们实战使用一下stream的分组与分区。
全栈程序员站长
2022/09/23
4.3K0
04-Java8新特性 Stream API
Java8中有两大最为重要的改变,第一个是Lambda表达式,另一个则是Stream API(java.util.stream.*)
彼岸舞
2021/12/14
9460
04-Java8新特性 Stream API
java实现excel一万条数据批量导入
要实现Excel一万条数据批量导入,可以使用Apache POI库来读取和解析Excel文件,并使用JDBC连接数据库将数据批量插入。以下是一个简单的示例代码:
疯狂的KK
2023/03/23
1.7K0
Stream & JDK8新特性
我们日常SQL使用的时候,都是Group By实现分组。Stream也有类似功能,比如一个集合有3个组的员工,我们想获取每个组的员工,就可以通过.collect(Collectors.groupingBy(Obj::getXXX));实现。返回的集合是Map集合!
收心
2022/11/11
2560
Stream & JDK8新特性
C# 一分钟浅谈:GraphQL 优化与性能提升
GraphQL 是一种用于 API 的查询语言,它提供了一种更有效和强大的方式来获取数据。与传统的 REST API 不同,GraphQL 允许客户端精确地请求所需的数据,从而减少了不必要的数据传输。然而,随着 GraphQL 应用的复杂性增加,性能问题也逐渐显现。本文将从常见的性能问题入手,逐步探讨如何优化 GraphQL API。
Jimaks
2024/12/08
1740
C#一分钟浅谈:GraphQL 中的数据加载
随着Web技术的发展,GraphQL作为一种数据查询和操作语言,逐渐成为现代Web应用中不可或缺的一部分。它提供了更高效、灵活的数据获取方式,相比传统的REST API,能够显著减少网络请求次数和数据传输量。本文将从C#的角度出发,探讨GraphQL中的数据加载机制,包括常见的问题、易错点以及如何避免这些问题。
Jimaks
2024/12/11
1340
大数据ClickHouse(十四):Integration系列表引擎
ClickHouse提供了许多与外部系统集成的方法,包括一些表引擎。这些表引擎与其他类型的表引擎类似,可以用于将外部数据导入到ClickHouse中,或者在ClickHouse中直接操作外部数据源。
Lansonli
2022/08/30
7150
大数据ClickHouse(十四):Integration系列表引擎
Mysql排序后分页,因数据重复导致分页数据紊乱的问题
前不久在写一个分页接口的时候,在测试阶段出现了排序结果紊乱且数据不正确的问题,那个接口是按照create_time进行排序的,但是对应的表中有很多相同create_time的数据,最后发现是因为 order by 排序的时候,如果排序字段中有多行相同的列值,则排序结果是不确定的。
翎野君
2023/05/12
9390
Java : List<Map>中 根据map的某个key去重
初始数据:[{name=张三, id=1123}, {name=李四, id=2}, {name=王五, id=1123}, {name=赵六, id=3}] 去重之后:[{name=李四, id=2}, {name=赵六, id=3}, {name=张三, id=1123}]
执笔记忆的空白
2020/12/24
5.3K1
推荐阅读
相关推荐
Python:轻量级 ORM 框架 peewee 用法详解
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验