【发布时间】:2018-01-13 10:47:13
【问题描述】:
我们正在尝试速率限制总数的方案。一个月内请求的 JSON 记录数达到 10000 个 API。 我们根据 client_id 和 Timestamp(这是主键)将记录的总数存储在表中。 根据请求,我们从该客户的表中获取该月带有时间戳的记录。 从这条记录中我们得到当前计数,然后将其增加为 no。请求中的当前记录并更新数据库。
使用Spring Transaction,伪代码如下
@Transactional(propagation=Propagation.REQUIRES_NEW, isolation=Isolation.REPEATABLE_READ)
public void updateLimitData(String clientId, currentRecordCount) {
//step 1
startOfMonthTimestamp = getStartOfMonth();
endOfMonthTimestamp = getEndOfMonth();
//step 2
//read from DB
latestLimitDetails = fetchFromDB(startOfMonthTimestamp, endOfMonthTimestamp, clientId);
latestLimitDetails.count + currentRecordCount;
//step 3
saveToDB(latestLimitDetails)
}
我们希望确保在多个线程访问“updateLimitData()”方法的情况下,每个线程都会获取一个月内某个 clientId 的更新数据,并且不会错误地覆盖计数。 在上述场景中,如果多个线程访问方法“updateLimitData()”并到达“步骤 3”。第一个线程将更新 DB 中的“count”,然后第二个线程更新 DB 中可能没有最新计数的“count”。
我从 Isolation.REPEATABLE_READ 了解到,仅在“第 3 步”调用更新时,“写锁”被放置在行中(到那时其他线程将拥有陈旧的数据)。在多线程场景中,我如何确保始终线程从表中获取最新计数。
我想到的一个解决方案是同步这个块,但这在多服务器场景中效果不佳。
请提供解决方案。
【问题讨论】:
-
如果我们使用不同级别的隔离,如“REPEATABLE_READ”和“SERIALIZABLE”,则仅在更新时放置锁定。是否选择语句也会导致行锁定。
标签: spring multithreading transactional transaction-isolation