修改 MySQL 唯讀參數的方式

Domas Mituzas 的 Blog 上看到如何不停機修改 MySQL 唯讀參數的方式:「Evil replication management」。

Domas Mituzas 在 Sun Microsystem 做事,同時也是 Wikimedia 的系統與軟體發展人員,我猜這個方法應該是用在 Wikimedia 的 MySQL server 上。Wikimedia 的 MySQL server 資料量不小,如果 shutdown 後改 my.cnf 再重新啟動,會因為 innodb_flush_method = O_DIRECT 用掉不少時間在熱機上面。(這是 InnoDB 常用的參數,可以避免 filesystem 與 InnoDB 重複 cache 同樣的資料,但也使得 mysqld 重新啟動時沒有 cache,會需要先熱機才能上線,不然會卡 query)

於是這篇文章就教你「非正規」的方式修改 (也就是說,要自己承擔風險),使得 cache 不會被清掉,進而降低 down time。

SVG

Wikimedia 的 Blog 上提到了可以用 Flash 顯示 SVG:「SVG for all… with Flash?」。

就目前瀏覽器的情況,只有 Opera、Gekco Engine 系列 (以 Mozilla 的產品為主)、WebKit Engine 系列 (以 AppleGoogle 的瀏覽器為主) 有內建,Microsoft 的 IE6/7/8 則必須靠 Plugin 外掛支援。

不過 svgweb 這個 Open Source 的專案 (Apache License 2.0) 雖然還在 alpha 階段,但總算是有機會利用 Flash 顯示 SVG 圖片了,就短期看來,這樣推廣 SVG 會比較順。

另外在原文裡有提到過於複雜的 SVG 檔案會使得 svgweb 過慢/吃資源的問題可以用 Scour 這個軟體清理 SVG 檔。

Distributed Key-Value Database

這篇是因為在 PIXNET 內講了 n 次,決定寫成文字,至少之後新人進來可以說「就看這篇」,避免整套系統都需要重新講一次。

對了,補充一下,PIXNET 還是有缺人,參考「缺人找人」這篇的內容,如果有想問的細節,可以寫信問我。

資料庫

RDBMS 提供了很多而且很豐富的操作方式,但當資料量愈來愈大時,會遇到單台機器的網路頻寬有限以及空間有限。這時候一定得走向多台的架構。

Replication

最容易解決的情況是「讀取的 query 比寫入的 query 多」,可以用 database replication 解決,這也是 Web 1.0 網站常見的解法之一 (另外一種常見的解法是使用靜態檔案,或是 reverse proxy cache),同步將資料複製到多台。

Memcached

接下來會發現當 slave 過多時會造成每台記憶體內重複 cache 相同的元素,也就是說,有二十台 slave,每台都有 SELECT * FROM `user` WHERE `name` = 'gslin' 的結果其實很浪費資源。不過這個問題可以用 memcached 或是 hash selection 解決。

Sharding

在 Web 2.0 的環境裡,User generated content 成為主流,當寫入的 query 超過單台可以負荷的量時,replication 的架構就不是很適合了,因為每個寫入的 query 在其他台 slave 上也會被執行。在商用資料庫的領域通常是使用 cluster 架構,在 open source 領域的 MySQL cluster 也是 cluster-based solution,不過用的單位還不是很多,而且 overhead 還蠻重的。

比較常見的解法是 sharding:依照 id,把資料拆散到各台。像是 Flickr 就是這樣使用。

但 sharding 就會少了很多 RDBMS 可以用的特性 (JOIN 與 transaction),在寫 application server 或是 library 的時候得花功夫多下幾次 query,並且注意資料的正確性。

上面這些方法在 2005 年 Brad Fitzpatrick (LiveJournal founder、memcached 作者) 的投影片「LiveJournal's Backend: A history of scaling」都有提到。

Sharding 是一個解法,但有不少缺點:

  • 需要 application server 或是 library,否則 3rd party 程式得清楚知道 sharding 的架構,才會知道資料要到哪個 cluster 找。
  • 無法隨意使用 JOIN 及 transaction。如果真的要 JOIN,設計時要想辦法把需要 JOIN 的資料放在同一台 database server。如果要跨機器 transaction 得透過 2PC 甚至 3PC (看需求),或是類似的 distributed transaction protocol,效能會比起同一台機器差很多。
  • 設計 schema 時必須注意當一個 cluster 愈來愈大時要 rebalance,或是更進一步,在一開始設計時就考慮到資料搬移的問題。

