淘宝双11秒杀在哪个位置 秒懂:淘宝0点0分0秒抢购攻略

Hi,大家好,美好的一天从这里开始,今天主要讲解淘宝双11秒杀在哪个位置,淘宝0点0分0秒抢购攻略,以及淘宝双11秒杀的一系列相关干货,其实这篇文章主要还是为新手朋友整理的,总的来说思路还是很重要!

其实对于交易平台来说,面对的不仅仅是人肉,还有很多脚本,外挂自动化的抢购系统,压力可想而知。

秒杀的优化手段很多,就拿数据库来说,有用排队机制的,有用异步消息的,有用交易合并的。

今天,我要给大家介绍一种更极端的秒杀应对方法,裸秒。

(其实我很久以前就写过类似的文章,趁双十一跟大伙再练练)

目前可能只有PostgreSQL支持裸秒,也即是说,来吧,强暴我吧,一起上。 有点淫荡,但是确实就是这么暴力。

PostgreSQL提供了一种ad lock,可以让用户尽情的释放激情,以一台32核64线程的机器为例,每秒可以获取、探测约130万次的ad lock。

试想一下,对单条记录的秒杀操作,达到了单机100万/s的处理能力后,秒杀算什么?100台机器就能处理1亿/s的秒杀请求,不行我的小心脏受不了了,下面听我娓娓道来。

秒杀场景简介

虽然秒杀已经很普遍了,但是出于文章的完整性,还是简单介绍一下秒杀的业务背景。

例如,Iphone的1元秒杀,如果我只放出1台Iphone,我们把它看成一条记录,秒杀开始后,谁先抢到(更新这条记录的锁),谁就算秒杀成功。

对数据库来说,秒杀瓶颈在于并发的对同一条记录的多次更新请求,只有一个或者少量请求是成功的,其他请求是以失败或更新不到记录而告终。

例如有100台IPHONE参与秒杀,并发来抢的用户有100万,对于数据库来说,最小粒度的为行锁,当有一个用户在更新这条记录时,其他的999999个用户是在等待中度过的,以此类推。

除了那100个幸运儿,其他的用户的等待都是无谓的,甚至它们不应该到数据库中来浪费资源。

传统的做法,使用一个标记位来表示这条记录是否已经被更新,或者记录更新的次数(几台Iphone)。

update tbl set xxx=xxx,upd_cnt=upd_cnt+1 where id=pk and upd_cnt+1<=5; — 假设可以秒杀5台

这种方法的弊端:

获得锁的用户在处理这条记录时,可能成功,也可能失败,或者可能需要很长时间,(例如数据库响应慢)在它结束事务前,其他会话只能等着。

等待是非常不科学的,因为对于没有获得锁的用户,等待是在浪费时间。

常用的秒杀优化手段

1. 一般的优化处理方法是先使用for update nowait的方式来避免等待,即如果无法即可获得锁,那么就不等待。

begin;select
1 from tbl where id=pk for update nowait; —
如果用户无法即刻获得锁,则返回错误。从而这个事务回滚。update tbl set xxx=xxx,upd_cnt=upd_cnt+1
where id=pk and upd_cnt+1<=5;end;

这种方法可以减少用户的等待时间,因为无法即刻获得锁后就直接返回了。

2. 合并请求,即将多个更新合并到一个更新的请求,这种做法需要修改内核,同时会破坏ACID,因为如果合并后的请求失败了,会导致合并中的所有人的请求失败。(与分组提交不一样,分组提交是不会破坏ACID的)。

那么接下来我们看看AD LOCK。

什么是ad lock

手册中的说明,AD LOCK是一种面向用户的轻量级锁,锁的目标是一个整型,分为事务级和会话级的锁,以及共享和排他锁。

在单个DB内,只要锁的整型值不一样,就可以获得锁,如果值一样,可以使用TRY来加锁,没有获得则立即返回FALSE。

https://www.postgresql.org/docs/current/static/functions-admin.html#FUNCTIONS-ADVISORY-LOCKS

Table 9-87. Advisory Lock Functions

