天天看點

【七天深入MySQL實戰營】答疑彙總Day2 MySQL 高并發場景實戰

【開營第二課,MySQL 高并發場景實戰】

講師: 淩洛,阿裡雲資料庫解決方案專家。

課程内容:高并發場景下MySQL資料庫的技術挑戰;如何用RDS MySQL支撐高并發業務;高并發場景資料庫運維最佳實踐。

答疑彙總:特别感謝班委@李敏 同學

  1. Mysql 一年應該是什麼水準?需要知道哪些知識?

    A:個人學習/接觸 Mysql 一年的話,最主要的還是學習基礎知識,如果你接觸的項目夠多的話,你會在實際的項目當中,獲得實際的一些和業務、技術結合的經驗,一年的話,最開始還是要從基礎知識開始學

  2. 最大連接配接數1000,高并發指多大的活躍連接配接數?最大連接配接數是 1000 的話,根據 rds 的規格來說的話,還是比較低的。在高并發的情況下,指多大的活躍連接配接數?

    A:活躍連接配接數,和 CPU 的核數是相關的,建議将最大活躍連接配接數不超過 CPU 核數 3 ~ 4,這個時候它的性能是比較高的。經常有使用者會混淆“最大連接配接數”和“活躍會話數”這兩個概念,最大連接配接數是指你的應用 應用連接配接池 * 執行個體上有多少個 DB,不超過最大的連接配接數的數量(這句話不太好整理),活躍會話數是指正在幹活的數量,這個數量不是越多越好,我們要保證活躍會話要盡可能少,這樣的話,mysql 才能提供最高的一個性能(了解各種連接配接數:

    https://developer.aliyun.com/article/683460
  3. Mysql 中分表時,需要組合表查詢時,如何做到高效?

    A:是不是想問多元查詢的概念啊?通常分表了以後。。。(中斷,調試了一下連麥)mysql 在分表時,如何做到組合表查詢,neng zuodao 高效,其實對于一張單表上面來說的話,它比較容易控制,比如說有主鍵、唯一鍵,在一張表上就不會出現,和其他表的關聯,就不說了,如果一張表有超過1億條的記錄,就要考慮分庫分表了,在分庫分表的時候,如果兩張表都超過一億,這位同學,是不是想問多元查詢的概念啊?如果想避免多元查詢的話,這個時候還是要做資料備援的,不是說資料表設計符合三範式越好,如果分庫分表了以後,盡量還是要避免組合表的查詢,特别是在分褲分表了之後,避免不了的話,那兩個表join的時候,在關聯的字段上面還是要建索引的。在兩個表查詢的時候,如果查詢關聯字段不太多的話,還是要做适當的字段備援)。還有一個巧思是說,比如淘寶系統買家庫和賣家庫,因為隻能按照一個次元來分表,如果按買家分表,但是按照賣家來查詢,其實是用不上分庫分表的字段,如果你是要用賣家的資料的話,它其實有幾種方式,一種方式是做資料備援,還有另一種方式是在現有表的基礎上,相當于是存一個映射的表,相當于你還是要做資料備援,但是資料備援是用的不同的的方式,你可以全量地把買家表的資料同步到賣家表,它的資料是一樣的(買家表的資料和賣家表一樣),隻不過你是以另外一種次元(賣家)來分表,這以空間換時間的概念;另一種方式就是,你可以沒有,另外一個以賣家次元分表的那一份完整的備援資料,但是你可以備援它的 ID,在現有表的基礎上,隻需要買家表和賣家表對應的id就可以了,這是一個比較輕量級的資料備援,如果要是用 drds 的話,可以用全局二級索引,我剛才說的那個概念其實也類似于全局二級索引,drds 裡面是有這個概念的,你在 drds 建立索引的時候,官方文檔是有的。(Polar-X 2.0的全局二級索引

    https://help.aliyun.com/document_detail/182180.html?spm=a2c4g.11186623.2.2.1bb148c1p28A4b ;)
  4. Mysql 5.7 使用 MHA 無損複制,是否有丢資料的可能?

    A:還是要看 5.7 使用的架構,三節點的企業版本,雙節點的開源社群版本,如果是雙節點,以雙1的參數(innodb_flush_log_at_trx_commit=,sync_binlog=1)啟動的話,原生的社群版是有丢一個事務(資料)的可能的,如果是用 rds 企業版或者金融版,這種的話是不會丢資料的。

  5. Mysql 中單表大約一億行資料,隻有首列(自增列)為主鍵,這種設計是因為高并發嗎?高并發在表設計上有哪些需要注意呢?

    A:如果隻有自增的列為主鍵,這種方式,如果是隻有自增的列作為主鍵,是有助于高并發的,但又不完全是因為這個。還有哪幾種可能會影響高并發的,最主要是記憶體的緩存命中率,就是 buffer pool 的命中率,如何才能在有限的 buffer pool 裡面,存儲足夠多的資料,那就需要我們在資料庫設計的時候注意,因為 buffer pool 裡面緩存了索引和資料,buffer pool 的命中率是一個方面,還有一個方面,是在磁盤空間裡面,mysql 的 innodb 表是索引組織表,如果是換做一個字元串為主鍵的話,相當于每個二級索引上都要挂一個這樣的葉子結點,不管是它的磁盤空間的使用會增長,buffer pool 裡面存儲的資料并不是那麼多。首列作為主鍵隻是一個參考,我們需要從那幾個方面去考慮高并發,最主要的還是要考慮緩存命中率,還有就是底層的資料結構,無論是做查找的時候,還有是在緩存命中率的時候,是否有助于...。為什麼會涉及緩存,一級一級來,剛才提到過的 redis,其實也是提升緩存的命中率,對于mysql 來說,buffer pool 也是一個緩存,記憶體的命中率,怎樣才能提升記憶體的命中率,也是從設計的時候考慮的一個問題。(buffer pool 的大小是可以配置的,記憶體空間在啟動的時候立即配置設定完成了,老師所說的更多的資料,有時候需要按照更多的記錄之類的去了解)

  6. Mysql 的讀寫鎖怎麼使用更好?讀寫鎖的使用場景?

    A:如果是單個語句來查詢的話,資料庫内部自己就控制了,對于應用來說,就不用單獨來控制,如果涉及到事務,比如事務,我見過事務最多的是,一個事務裡面有一千條語句,那在寫事務的時候就要注意了,特别是在核心的事務裡面,特别是在減庫存的場景裡面,你的行鎖的釋放時間和事務的釋放時間是有關系的,我們在使用事務的時候,還是要盡量地減少行鎖持有的時間,如果事務裡面有讀的話,如果業務上允許的話,把它移到外面,盡量地使這個事務足夠的少,這個就是事務裡面的控制。

  7. 高并發的時候,頻繁 crud,容易讀到舊資料應該怎麼辦?

    A:對于資料庫來說,底層的 MVCC 已經保證了資料一緻性,你問的應該是緩存裡面,比如 redis、memcache,從緩存讀到舊資料應該怎麼辦?基于這個問題,我們還是要基于實際的應用場景出發,比如減庫存,涉及到交易這種場景的話,以哪個(資料)為準?以緩存的為準,然後把它同步到資料庫裡面;還是以資料庫裡面的資料為準,到資料庫執行的時候,還是要做一個判斷的,如果是想要嚴格一點的話,還是要以資料庫為準;如果要是以資料庫為準的話,相當于是你從緩存裡面讀到既有的資料,你的緩存怎樣才能保證100%命中?群裡同學也有提到說,redis 那個鍊路更新的延遲,我們可以算一下,如果要是用這種方式的話(詳情見 PPT 17頁),相當于是 rds 寫 binlog,再同步到 redis 的話,這個可以控制在百毫秒左右,一方面是,db 在傳回的時候,我麼有 retina 那個更新檔,redis 傳回了之後,應用程式可以直接拿這個更新 redis,下遊鍊路并不是每次更新 redis 都成功,我們還有一個資料補償的任務,可以通過 binlog 這種方式,實時地更新 redis 這個鍊路,這個并不是在幾秒,而是在百毫秒内,可以把這個緩存給更新掉,這樣的話,增删改查的資料,就是在百毫秒内,redis 和 db 的資料,控制是最新的。

  8. 大流量的情況 MGR,如何保證從庫資料的實時性,老師您開始給出的流量峰值資料庫用的什麼架構?

    A:MGR 的内容見第一個課。峰值資料庫的架構有兩種,一個是用rds 的分庫分表;還有一個是,比較小的使用者的話,單個的 rds 就可以支撐。

  9. SSD 盤下參數 innodb_io_capacity 建議設定多大?

    A:根據不同的 SSD 盤的性能來決定的,對于 rds 來說,不同的執行個體,io_capacity 是不一樣的。自建的話,盡量不要超過盤的...,就要看對實體機分割方法,比如一個實體機上面,分割成很多個執行個體,是把 io_capacity 嚴格地區分?還是要盡量用實體機的性能?還是要看實體機資源隔離的方式。總的來說,同一個實體機上所有執行個體 io_capacity 的總和,不要超過實體機的 iops 的性能,比如說,實體機上所有執行個體都嚴格地隔離,一共有 1w 個的 io_capacity,四個執行個體,這個 io_capacity 要如何劃分,均分?還是不限制,讓它充分地使用實體機的 io_capacity,這些都是有關系的。

  10. 5.7 在使用過程中,占用記憶體會逐漸增大,調整思路是怎樣的?

    A:如果是記憶體逐漸增大的話,不排除某些版本存在記憶體洩漏的可能性,這種還是要持續觀察,記憶體逐漸擴大,有幾種可能性,比如表裡面有 table open cache,不建議設定過大,使用過程中,哪些會涉及到記憶體增大的幾種情況,就要看一下這些語句,比如說會話裡面的幾個,就是它的變量,設定 buffer pool 的時候,基本上上限就設定為 75% 這樣的一個值,其他幾個變量,就是語句裡面的會話,比如 join buffer,和會話相關的變量,語句裡面是不是有超大的使用記憶體的情況?剛才幾個問題,和 ppt 沒有多大關系,就沒有示範ppt。PPT 20頁中展示的,剛剛提到和記憶體相關的幾個參數,innodb_buffer_pool_instance 是全局的,和會話相關的 join_buffer_stats 和 sort buffer,看是不是有 order by、group by 這樣一系列的、會用到記憶體的幾種情況,還要再看剛才提到的 table open cache 是不是設定的比較大,如果設定的比較大的話,就調小一點,這種就是要來回調,來回觀察,不斷看它調的效果。(參數調優的内容詳情見 PPT 20頁)

  11. 如何擴充并行寫,除了分表還有别的方法嗎?

    A:并行寫,有幾種提升寫的性能的方法,比如你可不可以把它,把這些請求先存在應用的機器上,然後再批量地刷到資料庫裡面,這也是一種方法,就是把小批量(這裡應該是口誤)的請求換成批量的請求,小的一條條的,單條的請求,在應用端先存起來,再批量地刷到 db,這是一種方法,就不一定要分表;還有另外一種情況,就是像我們的 polar db 一樣,把底層的存儲,給它并行,這樣的話也是一種方法。

  12. 阿裡雲售賣 AliSQL 嗎?我沒找到,還是要自己來搭建?

    A:售賣的,alisql 有一部分是開源的,在社群都可以找到開源的源代碼,現在售賣的 rds 的 mysql 裡面,已經包含了 alisql 的特性,比如說剛才提到的庫存和線程池,這些更新檔都是其中這一,我們寫了十多個更新檔,然後你都可以用起來。(詳情見 PPT 24頁)

  13. 能不能講講阿裡的系統架構?

    A:阿裡做雙十一的一個主要步驟,他的架構其實和阿裡雲官網上售賣是一樣的,當單個執行個體不足以支撐的時候,可以用 drds ,也可以更新成 polardb。我們内部也是用了 das(詳情見 PPT 12頁) 和 dms,我們都是用的,基本上,我們是把内部我們用得很不錯的更新檔和場景,這些我們都是經過雙十一驗證過的,我們才把它們放到阿裡雲上售賣,這個和我們用的系統的架構是類似的。

  14. 熱點資料更新具體要怎麼做避免死鎖之類的問題?

    A:熱點資料更新和死鎖是兩個問題。熱點更新的方法已經介紹了,而且性能的提升可以看到(PPT 25頁)。避免死鎖之類的問題,要分析一下 死鎖産生的幾種情況,就加鎖的順序,無論是同一個表裡面,同一個頁裡面加鎖的順序,兩個不同表裡面加鎖的順序,出現互相的索引,這種情況才會出現死鎖,熱點更新和死鎖并沒有直接的關系,這還是要分成兩個情況來看。

  15. 能講講 rds sql 限流的實作原理不?

    A:在 sql 解析的時候,捕獲你設定的,das 的限流隻是界面上的一個功能(PPT 36頁),底層是需要核心來支援的,這個是内部雙十一場景遇到的,覺得對大家比較有用,确實很多使用者回報說比較實用。它這個原理是,我們捕獲到 sql 限流,是沒有實際會話對,這裡面在 show processlist 非常繁忙的情況,有大的 sql 的話,就可以撈到,就是可以設定限流,設定一系列關鍵字,在 server 層解析到關鍵字之後,設定并發,關鍵字比對上了之後,就可以根據這個限流了,實作上其實是比較簡單的,在 sql 解析層做的。

  16. 請問監控資料庫字段變化的 sdk 架構有什麼推薦?

    A:ibetas 這種嗎?

  17. 熱點資料更新從 rds 到 redis 是插件還是接口?

    A:是想問 redis 怎樣才能保證緩存的命中率,用的是 dts 資料訂閱的一個功能,接收 binlog,通過 dts 訂閱的一個元件,更新到 redis 裡面,可以了解為一個插件。

  18. rds redis 資料怎麼保持一緻性呀?

    A:傳統的緩存和資料庫更新的幾種模式:讀緩存失效 + 寫緩存失效。讀緩存失效就是從緩存讀不到資料,這個緩存就标記為失效;寫緩存失效。如果想保證緩存命中率的話,因為 redis 如果要是撐不住的話,這個執行個體(口誤?流量)打到 rds,也是撐不住的,這個情況的話,就盡量保證 redis 的緩存命中率,曾經曆史上,也發生過機器,redis 緩存不命中,直接就把 DB 打挂的情況,就是有出現過,是以後面我們才出了這樣一個保證緩存命中率的方案,如果要是頻繁地更新的話,對于一般的設計架構,它是保證不了,特别是雙十一庫存更新這樣一個場景,頻繁寫,保證不了緩存命中率 100% 的,我們是怎樣做到的,就是剛才提到的方法,這就是一個非常好的小巧思。

  19. Redis 會自動失效嗎?

    A:這個設定的自動失效,和使用者主動更新,頻繁寫的情況下,失效的事其實沒有可比性。使用者頻繁寫的話,用剛才被動的方式,無論是讀還是寫,還是失效的時間,都是不能保證緩存命中率 100%,如果要是設定失效時間來,它還是會把流量打到DB的,我們設計這種模式,保證緩存命中率 100% 的這種架構,就是為了保證在 redis 不命中的情況下,不要把 redis 打挂。

  20. 請問之前有關于 5.6、5.7、8.0 性能的測試,那穩定性呢?

    A:從 oracle 遷移到 mysql 能否直接上 8.0?都是經過了一系列的穩定性測試,才把它放到阿裡雲上面的。遷移到 mysql,能否直接上 8.0?從 oracle 直接遷移到 mysql 8.0,還是要驗證一下的,直接遷移還是要看文法相容不相容這一系列的,比如說 oracle 裡面的元件、ser,這些在 mysql 裡面是沒有的,還有一系列的,你在 orcacle 裡面有沒有存儲過程這樣一類的,相當于資料庫的異構,不建議直接遷,還是要經過詳細的評估,還是是要看功能、文法,文法相容不相容,msql 在視圖的方面支援得也不太好的,很多 oracle 的使用者都習慣用存儲過程和視圖的,我們不建議把存儲過程寫到 mysql 裡面的,這種是要經過改造的,直接上的話,是有一定風險的。

  21. mysql分表後,如何對所有子表的聯合資料保證高效查詢?

    A:聯合資料是什麼含義,分表後,如果不涉及多元查詢的話,和其他事一樣的,所有子表的查詢語句,和單表沒有差別,你在問的是有資料聚合的情況,count、sum、group by,你是問的這種嗎?

  22. 隻用 rds 不用 drds,可以做到高并發嗎?

    A:可以,自己可以設定,甚至開發一個 drds 的中間件,這是一種情況,或者是用其他的代理,如果要是用其他的代理,就要驗證多元查詢,所有子表的聯合資料保證,代理在和 rds 互動的時候,網絡延遲是一個要考慮的方面,每一個 rds 都是性能上限的,單個 rds,如果設計得足夠充分的話,是可以把單個 rds 的性能做到充分的高,單個 rds 的性能,我們做了基準的測試的,最高是可以達到十多萬的(PPT 10頁),16C64G不是最大規格,可以做到 6W,還有獨享實體機(形态)的,是可以做到十多萬的,主要看系統的峰值有沒有超過單個 rds 性能的峰值,整個資料庫的架構設計,還有真個系統的架構設計,能否充分地把資料庫的性能發揮到最大化,這種都是有關系的,後面再詳細交流。因為之前見過有使用者,資料庫設計中,索引設計得不是很合理,就不能充分利用資料庫的性能,應用和 db 互動的架構,剛才提到的庫存裡面,事務裡面語句的順序,都是和這個有關系的。是以要想做到高性能,不是一個點就可以做到的,需要從整個架構,性能測試,資料庫的測試和緩存的設計,都是有關系的,甚至一個事務裡面語句的順序對會影響到你的性能。

  23. redis記憶體資料有限 讀的資料容量有限制吧?

    A:redis 也是有規格限制的

  24. 有推薦的分庫架構嗎?

    A:對于阿裡雲來說,最常見的就是 drds,現在叫做 polar-X 2.0。

  25. 秒殺場景下,伺服器在北京,新疆 和 北京同時搶,怎麼保證兩邊延遲的公平性和防止超賣?

    A:就要看你這個資料是一份還是多份,如果要是一份的話,就沒有必要考慮北京和新疆的這樣一個問題,伺服器在北京,新疆 和 北京同時搶,那就要看最後哪個請求先到 db,不一定北京的請求先到北京。北京的應用的請求,因為你資料庫的伺服器是在北京,看這兩個誰先在資料庫裡面,資料庫裡面它也不能保證,不一定能保證是完全的按照先到先得得來的,兩邊不一定能保證延遲的公平性,防超賣,是庫存的一個邏輯,為什麼會出現超賣,在業務場景裡面,出現超賣就是,實際售出的數量,比商家庫存的數量要多。可以網上搜一下,2012 年我們的雙十一,出現過超賣的問題,後面經過一系列的改造,才把這個超賣,變成 0 超賣的,這個是一個小專利,可以單獨交流一下,解釋起來,時間需要比較久,簡單來說,防止減下來的數量,實際減的時候,不要超過商家設定的庫存的數量就 ok 了。

  26. 為什麼mysql不建議使用存儲過程?

    A:mysql 在這個方面做的不太好,大多數使用者一上雲的情況下,都會有考慮下雲的可能。有的使用者在實際定位問題的時候,往往都是先從應用端開始定位,有的時候會忽略存儲過程這樣一個邏輯存在,這種從應用的維護和設計上面來講,不建議使用存儲過程。

  27. 上億資料并且有聚合的情況?

    A:具體還是要看業務的需求量,如果在上億的情況下,做了分庫分表,做了多點存儲,不管使用哪些架構,隻要是把這些資料給分開來,再做聚合的時候。業内比較常見的是,看業務請求是輕量級的,還是比較重的。如果是比較重的業務聚合的情況下的話,推薦使用 adb,它會把請求下發到各個節點,各個節點是使用 MPP的架構;如果是有輕量級的聚合的情況下,polar-X 2.0 也就是 drds 也是可以勝任的,具體要看業務的請求,資料量,以及對時間的要求是多少。

  28. Mysql有個表特别大,40多G,請問單表大小多少保證性能好一些(有大字段)?

    A:就是按照經驗值來說,500W,是按照存儲的行數來說,是指 500W 行,還是要看我們的主鍵設計以及業務對資料庫的性能要求,就是按照經驗值是按照行(的次元),那麼按照大小來說的話,單表不要超過 10G。有大字段的話,如果是要保證性能更好一些,比如說我們剛剛提到的寫庫存的場景,我們就要保證,對于 innodb 來說,它寫 binlog 是全量的字段更新,而且 binlog 還要再傳到備執行個體上面,要考慮大字段是不是會被經常更新的,如果有,就是需要把大字段給隔離出來的。

  29. 在剛才讀redis 寫mysql的場景 mysql的資料庫容量也受限制了吧?因為mysql存的太多會撐爆redis?

    A:并不是把 mysql 所有的資料都存到 redis 裡面,把熱資料存到 redis 裡面就可以了。我們是要提前算一下的,我們算容量的時候,不止是要算資料庫的容量的時候,還要算 redis 的容量。算 redis 容量的時候,我們也是要算一下它是有多少熱資料,然後這個量是有多少,也是要充分地擴容 mysql 的量的。

  30. 如果有多個大字段,一般設計表的時候是把大字段放一個表還是分散的好?

    A:如果這個表經常要更删改查的話,而大字段又不經常修改的話,那你就要把它分開;如果整個表,包括這個大字段修改都不是頻繁更新,那你把它們放在一起也是 ok 的。

  31. 誰先到這個應該是自己的應用的決定的吧?

    A:應用決定的吧。

  32. 資料庫全量備份會影響寫操作,有什麼好的方式進行資料備份嗎?

    A:rds 的備份,一般是在備庫上執行的,是以這個也不會影響到寫操作。不得不在主執行個體上備份的時候,這種情況下才可能會影響。資料庫全量備份,有好幾種備份工具:一個是開源的 Xtrabackup,一個是用 dbs,就是資料先用邏輯備份,備份出來一份全量資料,再用增量 binlog 的方式同步到 oos,這種也是一種方式。如果你要是想不影響寫操作的情況,盡量地保證在資料庫備庫上備份的時間。還有一種,備份可能會失效,就是主備延遲,在資料庫設計的時候,和請求量都是有關系的,就不僅是備份工具/方式的問題。如果保證主備同步不中斷,沒有延遲,備庫的備份都是有效的,這樣的情況下,就不會到主庫,主執行個體上去做備份,就不會影響到寫操作。

  33. RDS主備異常的時候會在主庫備份的呀?

    A:rds 異常的時候,是會在主庫備份的,這種機率非常低,什麼時候會影響寫,就是在 flush 的時候會卡一下。如果要是用 Xtrabackup,在主庫備份的時候,是會卡一下的,如果是用 Xtrabackup 的話,沒有比較好的方式。另外一種備份方式dbs,經常把全量資料、增量資料同步,這種方式是不會影響的,因為它先是用邏輯在同步 binlog,這種不會suo。

  34. Double Sync 在大批量資料操作的時候,IO線程容易down掉,奇怪,新版本RDS還有這問題嗎?

    A:這個情況,我值班的時候沒有遇到過,這個情況發生的機率比較低,如果有的話,我們也是有修複機制的:stop slave + start slave。

  35. 還有percona 的xback?

    A:對,這種備份工具也有。

  36. rds和polar db,ocean base差別?

    A:價格看起來差蠻多?這種架構我不是很了解,你們可以看看官網上的對比,sa 或者是商務經理,跟他們問一下價格上面的問題。

  37. 監聽資料的修改 sdk,有哪些 sdk,能具體說一下嗎?

    A:你是說資料庫增删改查的那個嗎,其實就是 dts 的資料訂閱。

39.由于開發不規範,導緻有的sql在主庫執行沒問題,但是在從庫回放sql的時候回放失敗(比如說更新的條件多了亂七八糟的東西 WHERE id='430753 `wget http:// 169.254 ) 導緻主從同步失敗,一般我是告訴開發他們這個sql裡有開發不規範的問題,他那邊處理完了 我這個才能解決問題。本地自建的主從mysql,主從同步失敗了 失敗報錯是update 語句後面where條件問題,這個比較被動,請問老師還有别的方法嗎?

A:如果是sql線程回放中斷,你的主從同步設定的是什麼模式?statement?mix?row?設定row沒問題,statement?mix?不嚴謹