Key-Value Database

後來就有不少人注意到,Web 2.0 網站很多時候不需要 transaction,而 JOIN 也會儘量避免。透過多次 SELECT 拉資料,或是 denormalize 以提高效能的方式還蠻常見。(JOIN 保證 atomic,而且會因為 query analyzer enginer 在沒有正確分析的情況下會有大量的 random access,比多次 SELECT 耗資源)

另外一個是財務層面上的問題,一開始寫的時候通常也都只有一組 database server,不太可能一次就買兩組 database server。當成長到需要 sharding 時通常寫 code 的人已經不只一個人,一定有人偷懶使用 JOIN 或是其他無法 sharding 的程式。這時候會發現需要「重寫」而非「改寫」。

於是就有人開始思考,如果我放棄 RDBMS 的 JOIN 與 transaction,放棄到只剩下 key-value 的架構,是不是有辦法可以發展一套 distributed database system 可以取得 "incremental scalibility" 的特性 (白話的說就是「加機器就可以增加承載量」),再想辦法看看在這個系統上還可以加什麼功能。

也就是說,這樣的系統一開始可能只有兩台小台的機器 (為了 HA),同時跑 Web 與 Database,當網站愈來愈大的時候我把這些小機器拉到前端跑 Web,或是轉為開發機使用,本來的 Database 買 15KRPM SAS (為了 cache miss 的 seek time 與 latency) 與 64GB RAM (還是為了 cache hit 降低 latency)。

所以在 distributed key-value database 先有基本的功能:

  • GET(key)
  • SET(key, value)
  • DELETE(key)

有了這三個功能,至少你可以把本來在 RDBMS 裡很大一部份放到 Key-Value Database 裡。以 Blog 來說,可以把所有的標題及內文部份放到 Key-Value Database 內,大幅減少 RDBMS 的 cache 負擔。

或者,key 是 path + filename,value 是檔案內容,當作一個 filesystem 在用。(也就是 Amazon S3)

這樣對於前端寫程式的人就會簡單許多。整個 Key-Value Database 是一朵可以無限擴充的雲,前端程式不需要設計或是修改程式碼就可以一直發展。如果當作 Filesystem 就不用擔心 disk 滿了之後加機器需要停機。

在這個想法下,就有許多單位投入資源往 distributed key-value system 發展。經過這些年的發展,分散式資料庫主要有三個問題要解決,而且也被證明這三個問題無法同時解決 (被稱為 CAP theorem,參考 Brewer's Conjecture and the Feasibility of Consistent Available Partition-Tolerant Web Services, 2002 這篇原始論文,或是參考比較簡單易懂的說明「Brewer's CAP Theorem」):

  • Consistent
  • Availibility
  • Partition Tolerance

所以分散式資料庫得在這三個條件內取捨。目前比較熱門的 Distributed Key-Value Database 主要都是把 Consistent 放寬到 "Eventally Consistent",只保證資料「遲早會一致」,這些 Database 包括了 HBase (Yahoo!)、Cassandra (Facebook) 這兩套 Java-based 分散式資料庫。

要瞭解這兩套系統的架構,一般建議從「Amazon's Dynamo」這篇開始看,看完後再看這兩套系統的系統架構介紹,以及 mailing list 的討論。

這兩套除了基本的 Key-Value 外,還多了 Column 的觀念,彈性會比 Key-Value 好一些。Yahoo! 與 Facebook 都拿這個系統當 Search Engine 使用。

另外有一些比較單純的分散式系統,只有 Key-Value 而沒有 Column 的,在「My Thoughts on NoSQL」這篇文章裡對 CouchDBRedis 自稱 distributed 的嘴炮批評了不少。另外「Anti-RDBMS: A list of distributed key-value stores」介紹了很多。

大致上是這樣。

FreeBSD 8.0-BETA1 初步使用感想

雖然在裝之前就已經知道,但還是得再提一次,FreeBSD 8.0-BETA1 不是給 production 用的 XD

首先是安裝的部份,裝起來不太順,今天早上國內的伺服器速度不太快,而且偶而會遇到 error,之後還是跑去日本的 ftp.jp.freebsd.org 抓才正常多了。

