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