聊一下MySQL
關于mysql關系型資料庫的一些分析:
1、從性能上:如果我們碰到需要執行耗時特別久,并且執行結果不是很頻繁變動的SQL陳述句,我們就沒有必要每次都去查詢資料庫,因為每次操作資料庫都很耗時,
2、從并發上:在大并發的情況下(比如618秒殺活動,你敢讓千萬級的請求直接打到資料庫上嗎?)所有的請求直接訪問資料庫,資料庫就由可能造成宕機,
Redis
針對第一種情況,可以將不那么頻繁變換的結果放入基于快取的資料庫中,每次查詢就去快取中讀資料,這樣就提升了查詢效率,也減輕了資料庫的壓力,
針對第二種情況,可以讓這些高并發的請求從資料庫中分離出來,不去直接訪問資料庫,另外找一個適合高并發的來處理請求,
那就是Redis!!!
是什么?
- 基于記憶體的K/V存盤中間件(關于K/V你還能想到誰?)
- NoSQL(非關系型)資料庫
干啥用?
- 快取
(將熱點資料放到記憶體中,設定記憶體的最大使用量以及淘汰策略來保證快取的命中率)
- 設定定時過期資料
- 分布式鎖
(在分布式場景下,無法使用單機環境下的鎖來對多個節點上的行程進行同步,可以使用 Redis 自帶的 SETNX 命令實作分布式鎖)
- 抽獎功能
- 實作排行榜
- .......
面試題:1、redis常見的資料結構有哪些?
2、Redis持久化了解么?
秒殺場景
618預熱早已開啟,其中必不可少的秒殺是一個非常典型的活動場景,比如,在雙 11、618 等電商促銷活動中,都會有秒殺場景,秒殺場景的業務特點是限時限量,業務系統要處理瞬時的大量高并發請求,在秒殺活動中,大量用戶在同一時間視窗內搶購限量商品,這往往會給系統帶來極高的并發壓力,使用傳統的關系型資料庫來處理并發請求往往會導致性能瓶頸和系統崩潰,而Redis作為一種高性能的記憶體資料庫,能夠快速處理大量的讀寫請求,非常適合用于秒殺場景,
秒殺的特征一:瞬時并發訪問量非常高,一般資料庫只能支撐千級別的并發請求,而redis的并發處理能力能達到萬級別,甚至更高,在秒殺時,我們需要使用redis攔截大部分請求,避免大量請求直接發送給資料庫,造成資料庫宕機,
秒殺的特征二:讀多寫少,都是簡單的查詢操作,對于簡單的查詢操作并且結果相對固定我們可以先將其查詢出來放入redis中,減輕資料庫的壓力,秒殺活動中只有少部分用戶能成功下單,所以,商品庫存查詢操作(讀操作)要遠多于庫存扣減和下單操作(寫操作),
秒殺的特征三:實時性和回應時間要求, 秒殺活動通常是實時進行的,用戶希望盡快得知搶購結果,系統需要具備高性能和低延遲,及時回應用戶的請求,
三個階段
秒殺前
秒殺前,用戶會不斷的重繪商品詳情頁,那么就會導致對詳情頁的請求量急劇增加,這個階段的應對方案,一般是盡量把商品詳情頁的頁面元素靜態化,然后使用 CDN 或是瀏覽器把這些靜態化的元素快取起來,這樣一來,秒殺前的大量請求可以直接由 CDN 或是瀏覽器快取服務,不會到達服務器端了,
秒殺時
用戶點擊秒殺按鈕---->大量并發請求查詢庫存--->有庫存(下單){沒有則回傳,可能會點擊其他秒殺按鈕,繼續查詢庫存}--->庫存扣減---->生成實際訂單---->后續處理(物流、訂單支付等)
這個階段的操作是:庫存查驗、庫存扣減、訂單處理,而最大的并發力都在庫存查驗操作上,這個階段為了支撐大量高并發的庫存查驗請求,我們需要在這個環節使用 Redis 保存庫存量,這樣一來,請求可以直接從 Redis 中讀取庫存并進行查驗,
為什么訂單處理操作可以在資料庫中執行?而庫存扣減操作不能在資料庫中執行?
1、在資料庫中進行庫存扣減操作會帶來額外的開銷,我們已經事先在redis中保存好了庫存量,如果交給資料庫來處理扣減,那么就需要資料庫將最新的值再同步到redis中,這樣反而繁瑣也帶來了額外的開銷,
2、可能會出現超售的情況,資料庫的處理速度很慢,而秒殺又是一個快速高并發的場景,可能資料庫更新完一個庫值,秒殺就結束了,可能會導致用戶查詢到舊的庫存值,再進行下單,出現超售的情況,
所以需要在redis中把庫存扣減和庫存查驗兩個操作一氣呵成,實作原子操作,
秒殺后
用戶量減少,服務器完全可以獨立進行訂單處理等操作,
實作
我們可以使用Redis的原子操作和分布式鎖來支撐秒殺時的場景,(本文介紹分布式鎖)
簡單聊聊分布式
簡單理解:類比衛生間的隔間:
- 隔離性: 衛生間的隔間將每個使用者隔離開來,使每個人都能獨立使用空間,不會相互干擾,同樣,分布式系統中的各個節點也是相互隔離的,它們可以獨立運行,不會相互影響,
- 資源共享: 衛生間的隔間提供共享的基礎設施,如水源和排水管道等,類似地,分布式系統中的節點可以共享一些資源,如共享存盤、共享資料庫等,
- 容錯性: 如果一個衛生間隔間出現故障或需要維護,其他隔間仍然可以繼續使用,同樣,分布式系統中的節點之間可以具備容錯能力,如果某個節點發生故障,其他節點可以接替其作業,
- 擴展性: 如果需要更多的衛生間隔間,可以增加更多的隔間來滿足需求,同樣,分布式系統可以通過增加更多的節點來實作擴展性,以處理更大的負載和流量,
Redis分布式鎖(秒殺場景)
先讓客戶端向 Redis 申請分布式鎖,只有拿到鎖的客戶端才能執行庫存查驗和庫存扣減,這樣一來,大量的秒殺請求就會在爭奪分布式鎖時被過濾掉,而且,庫存查驗和扣減也不用使用原子操作了,因為多個并發客戶端只有一個客戶端能夠拿到鎖,已經保證了客戶端并發訪問的互斥性,大部分秒殺請求本身就會因為搶不到鎖而被攔截,
為啥要實作分布式鎖:
- 在有限的資源情況下,控制同一時間(段)只有某些執行緒(用戶/服務器)能訪問到資源,(比如秒殺時)
- 單個鎖只對單個jvm有限(好比用廁所只能用專屬于自己的哪個)
關鍵:怎么保證同一時間內只有一個服務器搶到鎖,
核心思想是:先來的人先把資料改成自己的標識(ip)后來的人發現標識已存在,就搶鎖失敗,繼續等待,等先來的人執行方法結束,把標識清空,其他的人繼續搶鎖,(類比搶廁所/上廁所 )
注意事項:
- 要注意解鎖(你不可能一直占著廁所吧!!!),
- 一定要注意加上過期時間(否則如果因為服務器掛掉,鎖就會一直存在了),
使用分布式鎖可能存在的問題
1、鎖提前過期:分布式鎖設定的時間提前過期,會導致其他方法加入一塊同時執行,(好比你拉*沒拉完,外面大哥把廁所門給撬開了)導致多個方法同時執行了,
2、還有可能導致連鎖效應(解鎖時不小心釋放掉別人的鎖)同樣導致多個方法同時執行,
3、解鎖的時候,判斷好了是自己的鎖,但是當要執行解鎖的時候,就在這個時刻,自己的鎖過期了(不需要刪了)有其他的方法見縫插針進來了,導致A刪了B的鎖,(就像是你用完廁所,你自己的門鎖時間過期開了,你手里還有把解鎖的“鑰匙”,結果你打開了旁邊大哥的門)這里其實是破壞了原子性,(需要保證A的操作是原子性的,不能有其他操作打斷,(也就是說A的上鎖和解鎖中間不能有其他的鎖操作)跟作業系統的PV操作好像),
4、鎖提前過期,任務還沒執行完,可以進行續期,(就像你上廁所,外面大哥等了你10min,結果你還沒完事,然后你跟大哥說再給我10min)進行續期,
關于redis在秒殺場景中的應用還有很多,這只是一丟丟~
場景題
1、如何防止超賣問題?
2、如何保證訂單的順序和可靠性?
3、如何解決重復下單的問題?
4、做了什么限流削峰的措施?
5、如果快取中的資料突然失效,導致請求全部打到了資料庫,怎么辦?
6、秒殺系統面臨的問題有哪些?
........
博客參考
實踐篇(11)Redis支撐秒殺場景的關鍵技術
知識星球
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/553742.html
標籤:其他
上一篇:< Python全景系列-8 > Python超薄感知,超強保護:例外處理的絕佳實踐
下一篇:返回列表