列出我自己遇到的已知問題:

  • 使用 disklabel 時會認為 c 應該從 0 開始 (ad4s1"c"),但新裝好的系統是從 32 開始,會無法修改...

另外一些小問題:(BETA 特有的,RC 與正式版的時候應該都會解掉)

  • FreeBSD PortsINDEX-8 還沒建出來,目前無法使用 pkg_version-I,以及其他需要使用這個檔案的程式。
  • library 都還沒 bump,除了從 8.0-BETA1 到 8.0-RELEASE 會大爆走外,還要注意軟體會爛光。
  • debug code 使得 performance 只有 7.2-RELEASE 的 2/3 左右。

Installer 改了不少東西,裝的時候其實發現很不順手 (像是 boot loader 的地方,Standard 與 BootMgr 對調,結果一直選錯)。另外 doc 的部份是以 package 裝入系統,不屬於 base system,不小心誤裝後可以用 pkg_delete 移除。

依照 schedule,應該是今明兩天就會出 8.0-BETA2 吧?再來看看情況。

FreeBSD 8.0-BETA1

FreeBSD 8.0-BETA1 出了,也已經可以用 freebsd-update 更新。(不過就 freebsd-update maintainer 的說法,因為他不是 Release Engineer (re@),對 8.0 並不比一般人更熟悉,想要利用 freebsd-update 升級到 BETA1 可能會有問題)

在「What's cooking for FreeBSD 8?」列出了 FreeBSD 8.0 會有的新功能或是改善。

對一般使用者比較重要的有「Xen dom-U support」,表示終於有可能在 Amazon EC2 上跑 FreeBSD。

另外一個是 amd64 平台的 Kernel memory limit 比之前大 (這個修正已經 merge 回 7-STABLE),以及 ZFS 更新到 v13,這使得 ZFS 的效能以及可用性大幅提昇。

NFS 的改寫也是重點,包括 NFS locking 與 NFSv4。FreeBSD 之前的 NFS client 在高負載時的效能與穩定性都不好,這次改寫後打算灌台機器來測試看看 8.0-BETA1 的效果如何。

瀏覽器的佔有率

Digg 的 Blog 上看到「Much Ado About IE6」這篇文章,提到目前瀏覽器佔有率的事情 (尤其是 IE6)。

Digg 的使用者者中,IE6 佔了 10% visitor 以及 5% PV,所以他們已經在規劃何時要放棄 IE6 support。

我翻了六月 PIXNET 全站的情況 (用 Google Analytics),以 visitor 來看,IE 佔了 83.09%,IE6 佔了 IE 的 48.66%,所以大約佔全部的 40.43%。以 PV 來看,IE 佔了 83.91%,IE6 佔了 IE 的 46.98%,大約佔全部的 39.42%。

這個數字離不支援還早得很...

Update:六月 PIXNET 全站的瀏覽器分佈,overall >1% 的部份。(by Visitor)

Internet Explorer - 83.09% (6.0 - 48.66%,7.0 - 48.58%,8.0 - 2.74%)
Firefox - 13.47% (3.0.11 - 46.78%,3.0.10 - 38.50%)
Chrome - 1.63%
Safari - 1.27%

InnoDB Fast Recovery Patch

在「Improving InnoDB recovery time」這篇看到的。

這個 bug 在 2007 年時 Heikki Tuuri 開了 #29847:「Large CPU usage of InnoDB crash recovery with a big buf pool」,在 bug report 中間有提到 workaround,在 recovery 時把 O_DIRECT 關掉並且降低 innodb buffer pool size,把問題推到 Filesystem cache,速度比較快。

但這表示在 crash 後必須手動介入,或是要寫 script 在啟動 MySQL 時判斷,並不是一個自動的解法。

不過今年五月的時候有人丟出 patch 了,目前測過的人用起來都沒問題,順利的話下一個版本就會收進去,對於 MySQL HA (像是 failover 時需要跑 InnoDB recovery 的系統) 幫助很大...

Google Apps 畢業,Openfind 推出郵件解決方案

Google Apps is out of beta (yes, really)」與「Openfind-解決方案-中小企業郵件解決方案-輕鬆郵」。

中間有一些小插曲,像是 Google Apps (Standard) 的連結不見,造成大家猜測是不是要趁著轉入正式版拿掉,最後又把連結放回去 (不過只有英文版的放回去,繁體中文版的還是拿掉了):「Google Apps Standard Edition: still free」。

