PostgreSQL基於預寫日誌的複製

PostgreSQL是一款優秀的開源關係型數據庫,從1989年至今已有22年歷史,經過多次轉折,如今乃是業界流行度僅次於MySQL的開源數據庫系統。比起MySQL,PostgreSQL有更好的索引支持和更穩固的ACID保證,也提供了諸多非常優秀的複製(Replication)解決方案,同時以更自由的開源許可協議發佈。在PostgreSQL 9.0之前,PostgreSQL就有了許多的第三方的複製方案,如下表:

特性 共享磁盤容錯 文件系統複製 基於預寫日誌的可讀複製 基於觸發的複製 基於語句的複製 異步多主節點複製 同步多節點主複製
常見的解決方案 NAS DRBD PITR Slony pgpool-II Bucardo
通信方法 shared disk disk blocks WAL table rows SQL table rows table rows and row locks
無需特製硬件
允許多主服務器
不增加服務端負荷
多服務器無等待
主服務器失敗時不丟失數據
備用服務器支持讀請求 Hot only
表級別粒度
無衝突解析

從PostgreSQL 9.0開始,基於預寫日誌(Write Ahead Log, WAL)的可讀複製(PITR)更是成爲了官方提供的異步主從複製(Master-Slave Replication)解決方案,該方案擁有如下優點:

  1. 使用預寫日誌記錄數據庫的改動,不額外增加服務端的其他負荷。
  2. 當主服務器失敗(如斷電、系統崩潰、災難)時,不會丟失任何數據。
  3. 支持基於流和基於檔案的兩種日誌傳輸方案。
  4. 備用服務器可作爲負載均衡節點提供讀請求。
  5. 支持多個或多級備用服務器。

實現原理

主服務器在接受到每個事務請求時,將數據改動用預寫日誌(WAL)記錄。具體而言,事務採用兩段提交(Two Phase Commit),即先將改動寫入預寫日誌,然後再實際改動數據庫。這樣可以保證預寫日誌的時間戳永遠不落後於數據庫,即便是正在寫入時服務器突然崩潰,重啟以後也可以依據預寫日誌將數據恢復,因爲預寫日誌保留了比數據庫記錄中更新的版本。PostgreSQL的異步複製解決方案正是利用了預寫日誌,將預寫日誌從主服務器(Master Sever)傳輸到備用服務器(Standby Server),然後在備用服務器上回放(Replay)出預寫日誌中記錄改動,從而實現主從複製。PostgreSQL使用了兩種方式傳輸預寫日誌:存檔式(archive)和流式(streaming)。

存檔式複製的原理是主服務器將預寫日誌主動拷貝到一個安全的位置(可以直接到備用服務器,也可以是第三臺服務器),同時備用服務器定期掃描這個位置,並將預寫日誌拷貝到備用服務器端然後再回放。這樣即使主服務器崩潰了,備用服務器也可以從這個安全的位置獲取到一份完整的記錄,以確保任何數據不會丟失。而流式複製則簡化了這一個步驟,由主服務器直接通過TCP協議向備用服務器傳輸日誌,避免了兩次複製的開銷,有利於減小備用服務器和主服務器直接的數據延時。但當主服務器崩潰時,未被傳輸到備用服務器的日誌則會丟失,造成數據損失。PostgreSQL支持存檔式和流式兩種模式的混合,當兩種模式都開啟時,備用服務器會定期檢查是否有存檔已經到達指定的位置,並回放日誌。一旦檢測到指定的位置沒有新的日誌,則會切換到流式模式試圖直接從網絡傳輸日誌,接着再檢查存檔,不斷重複這一循環。

基本配置步驟

1、在主服務器和從服務器上分別安裝PostgreSQL 9.1以上版本,初始化數據庫:

initdb -D "/var/postgres/data"  # Unix
initdb -D "D:/postgres/data"  # Windows

2、修改主服務器數據目錄下的配置文件pg_hba.conf,增加備用服務器訪問的權限,例如:

host    replication    postgres_repl    59.66.134.0/24    md5

以上表示允許來自59.66.134.0/24的連接,用戶名爲postgres_repl,口令採用MD5驗證。 如果不需要配置流式複製,此項配置可以忽略。

3、修改主服務器數據目錄下的配置文件postgresql.conf: 將wal_level設爲archive或hot_standby,archive爲單純備用服務器所需的日誌格式,hot_standby爲支持讀請求的備用服務器所需格式; 如果要支持流式複製,修改max_wal_senders爲一個大於零的數值,表示流式複製最大的備用服務器連接數目; 如果要支持流式複製,修改wal_sender_delay爲一個適合的時間值,表示發送流式日誌的週期。 如果要支持檔案式複製,設置

