库存Repostiory连带事务的解决方案

10-05-05 Foxswily
项目开发中遇到了类似论坛评论的问题

需求是维护产品的库存可用数量(需要经过计算,如库存数-预订数等等),在销售时改变库存数,考虑缓存的解决方案,

论坛评论解决方案:初次调用时缓存,以后都从缓存读写

库存解决方案:在销售时更新库存数,同时有其他的事务处理,如创建销售单,通知下一级人员处理等等。此处与论坛评论不同,更新库存是事务的一部分,有rollback的情况要处理,而缓存没有这样的能力...

请教此时该如何设计呢?

         

1
banq
2010-05-05 11:42
2010年05月05日 11:26 "Foxswily"的内容
更新库存是事务的一部分,有rollback的情况要处理,而缓存没有这样的能力 ...

缓存就是内存,不是说内存没有这个能力,可以使用语言锁等机制;你可以在更新数据库库存事务中,同时更新缓存中库存数据,你要把缓存看成是数据库的影子,shadow即可。

Foxswily
2010-05-05 12:51
纠结的地方在于,数据库事务在提交之前,其他的线程是看不到变化的,而缓存一旦变更,在这个时点其他读线程是可以访问的,这就造成了不同步。

比如:

当前库存:100

新销售:10

事务过程

开始事务

更新库存(此时是缓存)

数据库插入销售记录

其他事务处理

提交事务

可能的情况

1.数据库更新成功,缓存更新成功——OK

2.数据库更新失败,缓存需要rollback——至少需要对缓存额外的处理

3.缓存更新失败,数据库rollback——OK

以上各种情况都存在瞬间的数据不同步。

语言锁机制能很好的解决这个问题吗?可以想到的是对缓存的读写设置锁机制。但缓存更新后、提交前这段时间的状态呢?需要缓存提供事务机制?

icycrystal4
2010-05-05 13:33
既然使用缓存, 那么就应当保证缓存的数据是最新的, 通过异步来更新数据库.

涉及到事务时, 可以利用锁机制:

如果是单JVM简单的线程同步即可,

如果是多JVM/分布式, 那就需要在JVM级别同步(这个机制貌似比较复杂), 也可以参考CAP/BASE, 只需要eventual cosistence即可

另外, 数据库事务保证了在没有错误的时候才提交事务, 那缓存机制也可以在没有异常的时候才更新缓存, 所以说rollback与否与缓存没有什么直接的关系.

--菜鸟级回复

[该贴被icycrystal4于2010-05-05 13:37修改过]

banq
2010-05-05 13:41
2010年05月05日 12:51 "Foxswily"的内容
数据库更新成功,缓存更新成功——OK

2.数据库更新失败,缓存需要rollback——至少需要对缓存额外的处理

3.缓存更新失败,数据库rollback——OK

以上各种情况都存在瞬间的数据不同步。 ...

其实这是一致性问题,一般缓存也就是内存更新不会失败,写内存有失败过吗?除非掉电或硬件质量不好,这就要容错性failover来实现,一般是没有必要的。

第2种和第3种发生的可能性是极其低的,为了再降低这个概率,你在启动数据库写事务之前,清除缓存,不是更新缓存,事务结束后,由第一个访问这个数据的请求从数据库获得,然后再放到缓存中。

当然,这有脏读发生,也就是你写事务进行中,有读发生,可以通过数据库的ACID来实现。

总之,你一致性要求越高,可用性,也就是性能可能越差。

猜你喜欢
4Go 1 2 3 4 下一页