日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > 数据库 >内容正文

数据库

php mysql 秒杀_redis+PHP实现高并发下秒杀数据入库的问题

發(fā)布時(shí)間:2024/7/23 数据库 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 php mysql 秒杀_redis+PHP实现高并发下秒杀数据入库的问题 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

在高并發(fā)下實(shí)現(xiàn)搶購(gòu)秒殺功能中,我有一個(gè)疑問(wèn),就是數(shù)據(jù)入庫(kù)的問(wèn)題,什么時(shí)候入庫(kù)。

設(shè)想思路:

1.判斷他搶購(gòu)成功了,立馬把生成的訂單數(shù)據(jù)寫入mysql訂單表,同時(shí)庫(kù)存表字段減少1;

2.判斷搶購(gòu)成功后,把用戶的user_id存入到redis的list列表里(比如:order,以u(píng)ser_id為值的列表)。然后再用crontab定時(shí)去一個(gè)一個(gè)插入到mysql訂單表里,同時(shí)庫(kù)存表字段減少1。

設(shè)想結(jié)果:

第一種思路,很好理解。簡(jiǎn)單的代碼實(shí)現(xiàn)如下:

$num=10; //假設(shè)庫(kù)存量

for($i=0;$i

\Redis::lpush('goods_store',1);//往goods_store列表中,

未搶購(gòu)之前這里應(yīng)該是默認(rèn)push 10個(gè)1進(jìn)去,當(dāng)然里面的1沒有實(shí)際意義

在搶購(gòu)之前,上面的代碼可以先執(zhí)行,把商品入隊(duì)。

搶購(gòu)時(shí)間到了:(大量用戶請(qǐng)求下面代碼執(zhí)行操作)

/* 模擬搶購(gòu)操作,搶購(gòu)前判斷redis隊(duì)列庫(kù)存量 */

$count=\Redis::lpop('goods_store');//lpop是原子性的,可以保證不會(huì)出現(xiàn)超賣現(xiàn)象。

if(!$count)

return '已經(jīng)搶光了';

/* 下面處理?yè)屬?gòu)成功后與mysql數(shù)據(jù)庫(kù)的交互 */

1. //根據(jù)規(guī)則生成訂單號(hào)(order_num),然后把相關(guān)的字段數(shù)據(jù)插入到訂單列表里

$data['order_num'] = *****************;

$data['user_id'] = ***;

$data['goods_id'] = **;

.......

$res = DB::table('order')->insert($data);

2. //減少num庫(kù)存字段

if($res)

DB::table('goods')->decrement('num', 1);,

上面的代碼中,當(dāng)用戶搶購(gòu)成功后,立馬把相關(guān)的訂單數(shù)據(jù)插入mysql訂單表中,同時(shí)庫(kù)存減少。現(xiàn)在我的疑問(wèn)來(lái)了,要是用這種思路的話,大并發(fā)下,要是多個(gè)用戶都同時(shí)進(jìn)入到插入數(shù)據(jù)到訂單列表和減少商品庫(kù)存量這個(gè)過(guò)程中,是不是也會(huì)造成并發(fā)操作導(dǎo)致服務(wù)器壓力瞬間過(guò)大,導(dǎo)致數(shù)據(jù)入庫(kù)不正確呢,比如說(shuō)存庫(kù)少減了一個(gè)(還是說(shuō)根據(jù)mysql增刪改查的原子性,并不會(huì)造成這樣的錯(cuò)誤)?。

針對(duì)上面搶購(gòu)成功后,立馬把相關(guān)的訂單數(shù)據(jù)插入mysql訂單表中,同時(shí)庫(kù)存減少,造成的數(shù)據(jù)庫(kù)服務(wù)器壓力過(guò)大的問(wèn)題;

于是有了第二種思路,把用戶的user_id存入到redis列表里(比如:order,以u(píng)ser_id為值的列表),在通過(guò)定時(shí)器crontab定時(shí)去從列表里一個(gè)一個(gè)取出user_id,生成相關(guān)的數(shù)據(jù)插入到mysql訂單表里,同時(shí)庫(kù)存表字段減少1。

代碼實(shí)現(xiàn)跟上面差不多,

/* 模擬搶購(gòu)操作,搶購(gòu)前判斷redis隊(duì)列庫(kù)存量 */

$count=\Redis::lpop('goods_store');//lpop是原子性的,可以保證不會(huì)出現(xiàn)超賣現(xiàn)象。

if(!$count)

return '已經(jīng)搶光了';

/* 下面處理?yè)屬?gòu)成功后把user_id存入列表 */

\Redis::lpush('order',user_id);

通過(guò)定時(shí)器crontab定時(shí)去下面的代碼

$user_id = \Redis::rpop('order',user_id);

1. //根據(jù)規(guī)則生成訂單號(hào)(order_num),然后把相關(guān)的字段數(shù)據(jù)插入到訂單列表里

$data['order_num'] = *****************;

$data['user_id'] = $user_id;

$data['goods_id'] = **;

.......

$res = DB::table('order')->insert($data);

2. //減少num庫(kù)存字段

if($res)

DB::table('goods')->decrement('num', 1);,

第二種思路,我的疑問(wèn)是,要是搶購(gòu)成功后,先把user_id存入隊(duì)列,再用定時(shí)器每隔一段時(shí)間去隊(duì)列里取數(shù)據(jù),然后生成相關(guān)的數(shù)據(jù)插入的mysql訂單表里,同時(shí)減少庫(kù)存。這樣是可以減輕數(shù)據(jù)庫(kù)服務(wù)器的壓力了。但是我的搶購(gòu)流程是這么設(shè)計(jì)的,用戶搶購(gòu)成功后,彈出//去支付按鈕//進(jìn)入訂單列表頁(yè)面(訂單列表頁(yè)數(shù)據(jù)是從mysql讀取出來(lái)的),由于使用定時(shí)器去執(zhí)行生成訂單數(shù)據(jù)然后再插入到mysql數(shù)據(jù)庫(kù),這個(gè)過(guò)程肯定會(huì)有延遲,要是用戶此時(shí)通過(guò)//去支付按鈕//進(jìn)入訂單列表頁(yè)面,發(fā)現(xiàn)訂單列表還沒有生成訂單數(shù)據(jù),那不是很悲催嗎?

【這樣設(shè)計(jì)搶購(gòu)流程是否合理,是不是不用進(jìn)入到訂單列表,直接點(diǎn)擊去支付,支付成功后,才生成訂單數(shù)據(jù)插入到數(shù)據(jù)庫(kù)呢】

以上就是我對(duì)兩種思路存在的疑惑,希望可以得到專業(yè)人士的講解,或者一起探討。

總結(jié)

以上是生活随笔為你收集整理的php mysql 秒杀_redis+PHP实现高并发下秒杀数据入库的问题的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。