Name Return Type Description
pg_advisory_lock(key bigint) void Obtain exclusive session level advisory lock
pg_advisory_lock(key1 int, key2 int) void Obtain exclusive session level advisory lock
pg_advisory_lock_shared(key bigint) void Obtain shared session level advisory lock
pg_advisory_lock_shared(key1 int, key2 int) void Obtain shared session level advisory lock
pg_advisory_unlock(key bigint) boolean Release an exclusive session level advisory lock
pg_advisory_unlock(key1 int, key2 int) boolean Release an exclusive session level advisory lock
pg_advisory_unlock_all() void Release all session level advisory locks held by the current session
pg_advisory_unlock_shared(key bigint) boolean Release a shared session level advisory lock
pg_advisory_unlock_shared(key1 int, key2 int) boolean Release a shared session level advisory lock
pg_advisory_xact_lock(key bigint) void Obtain exclusive transaction level advisory lock
pg_advisory_xact_lock(key1 int, key2 int) void Obtain exclusive transaction level advisory lock
pg_advisory_xact_lock_shared(key bigint) void Obtain shared transaction level advisory lock
pg_advisory_xact_lock_shared(key1 int, key2 int) void Obtain shared transaction level advisory lock
pg_try_advisory_lock(key bigint) boolean Obtain exclusive session level advisory lock if available
pg_try_advisory_lock(key1 int, key2 int) boolean Obtain exclusive session level advisory lock if available
pg_try_advisory_lock_shared(key bigint) boolean Obtain shared session level advisory lock if available
pg_try_advisory_lock_shared(key1 int, key2 int) boolean Obtain shared session level advisory lock if available
pg_try_advisory_xact_lock(key bigint) boolean Obtain exclusive transaction level advisory lock if available
pg_try_advisory_xact_lock(key1 int, key2 int) boolean Obtain exclusive transaction level advisory lock if available
pg_try_advisory_xact_lock_shared(key bigint) boolean Obtain shared transaction level advisory lock if available
pg_try_advisory_xact_lock_shared(key1 int, key2 int) boolean Obtain shared transaction level advisory lock if available

通常数据库支持的最小粒度的锁(指开放给用户的)是行锁,行锁相比LWLOCK,SPINLOCK等是非常重的,所以传统的行锁在秒杀中会成为非常大的瓶颈,包括锁的等待。

ad lock的用途

ad lock的用途,除了我接下来要说的秒杀,其实还有很多用途,例如

并发的安全性检查,

递归调用中用于UPSERT的场景,

业务逻辑设计中用来确保原子操作等。

ad lock的性能指标

因为AD LOCK很轻量化,不需要访问数据,不需要执行冗长的代码,所以很高效。

32核64线程机器测试可以达到131万次/s的锁请求。

vi test.sql

\set id random(1,100000000)

select pg_try_advisory_xact_lock(:id);

pgbench -M prepared -n -r -P 1 -f ./test.sql -c 96 -j 96 -T 100transaction type: ./test.sql

scaling
factor: 1query mode: preparednumber of clients: 96number of threads:
96duration: 100 snumber of transactions actually processed:
131516823latency average = 0.072 ms

latency stddev = 0.070 ms

tps = 1314529.211060 (including connections establishing)

tps = 1315395.309707 (excluding connections establishing)script statistics:

– statement latencies in milliseconds: 0.001 \set id random(1,100000000) 0.074 select pg_try_advisory_xact_lock(:id);

ad lock用于秒杀的例子

在数据库中,商品通常有唯一ID,我们可以对这个ID加锁,(当然,如果对不同的表这个ID有重叠的可能,我们可以加偏移量或者其他的手段来达到无冲突)。

加锁成功才会去对行加锁,执行更新,这样就能规避掉无效的行锁等待,以及冗长的查询代码。

使用 AD LOCK 对单条记录的并发更新处理QPS可以达到39.1万/s,被秒杀的商品很快就会变成售罄状态,不会再浪费数据库的资源。

create table test(id int primary key, crt_time timestamp);insert into test values (1);vi test.sql

