抢购、秒杀是如今很常见的一个应用场景,主要需要解决的问题有两个:
1 高并发对数据库产生的压力
2 竞争状态下如何解决库存的正确减少(”超卖”问题)
对于第一个问题,已经很容易想到用缓存来处理抢购,避免直接操作数据库,例如使用Redis。
重点在于第二个问题
常规写法:
查询出对应商品的库存,看是否大于0,然后执行生成订单等操作,但是在判断库存是否大于0处,如果在高并发下就会有问题,导致库存量出现负数
[php] view plain copy
[php] view plain copy
– 数据库: big
–
– 表的结构 ih_goods
CREATE TABLE IF NOT EXISTS ih_goods
(
goods_id
int(10) unsigned NOT NULL AUTO_INCREMENT,
cat_id
int(11) NOT NULL,
goods_name
varchar(255) NOT NULL,
PRIMARY KEY (goods_id
)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ;
–
– 转存表中的数据 ih_goods
INSERT INTO ih_goods
(goods_id
, cat_id
, goods_name
) VALUES
(1, 0, ‘小米手机’);
–
– 表的结构 ih_log
CREATE TABLE IF NOT EXISTS ih_log
(
id
int(11) NOT NULL AUTO_INCREMENT,
event
varchar(255) NOT NULL,
type
tinyint(4) NOT NULL DEFAULT ‘0’,
addtime
timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id
)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
–
– 转存表中的数据 ih_log
–
– 表的结构 ih_order
CREATE TABLE IF NOT EXISTS ih_order
(
id
int(11) NOT NULL AUTO_INCREMENT,
order_sn
char(32) NOT NULL,
user_id
int(11) NOT NULL,
status
int(11) NOT NULL DEFAULT ‘0’,
goods_id
int(11) NOT NULL DEFAULT ‘0’,
sku_id
int(11) NOT NULL DEFAULT ‘0’,
price
float NOT NULL,
addtime
timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id
)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT=’订单表’ AUTO_INCREMENT=1 ;
–
– 转存表中的数据 ih_order
–
– 表的结构 ih_store
CREATE TABLE IF NOT EXISTS ih_store
(
id
int(11) NOT NULL AUTO_INCREMENT,
goods_id
int(11) NOT NULL,
sku_id
int(10) unsigned NOT NULL DEFAULT ‘0’,
number
int(10) NOT NULL DEFAULT ‘0’,
freez
int(11) NOT NULL DEFAULT ‘0’ COMMENT ‘虚拟库存’,
PRIMARY KEY (id
)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT=’库存’ AUTO_INCREMENT=2 ;
–
– 转存表中的数据 ih_store
INSERT INTO ih_store
(id
, goods_id
, sku_id
, number
, freez
) VALUES
(1, 1, 11, 500, 0);