标签:time res create user creat img 化学 lse 场景
下面是秒杀系统的架构:
CDN:主要存储一些静态内容,比如静态页面,例如商场上的秒杀商品页面;秒杀未开始的时候回挡住一些流量,避免访问后台;
Nginx:主要做后台流量的负载均衡
redis:后端服务的缓存,主要缓存秒杀接口;
db:存储我们的秒杀商品;秒杀单等信息;
主要的优化点:(主要是减少网络延迟和和行级锁的等待时间)
1、将秒杀接口放在redis中,避免频繁访问数据库;
2、数据库操作的优化,一个是秒杀单的insert操作,一个是秒杀商品库存的update操作;
2.1 对于数据库操作insert和update,要讲insert放在前面执行,这样可以直接屏蔽掉一些重复秒杀的操作,比如同一个seckillid + user_phone的数据多次插入就会导致插入失败,这时失败的操作就直接返回,不走下面的逻辑;
2.2 减少锁的等待时间;由于操作比较简单,一个insrert一个udate,可以使用存储过程实现,这样只有一次数据库访问,并且相关的逻辑判断和执行都在mysql本地执行,大大提升了执行时间;
这里的场景是所有参与当前商品秒杀的用户秒杀过程中都会去跟新当前商品的库存信息,当前正在更新的用户就会开启行级锁,锁住此商品,只有update操作commit或者rollback才会释放锁,这里就是要减少锁的持有时间,让当前操作尽快结束;
存储过程语句:
delimiter $$
create proceduer sakila.seckill(
in v_seckill_id bigint,
in v_phone,
in v_seckill_time,
out o_result int)
begin
declare isnert_count int default 0;
start transaction;
insert ignore into success_killed(id, phone, time) values(v_seckill_id, v_phone, v_seckill_time);
select row_count() into isnert_count;
if (isnert_count = 0) then -- 插入操作未修改任何数据
rollback;
set o_result = -1; -- 重复秒杀
elseif (isnert_count < 0) then
rollback;
set o_result = -2; -- 执行出错;
else
update seckill set number = number - 1
where seckill_id = v_seckill_id and end_time > v_seckill_time and start_time < v_seckill_time and number > 0
select row_count() into isnert_count;
if (isnert_count = 0) then -- 插入操作未修改任何数据
rollback;
set o_result = -1; -- 重复秒杀
elseif (isnert_count < 0) then
rollback;
set o_result = -2; -- 执行出错;
else
commit;
set o_result = 1; -- 秒杀成功
end if;
end if;
end;
$$
delimiter ;
标签:time res create user creat img 化学 lse 场景
原文地址:https://www.cnblogs.com/fpsfzy/p/13670106.html