archive_command = 'test ! -f /mnt/server/archivedir/%f && cp %p /mnt/server/archivedir/%f'  # Unix
archive_command = 'copy "%p" "X:\\server\\archivedir\\%f"'  # Windows

其中cp或copy是shell可執行命令,用於複製日誌,具體應用中根據環境可以是scp,或其他拷貝方式。/mnt/server/archivedir/或X:\server\archivedir\表示存儲日誌的安全的位置,可供備用服務器讀取。

4、修改備份服務器數據目錄下的配置文件postgresql.conf: 如果設置hot_standby爲on,則允許備用服務器支持讀請求,對應主服務器上wal_level要設置爲hot_standby;否則只作爲單純的備份服務器。

5、在備份服務器數據目錄下添加文件recovery.conf: 設置standby_mode爲on; 如果要支持流式複製,設置primary_conninfo,例如:

'host=59.66.134.21 port=5432 user=postgres_repl password=my_pass_word';

如果要支持檔案式複製,設置

restore_command = 'cp /path/to/archive/%f %p'
archive_cleanup_command = 'pg_archivecleanup /path/to/archive %r'

其中/path/to/archive/爲存儲從主服務器複製的日誌的位置,cp或copy的意義同上,可替換。

6、分別啟動主服務器和備份服務器:

pg_ctl start -D "/var/postgres/data"  # Unix
pg_ctl start -D "D:/postgres/data"  # Windows

在主服務器上改動數據,測試配置是否成功。

參考資料

http://www.postgresql.org/docs/9.1/interactive/continuous-archiving.html

http://www.pgsqldb.org/

勸君惜取少年時

小時候背過一首詩:

勸君莫惜金縷衣
勸君惜取少年時
花開堪折直須折
莫待無花空折枝

這首詩相傳乃唐時著名歌妓杜秋娘所作,千年以來成爲莘莘學子共勉之佳作。近日重讀,不禁令我感慨:時光飛逝,入學至今已經一年。這一年來過去的每一天令我懷念,我珍惜和清華同學們在一起的日子。

記得在我入學之前,我看了張昆瑋學長的一篇日誌,給我的震撼非同小可,因爲我知道,我與他有過,而且也許將會有相似的處境。爲什麼這麼說呢?這還要從當年奮鬥在信息學競賽的沙場上的一次邂逅談起。在2009年的信息學競賽冬令營上,我目睹了NOI2008國家集訓隊的所有隊員的答辯。張昆瑋的演示文稿設計非常精巧,給我留下了深刻的印象。也算是機緣巧合,2009年5月在北京大學的CTSC上,我和張昆瑋住在了賓館緊鄰的兩個房間,因而有機會前去和他交流。我們一起騎自行車從北大到還未開放的鳥巢、水立方,途中得到了他的不少指點,也得知他來自山西,競賽很弱的地方。後來我出其不意地拿了NOI2009的金牌,也像他一樣成爲了我當年想都不敢想的國家集訓隊成員,而且我竟然成了十幾年來河南第一個拿信息學競賽金牌的。來到清華以後,他把他大一的幾乎所有課本送給了我,指點我選課,還幫助我破解了輔導員對寢室網絡的封鎖,使我(以及我寢室附近的同學)大一一年沒有被實質性地限制住使用網絡。回到剛剛提到地那篇日誌,我看到,即使是像張昆瑋這樣地神級人物,也會被體育考試羈絆,也會體驗「超低空」飛行。我外形雖然看起來和張昆瑋很不一樣,但體育卻也一直是我一塊心病,聽說清華要考三千米,更是心寒。雖然第一學期過後,體育沒有不及格,但也算是「超低空飛行」了。

和我預料的一樣,一開學我學習微積分就遇到了很大的困難,尤其是我高中數學學的公式已經忘了個差不多,更別說沒有經歷過高三瘋狂的技巧性訓練。而我身邊,就有物理競賽金牌獲得者,他們早已學透了微積分,令我感覺簡直是難以望其項背。好在我並不孤單,因爲我身邊也有和我經歷差不多的人。

說實話,還沒開始軍訓我就後悔當時沒選擇去北大了。原因有很多,最主要的莫過於是清華過於強調「集體觀念」,經常強迫人做毫無意義的事情。這裏我認爲「毫無意義」的事情,別人也許並不這麼覺得,這也是體現了價值觀的差異。我不喜歡的是清華對「異端」的容忍程度要遠遠小於北大。後來我看到一篇文章,說清華人和北大人的差異,大致意思是清華人最大的特點是抱團,北大人各個卻像是獨行俠一樣。清華人創辦的企業,排他性非常強,北大人很難任職高層,而相反卻不一樣。漸漸我也明白了,所謂「傳統」是如何產生的。清華並非外界傳說的那樣封閉保守,但其兼容性真的有待於提高。一年下來,如果讓我重新選擇一次,我還會選擇清華。不知道爲什麼,也許祗是懼怕重來一次吧。

