MySQL 總算要拔掉 mysql_query_cache 了

半官方的 MySQL blog 上宣佈了拔掉 mysql_query_cache 的計畫:「MySQL 8.0: Retiring Support for the Query Cache」。

作者開頭引用了 ProxySQL 的人對 MySQL Query Cache 的說明:

Although MySQL Query Cache was meant to improve performance, it has serious scalability issues and it can easily become a severe bottleneck.

主要問題在於 MySQL Query Cache 在多 CPU 環境下很難 scale,很容易造成一堆 thread 在搶 lock。而且作者也同意 ProxySQL 的說法,將 cache 放到 client 的效能比較好:

We also agree with Rene’s conclusion, that caching provides the greatest benefit when it is moved closer to the client:

可以看到 Query Cache 在複雜的環境下對效能極傷。而之前也提到過類似的事情了:「Percona 對 mysql_query_cache 的測試 (以 Magento 為例)」、「關閉 MySQL 的 Query Cache」。

一般如果要 cache 的話,透過 InnoDB 裡良好的 index 應該還可以撐不少量起來。

支援多 CPU 的 ab:wrk

在「wrk」這邊看到 wrk 這個工具:「Modern HTTP benchmarking tool」。

利用 multi-threading 與 epoll/kqueue 撐出效能:

wrk is a modern HTTP benchmarking tool capable of generating significant load when run on a single multi-core CPU. It combines a multithreaded design with scalable event notification systems such as epoll and kqueue.

MySQL 的 Parallel Replication

Multithreaded Replication to the Rescue」這篇提到了 Replication 的 Parallel Worker 機制。

作者給了平行的數量對 replication lag 的影響:

可以看得出來 Parallel Worker 機制對 Replication Lag 改善頗大,不過作者在 comment 提到中雷了:「MTS breaks in after restart」。

對於還在使用 traditional master-slave 架構的人可以參考看看。

MySQL 平行執行的 Replication...

MySQL Replication – Multi-Threaded Slaves (Parallel Event Execution)」這篇在講 MySQL 5.6 的 multi-threaded replication。

在文章裡提到,在 5.6.3 之前的版本,MySQL replication 都是 single-threaded,所以當 master 可以充分發揮多 CPU 能力時,slave 仍然要一個更新跑完才會跑下一個更新。

舉例來說,假設 master server 上有兩個 thread 在跑:

  • thread 1 正在執行 UPDATE table1 SET foo = 0 WHERE ...; (SQL 1,假定是 CPU bound,需要跑 100 秒)
  • thread 2 正在執行 UPDATE table2 SET bar = 1 WHERE ...; (SQL 2,也假定是 CPU bound,也需要跑 100 秒)

假設 thread 1 先執行完,這時候 slave 就會在跑完的時候收到 SQL 1,然後把資料同步進去。等到 100 秒過去後,再跑 SQL 2,再花 100 秒。這導致了最少 100 秒的 replication lag (master 與 slave 不同步的時間)。

在 master server 執行時會是這樣:

兩個 SQL query 可以同時跑。

到了 slave 時,在 MySQL 5.6.3 之前的 replication 會變成這樣:

可以看到還是得先執行 SQL 1 再執行 SQL 2,所以最長會有 200 秒的 replication lag。

而 5.6.3 之後支援 multi-threaded replication,可以用 slave_parallel_workers 指定平行執行 SQL query 的數量,這讓 master server 與 slave server 之間的 replication lag 降低不少:

在收到同步的 SQL 指令後就可以同時跑,這讓 replication lag 降到 100 秒。

不過還是要提,如果希望把資料同步問題降到最低,那麼 Galera Cluster 可以解的更徹底,不論是寫入的那台 master server,或是其他的 master server (在 Galera Cluster 架構裡都是為 master),一律都是同步執行:

不會有 master server 與 slave server 不同步的問題,可以減少很多 application 層的麻煩...

用 Lbzip2 解壓縮

手上抓了幾個 .bz2 的檔案要 bzcat 出來 pipe 丟給 Perl script 跑,用系統預設的 bzip2 發現速度卡在解壓縮,而不是 Perl script...

用 parallel 與 bzip2 當關鍵字到 apt-cache 裡面找,有找到兩個套件:Lbzip2Pbzip2,都裝起來後測解壓縮的功能,發現 Pbzip2 解壓縮時沒有辦法利用到多核心的優勢,而 Lbzip2 則是很順利的超過 100%,輸出結果讓 Perl script 也吃滿 CPU resource...

如果是壓縮時需要壓縮率,還是用 xz 就好...

裝 mplayer-mt 改善解碼效率

用 multi-threaded 版本可以將解碼的程式丟到多顆 CPU core 上跑,善用多 CPU 的資源,這樣看 1080p 才不會痛... (家裡的 AMD X2 4000+ 得這樣設,不然原來的版本解不動)

主要有兩個步驟要做,首先是加 ppa 並且安裝 mplayer-mt:

sudo apt-add-repository ppa:longinus00/mplayer-mt
sudo apt-get update
sudo apt-get upgrade # 已經有 mplayer 的 case
sudo apt-get install mplayer # 沒有裝 mplayer 的 case

然後是設定 smplayer 要他在用 mplayer 時加上參數:

參數是「-lavdopts threads=4」。

不過寫完才發現我這張 video card 有硬解可以用... XD

Perl 的 Threading 實做:Coro

去年「Perl - PSGI」這篇文章裡面提到 Perl 的 threading 一直是頭痛的問題之一,唐鳳在留言上推薦用 Coro 而非原來的 thread。

實際測試後發現並非 OS level 的 threading,而是利用抽換的方式將系統內許多 blocking function 換掉,並且支援常用到的 module (像是 libwww-perl 系列),使得現有的程式要 porting 到 Coro 上會簡單很多,寫起來也的確比較像 threading 程式。(雖然實做比較接近 event-based)

附上之前寫來測試的程式,用的是 PIXNETAPI