update test set crt_time=now() where id=1 and pg_try_advisory_xact_lock(1);

pgbench -M prepared -n -r -P 1 -f ./test.sql -c 64 -j 64 -T 100transaction type: ./test.sql

scaling
factor: 1query mode: preparednumber of clients: 64number of threads:
64duration: 100 snumber of transactions actually processed:
39104368latency average = 0.163 ms

latency stddev = 0.216 ms

tps = 391012.743072 (including connections establishing)

tps = 391175.983419 (excluding connections establishing)script statistics:

– statement latencies in milliseconds: 0.163 update test set crt_time=now() where id=1 and pg_try_advisory_xact_lock(1);

此时数据库主机还有66.2%的空闲CPU资源可用使用。

top
– 13:12:43 up 51 days, 18:41, 2 users, load average: 1.12, 0.97,
0.78Tasks: 1463 total, 28 running, 1435 sleeping, 0 stopped, 0
zombieCpu(s): 24.5%us, 9.3%sy, 0.0%ni, 66.2%id, 0.0%wa, 0.0%hi, 0.0%si,
0.0%stMem: 529321832k total, 235226420k used, 294095412k free, 903076k
buffersSwap: 0k total, 0k used, 0k free, 62067636k cached

对比传统的例子

传统的消除等待的做法是这样的,通过select for update nowait。

begin;select
1 from tbl where id=pk for update nowait; —
如果用户无法即刻获得锁,则返回错误。从而这个事务回滚。update tbl set xxx=xxx,upd_cnt=upd_cnt+1
where id=pk and upd_cnt+1<=5;end;

在PG中,可以使用do语句,把以上合成到一个块里面操作。

使用传统的方法,每秒可以处理8.6万。

vi
test.sqldo language plpgsql $$ declare begin with t as (select * from
test where id=1 for update nowait) update test set crt_time=now() from t
where t.id=test.id; exception when others then return; end; $$;

pgbench -M prepared -n -r -P 1 -f ./test.sql -c 64 -j 64 -T 100

transaction type: ./test.sql

scaling factor: 1

query mode: prepared

number of clients: 64

number of threads: 64

duration: 100 s

number of transactions actually processed: 8591222

latency average = 0.744 ms

latency stddev = 0.713 ms

tps = 85888.823884 (including connections establishing)

tps = 85924.666940 (excluding connections establishing)

script statistics:

– statement latencies in milliseconds:

0.744 do language plpgsql $$ declare begin with t as (select * from
test where id=1 for update nowait) update test set crt_time=now() from t
where t.id=test.id; exception when others then return; end; $$;

CPU剩余54.5%

top
– 13:13:48 up 51 days, 18:42, 2 users, load average: 8.14, 2.69,
1.37Tasks: 1464 total, 21 running, 1442 sleeping, 0 stopped, 1
zombieCpu(s): 41.7%us, 3.8%sy, 0.0%ni, 54.5%id, 0.0%wa, 0.0%hi, 0.0%si,
0.0%stMem: 529321832k total, 235256052k used, 294065780k free, 903176k
buffersSwap: 0k total, 0k used, 0k free, 62068308k cached

ad lock相比其他秒杀优化的优势

淘宝双11秒杀在哪个位置,淘宝0点0分0秒抢购攻略,淘宝双11秒杀

使用AD LOCK可以使得CPU开销最小化,等待最小化,从本文的测试CASE来看,单条记录的更新可以达到39.1万/s。

传统的手段只能达到8.6万/s。

使用AD LOCK不破坏ACID,单个请求单个事务,不影响其他的事务。

合并优化,本质上是破坏了ACID的,如果合并失败,会导致所有相关的请求失败。

这篇文章的所有内容到这里就完了,希望能帮助到你们,看完了淘宝双11秒杀在哪个位置「秒懂:淘宝0点0分0秒抢购攻略」,收获很多,欢迎帮忙分享一下。我在这边先谢谢各位了哈!

本文发布者:百事通,不代表巢座耶立场,转载请注明出处:https://www.chaozuoye.com/p/7742.html

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 jubao226688#126.com 举报,一经查实,本站将立刻删除。