另外一邊是 Openfind 推出「輕鬆郵」,提供 closed-source 版本的 server 軟體,有 100 accounts 限制,主要是給對於郵件系統放到 3rd-party 有疑慮的公司,但自己建制不敷成本的單位使用。網站上不能直接下載,需要填表...

另外一個重點是 GPL violation,這套免費版的防毒軟體使用 ClamAV (參考「常見問題」內的 Q4),不過 Openfind 已經明確表示他不會提供 source code 了 (看介接方式才會知道感染多大塊),這點就看誰拿到 binary 後去跟他們要...

innobackupex

innobackupex 是 Percona 因為 XtraBackup 需要,改自 InnoDB 的 script,可以不停機備份 InnoDB 或 XtraDB。對於沒有一開始就設定 DRBD 或是類似架構的人來說,這個方法算是蠻不錯的。(當然,如果允許停機的話更簡單)

這個方法是以 InnoDB 為主體的 database 為主,MyISAM 也可以透過這個方式備份,不過這就不在我測試的範圍內了... (我測的兩個 cluster 只有系統資料庫是使用 MyISAM,其他都是 InnoDB)

這邊寫的版本是使用 XtraBackup 0.7 版 (前幾天測試的,當時 0.8 版還沒有正式放出來,就先拿 0.7 版測試),在 Debian 上先安裝 package:

# dpkg -i xtrabackup_0.7-1_amd64.deb

裝完後就可以試著使用 innobackupex 備份,並要求 innobackupex 紀錄 slave 資訊:

# innobackupex-1.5.1 --slave-info [dest_path]

在「Btw xtrabackup is not only backup..」有推薦用 --stream=tar 將備份資料輸出成 tar 格式,不過實際上會因為 ibdata1 被改變而使得 tar 認為無法備份而失敗,所以目前比較偏好的作法是直接輸出到某個目錄下 (就不會用到 tar),目錄可以是 nfs 或是 local disk。

另外,預設是透過 socket 連 MySQL,但也可以故意用 --port=3306 強制他走 TCP,或是用其他指令指定帳號及密碼,這些都可以直接執行 innobackupex 看到。

innobackupex 會試著使用 mysql 並下一些指令,但使用時並不會指定完整路徑,所以會依照 PATH 內所設定的路徑而執行。不過,因為上面的指令通常需要 root 權限,如果使用 sudo 有可能會將 PATH 重設而造成 mysql 無法執行而失敗 (像是 Percona 的版本是裝在 /usr/local/mysql-blah-blah 下,所以配合 sudo 時的用法會是:

# sudo env PATH=/usr/local/mysql/sbin:/usr/local/mysql/bin:[original_path] innobackupex-1.5.1 --slave-info [dest_path]

這樣就解決了。

備份完成後再用 --apply-log 把還在 log 的 entry 寫回 pool:

# sudo innobackupex-1.5.1 --apply-log [dest_path]

這樣一來,一份可以當作 slave server 的資料就完成了。

丟到其他機器後,用 chown 先把檔案權限改對:

# chown -R mysql:mysql [data_dir]

然後跑起 mysql 後,看裡面的 slave 資訊設定 master:

CHANGE MASTER TO master_host = 'master_host', master_user = 'master_user', master_password = 'master_password', master_log_file = 'blahblah.012345', master_log_pos = 123456;

這樣就可以讓 slave 動起來了。(記得要自己 START SLAVE;)

Firefox 3.5 與 PHP 5.3

兩個不小的軟體都出新版...

Mozilla Firefox 3.5 正式版昨天放出來了,JavaScript 的速度再次提昇,另外有不少新功能,以台灣的普及率,大約等兩年後看普及狀況再決定能不能用。

另外一個是 PHP 5.3 第一個的正式版 5.3.0 也是出了,可以在 PHP 5 ChangeLog 看到比較詳細的說明。照之前國外測試的結果,除了使用過舊的 deprecated function 外,應該不會造成目前的程式不能動,不過還是要測過才會知道...

比較新的功能是 namespace,雖然用 backslash (就是「\」這個符號) 大家看了都很囧,不過畢竟是有 namespace 了,PHP library & framework 總算可以用 namespace 解決命名的問題。