大一第一個學期的選課看起來很有遠見,因爲我空出了週五一天來。這樣,我的週末就有連續三天,可以做更多的事情了。祗可惜,我的想法還是太天真,因爲當時第一個學期每週六上午都要被迫去上「軍事理論」課,而週六晚上又要上「語音學」課,這樣我的三天就被攔腰截斷。第一個學期,我不知道花了多少冤枉的時間,我都不知道幹什麼了,沒有學習,沒有打遊戲,沒有看書,沒有外出,沒有鍛煉……仿佛一些時間就憑空消失了。第二個學期,我繼承我的愛好選了中文系的「音韻學」課,課餘還做了「廣韻查詢系統」,算是非常有意義的事情了。然而「多元微積分」依然是一個折磨人的課,「大學物理」的繼承式授課方式更讓我不能接受。

環顧四周,我發現我的同學們還在延續高中的應試教育的生活,被動地接受知識,大量刷題,準備考試,然後忘掉。絕大多數人對自己的未來完全沒有看法,不是相信「車到山前必有路」,就是認爲隨大流就行了。輔導員也在向我們灌輸着一種扭曲的價值觀:「學分積最好的出國,學分積一般的保研,學分積最差的就業。」我不止一次地問自己、問同學、問學長、問老師,究竟爲什麼要學那些「沒用」的課?大多數答復是,爲了培養科學思維,清華計算機系不是像社會上的培訓班一樣培養「碼農」的。更有實際的說:爲了通過考試,爲了拿到畢業證,爲了學分積。可是,很少有人想過自己爲什麼需要科學思維,應試教育培養的是科學思維嗎?如果你將來搞研究靠的是應試教育灌輸的這一套,那麼我相信你的前途是暗淡的。况且,你真的會去搞研究嗎?可悲的是,我接觸到的大多數人對科研的熱情,已經在應試教育的摧殘下消磨殆盡:「將來死也不會去搞研究,把自己在象牙塔裏面關一輩子。」不少人說,學分積什麼的都是浮雲,但往往很多人不知道學分積爲什麼是浮雲,也並沒有真的把學分積當作浮雲。看重學分積的人,多數是對未來很迷茫的人,不知道目標如何,所以覺得有了學分積這個法寶,將來肯定不會喫虧。多年後這些人還會作爲過來人指引後輩們說:「一定要學分積高高的纔行啊。」而作爲後輩們看這些人,覺得他們步伐穩健,必定是好路子,所以亦步亦趨。我一向不喜歡的,就是這種所謂「平步青雲」的生活,殊不知浪費了多少青春在這種平淡無味的日子裏,老來難道不會後悔自己虛度了自己本該不平淡的青春嗎?這些簡單的想法我也和不少同學探討過,但我並不是試圖說服一個價值觀和我不一樣的人,祗是希望能够喚醒同道中人而已。

有意思的是,我的學分積雖然不怎麼樣,卻還是有不少人把我當成「大牛」。這也是令我欣慰的一點,因爲要麼是學分積尚沒有成爲清華人的惟一價值標準,要麼是學院足够尊重隱私,以至於大多數人不知道我學分積如何。我是一個處事高調的人,有很強的表現欲,希望取得別人的關注,認同,或者反對,都對我來說是一種鼓勵。有時候,有些行爲會被人看作是反常,但這又何妨?引用唐寅詩句:「別人笑我太瘋癲,我笑他人看不穿。不見五陵豪杰墓,無花無酒鋤作田。」

一個朋友在他29歲生日的時候,給過他年輕的朋友們一句話:「Gaudeāmus igitur, iuvenēs dum sumus(拉丁文)」,翻譯是「在我們還年輕的時候,讓我們快樂吧。」,換成一首詩就是「花開堪折直須折,莫待無花空折枝。」想想看,我們正當人生中最美好的歲月,爲什麼不去做自己喜歡的事情呢?不要被所謂的現實羈絆,試想人在年輕的時候如果還有如此多的「不能」,那麼將來的「不能」祗會更多。所以,大膽去做吧,無需後悔。

最後,附上兩張難得的合影,一張是我計零二班,一張是計算機系2010級全體。背後是2011年百年校慶期間落成的「新清華學堂」。

計零二班

湯汝鳴 林源 魏凌宇
李曉瀟 林楠 謝宇軒 陳高遠 許皓宇 葛俊翔 劉思奇 劉藝寧
倉馥芝 黃劍 孫偉倫 王柱人 莫濤 蔣林浩 金臨霄 陳凌峰
喬宇宸 郭家寶 韓奕 王鈺 王思思 吳博雅 李愷威 范典

計算機系