16 条回复  ·  1846 次点击
ShawyerPeng 楼主 初学 2025-7-28 19:48:01
@zpfhbyx 我们需要保证是近实时的分析,由于逻辑复杂(比如需要实现超时机制,一个人中间一直没有作业的休息间隔超过 20 分钟则需要终止这段作业时长统计;还需要有不同作业类型切换的顶替机制;还有时长跨天拆分机制,把原来的一条数据库记录一拆为二,保证单据绑定正确日期的工时)很难放到离线 HSQL 中实现正确的统计逻辑。
ShawyerPeng 楼主 初学 2025-7-28 19:56:53
@crysislinux 感觉好像要解决的问题不太一样?我是想在高并发场景解决:来了一个值 c ,如果它在[a, b]窗口范围内,没拿到锁,则不允许更新滑动窗口的左区间或者右区间(如果 c < a 则更新为[c, b],如果 c > b 则更新为[a, c])。 因为我要防止并发更新,所以要锁住这个窗口范围。
emmmbu 初学 2025-7-28 20:15:35
锁数据库那一行 id 不就得了,只允许一个线程拿到锁,然后查询并且更新 end_time
YangQingLin 初学 2025-7-28 20:37:32
我在想,是否可以利用数据库自身的锁来解决。把时间比大小推到数据库更新的时候计算,比如下面这样: ```sql UPDATE work_sessions SET start_time = LEAST(start_time, :new_biz_time), -- LEAST 是 SQL 函数,取最小值 end_time = GREATEST(end_time, :new_biz_time) -- GREATEST 是 SQL 函数,取最大值 WHERE user_id = :user_id AND date = :date; ``` 利用数据库本身的原子性来更新时间范围,是不是也能达到想要的结果? 对于休息间隔重新计算,我觉得可以增加一个缓存层,每次来新的 biz_time 先和缓存中的内容进行判断,超过 20 分钟或者跨天的话就使用 insert 新开一条记录。 如果上面这种方式也不合适的话,我觉得也可以从时间排序方面入手,你希望保证的是“近实时”的分析,那我这里假设分析结果可以延迟 1 分钟更新,那么使用一个以 biz_time 作为 key 的小顶堆的数据结构接收那些并发的请求,然后只有当堆顶的 biz_time 与当前相差超过 1 分钟之后才会取数据更新入库,这样可以把一分钟之内的数据乱序问题抹除。然后同样将时间戳大小对比丢给数据库更新的时候计算,不知道这样是否能满足你的需求。
ShawyerPeng 楼主 初学 2025-7-28 20:46:22
@emmmbu select for update 在高并发场景下性能很差吧
emmmbu 初学 2025-7-28 21:17:30
@ShawyerPeng #14 如果高并发锁竞争很激烈,那我觉得最好用队列,跟你说的这个范围锁还是怎么锁都无法解决
z1829909 小成 2025-7-28 22:18:17
感觉方案上有些问题,加锁更复杂而且 io 变多。 不如直接所有改动都扔队列,然后消费的地方攒一批数据做合并,然后写入更新,这样 io 也会降低。
12
返回顶部