Coding 應當是一輩子的事業,而不只僅是 30 歲的青春🍚
本文已收錄 Github https://github.com/ponkans/F2E,歡迎 Star,持續更新💧前端
這篇 Node.js 的文章接水怪很用心,也很硬核,相信能看完的都有點東西!!!node
每篇文章都但願你能收穫到東西,這篇根據搶口罩的實際場景出發,逐層對一個 Node 高併發的系統進行分析,其中 Node 服務層會講的詳細一些,但願你看完,可以有這些收穫:mysql
真的打心底對那些在一線的工做人員點贊,接水怪的父親目前仍在一線湖北提供生活物資的運輸,我想說,爸,你真的很棒,怪怪爲您感到自豪與驕傲! nginx
想搶個口罩怎麼就這麼難!接水怪大學以前是湖北的,想給湖北的朋友搶個口罩快遞過去,結果顯而易見,沒有搶到…git
因而,接水怪痛定思痛,下定決心對口罩秒殺系統架構一探究竟,雖然業界大部分的這種場景應該都是基於 Java 實現的,可是怪怪我決定嘗試從 Node.js 的方向,配合業界一些成熟的中間件來分析一下整個系統的架構,以及一些常見的問題。程序員
關於 Node.js 如何實現高併發的原理,怪怪往期的文章有寫哈。github
寫以前跟好兄弟丙丙也請教了很多後端側的東西,對,就是大家熟悉的那個男人,號稱本身在互聯網苟且偷生的那個敖丙!面試
怪怪在這裏將先後端一併分享給你們,畢竟 Node 的生態環境日益加強,前端側能作的東西也愈來愈多。redis
好比你想在公司本身作一個基於 Node 的前端發佈系統,也會涉及到 db,緩存,消息中間件這些東西。sql
接下來,讓咱們請出今天的主角兒,噹噹噹當~~ 它就是低調奢華有內涵的口罩秒殺系統架構圖,後面的內容會基於這個架構圖來擺會兒龍門陣。
擺龍門陣,怪怪方言,也就是怪怪想跟你們聊會兒天的意思啦~)
秒殺,秒殺,顧名思義就是一個短期內的高流量操做,是一個自然高併發的場景,換句話說,讀寫衝突十分嚴重。
而一般秒殺類型的業務,價格都比較誘人,這就引起了另一個薅羊毛的問題,有很多黃牛會在這個時候趁機撈一筆,想必每一年春節回家,你們都深有感觸吧,還沒來得及輸完 12306 的高智商驗證碼,票已經沒有了,哦豁~~
"哦豁",怪怪的方言,很無奈,很驚訝的意思
試想幾十萬,上百萬的流量直接打到 DB?
世界忽然安靜,不得再也不一次發出熟悉的感慨,哦豁~
所以,秒殺的核心就在於請求是真實請求的前提下,處理好高併發以及數據庫存扣減的問題。
接下來,就讓咱們逐層來看看是怎麼作的~
針對流量特別大的場景,能夠分時分段開展活動,原來統一 10 點搶口罩,如今 6 點,6 點半,7 點,…每隔半個小時進行一次活動,達到流量攤勻的效果。
APP / H5 / 小程序 / PC
前端側會進行一個按鈕置灰的操做,當你點擊完一次以後,按鈕會變灰,防止用戶重複提交搶口罩的請求。
想必你必定會說,這還不簡單?抓個包,寫個定時腳本,一到時間,for 循環自動打請求不就行了?
我只能說,小夥子,你很優秀,有的場景確實是闊以滴,可是你別慌,接着往下看↓↓↓
彆着急,剛剛就是讓你皮一下,哦豁~
針對上面這種狀況,後端 controller 層會進行處理,簡單來講就是對同一個用戶搶口罩的請求進行校驗,對於同一個用戶在短期內發送的大量請求進行次數限制,以及請求去重處理~
但怪怪我諮詢了風控的朋友,如今企業中大部分場景,後端是不作這個特殊處理,而是讓風控團隊來處理,下面所謂黑客的部分會稍微細說一下。
道高一尺,魔高一丈,接下來請出咱們的終極大魔王,高端 Hacker!!
好比一些高端 Hacker,控制了 30w 個 Dorking,也就是這些人手上有 30w 的 uid,若是他們同時發動手上 30w 的 Dorking 來搶口罩,咋辦?
此時,再一次陷入了尷尬~ 哦豁~~
這個問題,怪怪我諮詢了安全、以及風控的朋友,簡單跟你們分享一下
首先,安全針對秒殺,沒作啥特殊的處理。
通常來說,秒殺類工做主要在風控這邊,對於那種利用機器或者腳本瘋狂刷新的,QPS 異常高的,換句話說就是短期內流量異常高滴的用戶,會直接給他彈一個滑塊(滑動驗證,應該你們都遇到過這種狀況),這樣能夠大大提升那些刷請求批量操做的成本,甚至可以遏制他們的行爲。
同時風控也會根據一系列的規則(經過這些規則來斷定這個 uid 也就是這個用戶是否符合要求,不要問我具體規則,怪怪我還想繼續寫文章,不想進去~~),對於那些不符合平臺下單要求的 Dorking ,直接進行請求攔截,甚至有的會加入黑名單,直接取消掉這個用戶的相關權限。
寫到這裏,我想說,風控、安全團隊,大家仍是有點東西!!
實際上真正的企業架構中,在 Nginx 的上面一層還會有一層 lvs ,這裏不展開講,簡單解釋就是可以在網絡第 4 層對 Nginx 服務的 ip 進行負載均衡
雖然上面咱們攔截了惡意請求,減小了部分流量,但秒殺真實的用戶也超多的啊,你想一想此次有多少人在搶口罩!
因此咱們咱們仍是要搞負載均衡~~
咱們先簡單解釋一下集羣跟負載均衡是個什麼玩意兒,哦豁~
集羣嘛,簡單來說就是咱們不是有秒殺的 Node 服務嘛,那一臺機器是否是有可能會掛掉,流量太大,單臺機器根本扛不住,咋辦?
加機器唄,一臺會被打掛,那咱們多搞幾臺,不就變強啦?俗話說,1 根牙籤一碰就斷,10 根牙籤…… 咦,好像也是一碰就斷,hhhh,哦豁~
那負載均衡是嘛玩意兒嘛?剛上面不是說了集羣就是加機器嘛,那如今機器雖然變多了,來了一個請求,具體派哪一個機器去處理,是否是得有一套規則嘛,而且這套規則要讓請求分發的比較合理,否則就失去了集羣的意義了撒~
Nginx 層下面是基於 Node 的 service 層,也就是業務邏輯會在這裏進行處理,實際上 Nginx 在這裏主要作了兩件事:
這一層我會說的細一些,讓咱們挨個來擺下龍門陣吧~~
想必你們都知道服務模型是經歷了 4 個階段滴,同步、複製進程、多線程、以及事件驅動。
不清楚的同窗須要補補做業啦~
多線程目前業界以 Java 爲首,性能啥的就不說了,各類雙十一已經證實這位兄臺是個狠人。
可是,怪怪我以爲,雖然多線程之間能夠共享數據,內存能夠充分利用,而且利用線程池能夠較少建立和銷燬線程,節省開銷。可是,仍是存在一些問題,好比:
那能不能讓咱們人見人愛滴小闊愛,Node 小朋友,來嘗試搞一下?
Node 是基於事件驅動模型滴,相信前端同窗都知道事件驅動,後端同窗可能有點懵,可是做爲後端同窗,Node 你沒搞過,Nginx 你總用過哈,Node 跟 Nginx 都是基於事件驅動模型滴~
而且,Node 是單線程,採用單線程能夠避免沒必要要的內存開銷,以及上下文切換。
跟多線程 Java 比起來,好像 Node 也有本身的優點呢~
我知道,已經有很多同窗火燒眉毛要接着問我了,尤爲是後端同窗內心確定在想,你 TM 逗我呢,你一個單線程還能來搞高併發,多核 CPU 怎麼利用?
畢竟隔行如隔山,後端大佬對咱們 Node 有誤解,也是情有可原,就跟不少前端以爲 Java 用類型檢測是很麻煩的,不如咱們 JS 靈活,是一個道理~
若是咱們 Node 解決了多核 CPU 的資源利用問題,再加上 Node 異步非阻塞的特性,帶來的性能上的提高應該是很不錯滴,而且也沒有複雜的多線程啊,加鎖這一類心累的問題。
關於 Node 單線程如何實現高併發,能夠查看往期文章哦💖
咱們順着架構圖,一步步來分析~
先看這裏,說好的單進程,單線程呢,這是個什麼鬼?
彆着急,這是 Node 進程模型中著名滴 Master-Worker 模式哦~
還不是由於單線程,沒法利用多核 CPU 嘛,咱們的小闊愛 Node 提供了 child_process 模塊,或者說 cluster 模塊也行,能夠利用 child_process 模塊直接建立子進程。
說到這裏, HTML5 提出的 Web Worker ,方式大同小異,解決了 JavaScript 主線程與 UI 渲染線程互斥,所引起的長時間執行 JavaScript 致使 UI 停頓不響應的問題。
cluster 模塊:實際上就是 child_process 模塊跟其它模塊的組合
另外申明一點:fork 線程開銷是比較大的,要謹慎使用,而且咱們 fork 進程是爲了利用 CPU 資源,跟高併發沒啥大關係
這樣看來,多核 CPU 的資源利用問題,好像獲得瞭解決,雖然看起來方式稍顯粗暴~
咱們再次迴歸到上面的主、子進程的架構圖,接着談談主進程與子進程通訊的問題,如今一個口罩秒殺請求過來了,Node 主進程,子進程這裏是怎麼進行處理的呢?
想必你們都知道 IPC,也就是進程間通訊,首先要申明的是實現 IPC 的方式不止一種,好比共享內存啊、信號量啊等等~~
而 Node 是基於管道技術實現滴,管道是啥?
在 Node 中管道只是屬於抽象層面的一個叫法而已,具體的實現都扔給一個叫 libuv 的傢伙去搞啦~以前的文章有講到 Node 的 3 層架構,libuv 是在最下層滴哦,而且你們都知道 Node 能夠跨平臺嘛,libuv 會針對不一樣的平臺,採用不一樣的方式實現進程間的通訊。
ok,咱們上面大體說完了理論部分,是否是要實戰一把了?
一把大叉叉什麼鬼?說明經過代理請求轉發這種方式是不太友好滴~
那咱們具體分析一下,爲何不友好,怎麼改進?
首先咱們須要明確一點,操做系統有一個叫文件描述符的東西,這個涉及到操做系統內核的一些小知識點,而且操做系統的文件描述符是有限的,維護起來也是須要成本滴,所以不能鋪張浪費~
那咱們分析一下上面的流程,這些口罩請求打到主進程上面,主進程對這些請求進行代理,轉發到不一樣端口的子進程上,看起來一切都那麼美好~
而且在主進程這裏,咱們還能夠繼續進行一層負載均衡,讓每一個子進程的任務更加合理。
but,but,接下來是重點!!
前面咱們說啦,操做系統的文件描述符不能鋪張浪費,咱們來看看這個代理的方式,有沒有浪費~
首先,須要明確一點。進程每收到一個鏈接,就會用到一個文件操做符,因此呢?來,怪怪給你整個當字開頭的排比句!
當客戶端鏈接到主進程的時候,用掉一個操做符~
當主進程鏈接到子進程,又用掉一個~
因此嘛,從數量上來看,代理方案浪費掉了整整一倍,這好像不太科學,囊個搞內?
怪怪那兒的方言,「囊個搞」,就是怎麼辦的意思咯~~
魔高一尺,道高一丈~
Node 在 v0.5.9 引入了進程間發送句柄的機制,簡單解釋一下,句柄實際上就是一種能夠用來標識資源的引用。
經過句柄傳遞,咱們就能夠去掉代理這種方案。使主進程收到客戶端的請求以後,將這個請求直接發送給工做進程,而不是從新與子進程之間創建新的鏈接來轉發數據。
但實際上這一塊還涉及到不少知識點,好比句柄的發送與還原啊,端口的共同監聽啊等系列問題。
這一塊的具體實現,能夠參考 《深刻淺出 Node.js 》9.2.3 句柄傳遞
最終,經過句柄傳遞就能夠獲得咱們想要的效果,即不通過代理,子進程直接響應了客戶端的請求。
怪怪我也去研究了一下 Egg.js 在多進程模型和進程間通訊這塊是怎麼作滴,大致架構思路跟上面差很少,不一樣的點在於, Egg.js 搞了一個叫 Agent 的東西。
對於一些後臺運行的重複邏輯,Egg.js 將它們放到了一個單獨的進程上去執行,這個進程就叫 Agent Worker,簡稱 Agent,專門用來處理一些公共事務,具體細節能夠參考 Egg.js 官網。
畢竟是秒殺服務,fork 的子進程是可能掛滴,因此咱們須要一種機制來保證子進程的高可用。
我知道,你確定會說,掛了,重啓一個繼續提供服務不就行了?
對,你說的沒錯,咱們就先來搞定重啓這一趴~
假如如今某個子進程發生異常啦,哦豁~
那麼,此時這個子進程會當即中止接受新的請求鏈接,直到全部鏈接斷開,當這個子進程退出的時候主進程會監聽到一個 exit() 事件,而後主進程重啓一個子進程來進行補償。
也就是這樣一個流程。
小夥子,你很不錯,可是極端狀況咱們是否是也要考慮一會兒?
假若有一天,出現極端狀況,你全部的女友一晚上之間都要跟你分手,是否是開始慌了?(壞笑~~)
若是全部的子進程同時異常了,按照咱們上面的處理方式,全部的子進程都中止接收新的請求,整個服務豈不是就會出現瞬時癱瘓的現象了?大部分的新請求就會白白丟掉,想一想若是是雙十一,損失得有多大,哦豁~
既然如此,咱們就來改進一下。
有的小夥伴可能會說,我知道怎麼搞了!!!
既然不能一直等待着,那就直接強行 kill 幹掉這個進程,而後立馬重啓一個!!
小夥子,你有點激動,不過能夠理解,畢竟能想到這裏,你仍是有點東西~~ 不過能夠更加全面一點
強行 kill 掉,會致使已鏈接的用戶直接中斷,那用戶也就天然離開啦~ 哦豁~
因此,總結起來咱們要解決的就是,如何在不丟失現有用戶請求的基礎上,重啓新的子進程,從而保證業務跟系統的雙重高可用!!!
突然靈光一現,咱們能夠這樣搞撒~
上面分析到主進程要等到子進程退出的時候,纔會去重啓新的子進程,這就有點意思啦!! 同志,不要等到分手了再去反思本身哪裏作的不對!!! ,只要女友一輩子氣,即便響應,立馬認錯,沒毛病~~~
所以,咱們能夠在子進程剛出異常的時候,就給主進程發一個自殺信號,主進程收到信號後,當即建立新的子進程,這樣上面的問題完美解決!!
今後跟女友過上了幸福美好滴生活~
搞定了上述秒殺服務 Node 主進程,子進程高可用的問題以後,咱們就能夠搭建 Node 集羣了,進一步提升整個系統的高可用,Node 集羣的負載均衡,文章一開始的 Nginx 層已經講過啦~
至於集羣作多大,用多少臺機器,這些須要根據具體的業務場景來決策。而且通常大型的活動上線以前,企業內部會進行幾輪壓測,簡單來說,就是模擬用戶高併發的流量請求,而後看一下小夥子你搞的這個系統抗不扛得住,靠不靠譜~
但真正的壓測,遠比我說的要複雜,好比壓測中某個環節出了問題,扛不住啦,是直接重啓機器,仍是擴容,又或者是下降處理等等,這都是須要綜合考慮滴~
固然,最終的目的也是在保證服務高可用的前提下能給企業節約成本,畢竟加機器擴容是須要成本滴~
一樣的需求,別人要 5 臺機器,你只要 4 臺就能搞定,小夥子,那你就真的有點東西啦,升職加薪指日可待!!~
搞定了上面 Node 服務的各個環節以後,還有一個很重要的問題要解決,我丟!!! 咋還有問題~~
首先,明確一個知識點,Node 多個進程之間是不容許共享數據滴~
這就是最後一個很是重要的問題,數據共享。
實際業務中,就拿咱們今天的口罩系統來講,庫存量就是一個典型數據共享的場景,會有多個進程須要知道如今還有多少庫存,不解決好這個問題,就頗有可能發生口罩超賣的問題。
超賣,簡單來說就是,怪怪家一共有 200 只口罩等待出售,而後怪怪我在某平臺上發起了一個秒殺搶口罩的活動,因爲平臺的數據沒處理好,怪怪我在後臺驚喜的收到了 500 個訂單,超出了 300 個訂單,這就是超賣現象啦~
那這個問題,咱們應該如何避免呢,怪怪我有點心累,買個口罩怎麼這麼複雜!
既然 Node 自己不支持數據共享,ok,那咱們就用三方的嘛,好比今天的第二個主角~ 噹噹噹當~~ 它就是一位名叫 Redis 的神祕女子,身穿紅色外套,看着還有點內斂~
至於 Redis 這裏如何保持數據一致,放到下面 Redis 的部分一塊兒說。
咱們使用 Redis 解決上述遺留的 Node 進程間數據不能共享的問題。
解決問題以前,先簡單介紹一下 Redis ,畢竟,都不認識,怎麼開始戀愛?
Redis 仍是有不少知識點滴,具體可查看 Redis 官網
相信你們在大學的時候都接觸過 SQL Server ,相信你也曾經由於 SQL Server 那詭異的環境曾頭痛~
但大部分學校,應該都是沒有 Redis 這門課滴,若是有,怪怪我只能說,朋友,你的學校有點東西!!
步入正題,Redis 是一個在內存中進行數據結構存儲的系統,能夠用做數據庫、緩存和消息中間件,是 key-value 的形式來進行數據的讀寫。簡單理解就是,咱們能夠利用 Redis 加緩存減輕 db 的壓力,提高用戶讀寫的速度。
你們要明確的是,秒殺的本質就是對庫存的搶奪,若是每一個從上層 Node 服務打過來的請求,都直接去 db 進行處理,
拋開最大的性能問題先不說,你不以爲這樣好繁瑣,對開發人員以及後期的維護都很不友好嘛?
上面已經說啦,直接搞到 MySQL 扛不住,你能夠找她閨蜜 Redis 嘛,寫一個定時腳本,在秒殺還未開始以前,就把當前口罩的庫存數量寫入 Redis,讓 Node 服務的請求從 Redis 這裏拿數據進行處理,而後異步的往 kafka 消息隊列裏面寫入搶到口罩用戶的訂單信息(這一塊具體的放到後面 kafka 消息隊列部分分析)。
那這裏就關聯上了咱們前面提到的問題,數據一致性問題,如何保證 Node 服務從你 Redis 拿到的庫存量是沒有問題滴?
若是直接按正常的邏輯去寫,搶到口罩,Redis 中庫存 count -1,這種方式看起來是沒有問題滴,可是咱們來思考這樣一個場景。
好比倉庫裏面還有最後 1 個口罩,如今光頭強發了一個請求過來,讀了一下 Redis 的數據,count 爲 1,而後點擊下單,count - 1 。但若是此時 count 正在執行 -1 的操做的時候(此時 count 依然是 1 ),熊大哥哥一看這形式不對,也開始搶口罩,一個查庫存量的請求再一次打了過來,發現 Redis 中庫存量仍然爲 1 ,而後點擊下單。
按上述的流程,就會發生文章一開頭提到的超賣現象,1 只口罩,你給我下了兩個單?!!!
咱們能夠加事務嘛!!
事務能夠一次執行多個命令,而且有兩個很重要的特性~
這裏直接引用 Redis 的官方示例來解決超賣問題,官方示例講的是執行 +1 的操做,咱們這裏只須要修改爲 -1 就 ok。具體可參考官方文檔。
這樣一來,Node 數據共享,庫存減叩的問題就搞定了,Redis 小姐姐,你有點東西!!~
那若是單臺 Redis 扛不住怎麼辦,咱們能夠對 Redis 進行集羣嘛,主從同步這一系列的操做,而後再搞點哨兵,持久化也搞上,那你這個秒殺直接無敵!!!
後續有時間,會寫一個基於 Node.js 的 Redis 實戰與原理剖析😁,以前怪怪寫過一個可視化頁面搭建系統,其中各個模塊在後臺進行渲染的時候,爲了提升渲染速度,就用到了 Redis 進行高速緩存。
緩存這一趴告一段落,下面接着說說消息隊列~
若是將訂單數據一次性所有寫入 db,性能很差,因此會先往消息隊列裏面存一下,固然消息隊列不只僅是起到了這個做用,像什麼應用的解耦,也能夠基於 kafka 來作一層封裝處理。
先簡單說一下消息隊列,不光秒殺,其它場景的使用大同小異。
kafka 消息隊列就是基於生產者-消設計模式滴,按具體場景與規則,針對上層請求讓生產者往隊列的末尾添加數據,讓多個消費者從隊列裏面依次讀取數據而後自行處理。
結合到咱們的秒殺場景就是,對訂單進行分組存儲管理,而後讓多個消費者來進行消費,也就是把訂單信息寫入 db。
這裏附上一張經典的消息隊列的圖,有興趣的小夥伴能夠深刻去了解 kafka,仍是有點東西。
數據庫這塊很少說,數據存儲的地方,最終的訂單信息會寫到 MySQL 中進行持久化存儲。
簡單模擬這個系統的話,表結構就搞到最簡化就行。
CREATE TABLE IF NOT EXISTS `seckill`(
`id` INT UNSIGNED AUTO_INCREMENT,
`date` TIMESTAMP,
`stock` INT UNSIGNED,
PRIMARY KEY ( `id` )
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
複製代碼
深刻學習 MySQL,仍是有些東西滴,查詢優化啊,索引怎麼用啊,底層數據結構啊,怎麼去設計表啊等等一些列問題均可以去探究~
相信前段時間搞的沸沸揚揚滴刪庫跑路事件,你們也都據說了~~
順便提一嘴,不少小夥伴說,我想搞一下前端工程化,我想搞幾個減小開發流程的系統,我想…
就舉個很簡單的例子,企業都有線下、預發、線上這一套環境,你想開發一款 host 切換工具來切各個不一樣的環境,兩種方式:
怪怪以前是維護咱們公司的這個 host 小工具滴,後面計劃本身寫一套開源出來。
什麼,這麼個破玩意兒你還要開源?
舉上面的例子,就是想說,Node 生態愈來愈好,咱們前端能作的事情也愈來愈多,咱們有義務去接觸更多的東西,尋找更多前端的突破口~
狼叔那一篇在 cnode 社區置頂的文章,就寫的很是贊!!~~~
可以看到這裏,說明你有點東西,整個系統的各個層都講了一下,我估計如今讓你本身來搞一個秒殺系統,也問題不大了~
怪怪我基於文章開頭的架構圖,本身搞了一個低配版的 Node 秒殺系統,在這裏把踩過的一些小坑跟你們分享一下,畢竟踩過的坑,不但願你們踩第二次!
首先,若是你們本身在本地搞這個系統,可能乍一看,又有 Node,又有 Nginx,又有 Redis ,又有 kafka,並且管理 kafka 還要用 zookeeper,感受這也太麻煩了,可能看到這個環境搭建都望而卻步了~。
淡定,淡定!!
咱們能夠用 docker 來搞嘛,這樣就很輕量而且很方便管理,沒用過的小夥伴強烈建議去學習一下~
使用 docker 來搞,上面說的幾個環境,一個配置文件就搞定,簡單示意一下:
services:
zk:
image: wurstmeister/zookeeper
ports:
- "2181:2181"
kfk:
image: wurstmeister/kafka
ports:
- "9092:9092"
environment:
KAFKA_ADVERTISED_HOST_NAME: 172.17.36.250
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
volumes:
- ./docker.sock:/var/run/docker.sock
redis:
image: redis
ports:
- "6379:6379"
mysql:
image: mysql
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: 'password'
複製代碼
用 docker 搭建環境,避免本身去裝那些沒必要要的環境,好比 MySQL。
使用 Docker Compose 定義和運行多容器的 Docker 應用程序,便於容器的集中配置管理。
刪除 Docker 容器,容器裏面的數據仍是會在你物理機上面,除非你手動去清理。
kafka-node 這個 npm 包,最新的版本用法相比老版本有一些更新,好比老版本建立一個 kafkaClient 的寫法是 new kafka.Client(); 但新版本如今已是 new kafka.KafkaClient(); 這種寫法了
kafka 的 docker 鏡像,官方提供的 docker-compose 示例未指定端口映射關係,須要自行處理一下映射關係
Egg.js 首次在鏈接 MySQL 的 docker 容器的時候,會出現 Client does not support authentication protocol requested by server; 的異常,修改一下密碼就 ok。
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'your_new_password';
FLUSH PRIVILEGES;
複製代碼
萬一機器不夠,只能放棄部分請求,原則上仍是要已保護系統爲核心,否則全部的請求都失敗,就更不理想
那就給用戶及時反饋說下單失敗,讓用戶重試,都已經搶到口罩了,從新下個單應該問題不大的,再者,這是少數狀況~
首先,搶到口罩以後,支付界面會有一個支付的時間提醒,例如,超過 20 分鐘未支出,這筆訂單將被取消。關聯到數據庫裏就會有一個未支出的狀態。若是超過期間,庫存將會從新恢復。
前端側也會給到用戶對應的提示,好比 20 分鐘以後再試試看,說不定又有口罩了喲~
本文已收錄 Github https://github.com/ponkans/F2E,歡迎 Star,持續更新💧
怪怪上面寫的也不全,真正的企業實戰,整個鏈路會複雜不少,環環相扣。好比 Node 服務的監控報警啊,各類異常處理啊等等~~
後續會對這篇秒殺中的知識點進行拆分深刻探究,好比進程,線程這塊從最基本概念到最底層內核的一些知識都會來跟你們分享。
近期會針對 Node.js 寫一個系列,同系列傳送門:
喜歡的小夥伴加個關注,點個贊哦,感恩💕😊
微信搜索【接水怪】或掃描下面二維碼回覆」加羣「,我會拉你進技術交流羣。講真的,在這個羣,哪怕您不說話,光看聊天記錄也是一種成長。(阿里技術專家、敖丙做者、Java3y、蘑菇街資深前端、螞蟻金服安全專家、各路大牛都在)。
接水怪也會按期原創,按期跟小夥伴進行經驗交流或幫忙看簡歷。加關注,不迷路,有機會一塊兒跑個步🏃 ↓↓↓