Java并发查询到同一表以进行电子邮件处理

时间:2019-06-30 22:37:34

标签: java spring spring-boot spring-data-jpa

我有一个用作电子邮件队列的mysql表-存放需要发送的所有记录。我正在尝试使用多个线程执行每个电子邮件的发送。每个线程都必须对此电子邮件队列表进行查询,以获取一组记录,然后将其发送并从表中删除。您如何确定每个线程将从表中获取哪些记录?从那里,您如何管理这些并发查询?我正在将Java Spring Boot与Hibernate结合使用。

1 个答案:

答案 0 :(得分:0)

我会想像下面的事情。这是使用数据库中一行的ID完成的。如果您的ID差距很大,则不是一个很好的解决方案。您可以将其重构为使用某些日期列或任何其他有助于批量记录的数据。

10-线程数

i-我们正在迭代的当前线程数

10000-批量,用于获取10000封电子邮件

counter-变量,该变量知道哪个线程应该负责哪个id批处理

maximumEmailId-电子邮件表中电子邮件的最大ID

1. Create 10 numbered threads - 0, 1, 2..., 9
2. Start every thread
3. For each thread number (i):
4. For counter = 0, step 10000
5. if (counter / 10000) % 10 == i then
- SELECT * FROM emails WHERE id BETWEEN (counter) AND (counter + 10000)
- Send emails
6. if counter > maximumEmailId then break;

它的行为如下:

iteration 0:
  -thread 0 - counter = 0 - select ... where id between 0 and 10000
  -thread 1 - counter = 10000 - select ... where id between 10000 and 20000
  -thread 9 - counter = 90000 - select ... where id between 90000 and 100000

iteration 1:
  -thread 0 - counter = 100000 - select ... where id between 100000 and 11000
  -thread 1 - counter = 110000 - select ... where id between 110000 and 12000
  -thread 9 - counter = 190000 - select ... where id between 190000 and 20000

基本上,此解决方案与锁定,技术性并发技巧等无关,您只需要划分数据集即可,因此没有人尝试读取同一批数据。想象一下,在地面上有100个盒子,线程0取有编号0, 10, 20,...,90的盒子,线程1盒子1, 11, 21,...,91等等。