(0)
上一篇 2023年5月30日 15:31
下一篇 2023年5月31日 08:49

相关推荐

  • 正规兼职做什么挣钱「推荐网上兼职赚钱正规平台」

    Hi,大家好,美好的一天从这里开始,今天主要讲解正规兼职做什么挣钱,网上兼职赚钱正规平台,以及关于兼职做什么挣钱这些一系列的精品相关干货,认认真真阅读完,若能把我想表达的全部理解,相信你已经离大牛不远了哈! 主要问题的话是因为我儿子一直都是跟着我们长大的,而我们也很少回老家去,也就过年的时候回去一下,因此我儿子是根本不会跟别人,无论怎么哄都是一样,只要我们不…

    百科 2023年2月13日
  • 帮做服装朋友在朋友圈宣传语 推荐朋友圈创意广告文案推荐

    最近有很多朋友问陈向宇关于帮做服装朋友在朋友圈宣传语,朋友圈创意广告文案推荐的事情,还有帮朋友在朋友圈宣传语相关的各种内容,如果你是老司机,你可能觉得很简单,但如果你是新手,你可能就不这么想了。 1、请保持那一份热爱 ,奔赴下一场山海。 2、以为是乏味的城市,却遇见彩色的梦和许多美好。 3、云朵偷喝了我放在屋顶的酒 ,于是它脸红变成了晚霞。 4、 做个少女,…

    2023年11月4日 百科
  • 咸鱼网官网二手买东西靠谱吗 附:咸鱼常见骗局大揭秘

    很高兴又和大家见面了,今天尤乃涓来和大家聊一聊咸鱼网官网二手买东西靠谱吗,咸鱼常见骗局大揭秘,以及咸鱼网官网二手相关的事项,认认真真阅读完,若能把我想表达的全部理解,相信你已经离大牛不远了哈! 前互联网产品经理,现二手数码店主,拥有七八年的玩机(翻车)经验,熟知各路骗局,这里给各位整理出一份闲鱼防骗指南,读完此篇,小白变大神,保你大战奸商不翻车,无任何广告,…

    2024年1月11日 百科
  • 阿里众包兼职怎么做 详细介绍:十大正规兼职平台

    小伙伴们大家好,今天吴荣超给大家分析下关于阿里众包兼职怎么做,十大正规兼职平台的事情,以及关于阿里众包等等各种相关干货,想要做好首先一定要把基本功练好了,否者是很难持续提升的。 你听说开某宝店铺能赚钱,噌噌的又过去了,这次钱到没到手我不知道,但学费肯定是交了。 你听说新型微商能赚钱,噌噌的赶紧去当代理,私欲流量什么的各种概念懂了一堆,但到头来钱不仅没赚到,各…

    2023年5月22日
  • 手机现在有哪些网游能挣钱 必看:手机打金传奇哪个靠谱

    小伙伴们大家好,今天李亘宇抽了个时间整理了一些关于手机现在有哪些网游能挣钱,手机打金传奇哪个靠谱,以及关于手机有哪些网游能挣钱这些一系列的精品相关干货,其实这篇文章主要还是为新手朋友整理的,总的来说思路还是很重要! 如果在有限时间边玩游戏还能赚到钱,为大家介绍这几款几款游戏【小蟹说话原创,有不懂可以留言问我,知必回】。 游戏 注:今年很多游戏官方都严打非法脚…

    2023年6月1日 百科
  • 直播带货的货源哪里找 新手必看:新手主播入门必看教程

    很高兴又和大家见面了,今天秦意来和大家聊一聊直播带货的货源哪里找,新手主播入门必看教程,还有关于货源哪里找等等其他相关干货,希望你认真看完这篇文章后,能充分理解我想表达的意思。相信你很快就能掌握!你离大牛越来越近了! 随着今年直播带货的兴起,现在有直播带货想法的人很多,但是苦于找不到货源或者找到好的货源迟迟不能付之行动。 关于货源,刚开始会碰到几点难题,怕批…

    2024年5月5日 百科