如何正确处理大批量数据的业务

2023-02-09 09:13:26 +08:00
 ak1ak

Hello, all!

数据库中有一大批待处理的数据,可能有百万量级,还会增长。希望定义一个接口,请求之后查询并处理好这些数据。 处理的逻辑可能涉及 RPC 之类耗时较长的代码。因此,我使用异步代码处理。伪代码如下:

// 1.查询数据库
List<Biz> bizs = queryDB();
// 2.分批次
List<List<Biz>> bizLists = Lists.partition(bizs, 1000);
// 3.异步处理 list
bizLists.forEach(list -> listAsyncService.handle(list));
// 4.listAsyncService#handle 也是异步处理
list.forEach(biz -> asyncService.handle(biz));

请教一下,上述代码是否合理。在数据量很大的情况下,如何避免步骤 1 出现 OOM 。

1927 次点击
所在节点    程序员
11 条回复
tairan2006
2023-02-09 09:21:52 +08:00
你这个应该用 rabbitmq 之类的做异步,长时间运行的流程靠开线程异步不靠谱,除非调用方能容忍失败。

如果害怕第一步 OOM ,那你直接在第一步分页查数据库不就完了…
ak1ak
2023-02-09 09:25:09 +08:00
在主键为 id 的情况下,每次查询记录 min(id),并针对 min(id) 分页只处理部份数据,如 10000 条。SQL 这样写:

```sql
select * from tb_biz where id > (select min(id) from tb_biz where 查询条件) and 查询条件 limit 10000
```

这样的话,就需要多请求几次接口。
ak1ak
2023-02-09 09:29:16 +08:00
@tairan2006 这个业务的场景是处理一些历史数据,接口是提供给内部人员调用的。希望尽可能一次性处理比较多的数据,调用者不乐意传分页参数,只希望分页逻辑在后台做掉。
NoString
2023-02-09 09:45:58 +08:00
调用者不传你自己加分页,写个方法
queryMinLimitData(Long minId,int limitCount)
嫌慢多线程调这个方法
imokkkk
2023-02-09 09:59:46 +08:00
1 查完之后推给 MQ ,2 从 MQ 拉取到数据后再分成小批次交给线程池多线程去处理
5boy
2023-02-09 10:10:08 +08:00
楼上回复分页查的一看就是菜鸟。分页查完汇总不还是这么多数据吗?数据又不会少,还是会 oom
wangxin3
2023-02-09 10:18:26 +08:00
就是分页查询 然后发送到 MQ ,查一批发一批,内存占用转移到 MQ 中去,然后多开消费者按需消费 MQ 的数据。
zzzzz001
2023-02-09 10:55:05 +08:00
简单点,在表里面加个同步字段,每次同步了就更新这条数据,你每次用 limit 1000 取 1000 条未同步的,无限循环下去,当没有返回就终止循环
zzzzz001
2023-02-09 11:01:37 +08:00
@zzzzz001 这种方式我玩了很多次了
beneo
2023-02-09 11:05:04 +08:00
spring batch
Juszoe
2023-02-09 11:09:02 +08:00
使用数据流中间件
我没用过,不负责任推荐 https://github.com/mage-ai/mage-ai

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/914452

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX