例如,Iphone的1元秒杀,如果我只放出1台Iphone,我们把它看成一条记录,秒杀开始后,谁先抢到(更新这条记录的锁),谁就算秒杀成功。
例如:
这种方法的弊端:
等待是非常不科学的,因为对于没有获得锁的用户,等待是在浪费时间。
所以一般的优化处理方法是先使用for update nowait的方式来避免等待,即如果无法即可获得锁,那么就不等待。
但是这种方法也存在一定的弊端,对于一个商品,如果可以秒杀多台的话,我们用1条记录来存储多台,降低了秒杀的并发性。
因为我们用的是行锁。
解决这个问题办法很多,最终就是要提高并发性,例如:
1. 分段秒杀,把商品数量打散,拆成多个段,从而提高并发处理能力。
总体来说,优化的思路是减少锁等待时间,避免串行,尽量并行。
Postgresql还提供了一个锁类型,advisory锁,这种锁比行锁更加轻量,支持会话级别和事务级别。(但是需要注意ID是全局的,否则会相互干扰,也就是说,所有参与秒杀或者需要用到advisory lock的ID需要在单个库内保持全局唯一)
例子:
update tbl set xxx=xxxupd_cnt+1 where idpk and upd_cnt1<=5pg_try_advisory_xact_lock(:id);
最后必须要对比一下for update nowait和advisory lock的性能。
下面是在一台本地虚拟机上的测试。
新建一张秒杀表
postgres=# \d t1Table "public.t1"Column | Type | Modifiers--------+---------+-----------id | integer | not nullinfo | text |Indexes:"t1_pkey" PRIMARY KEY,btree (id)
只有一条记录,不断的被更新
# select * from t1;
id | info
----+-------------------------------
1 | 2015-09-14 09:47:04.703904+08
(1 row)