日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

咱们一起聊聊Zookeeper

發(fā)布時(shí)間:2025/7/14 48 豆豆
生活随笔 收集整理的這篇文章主要介紹了 咱们一起聊聊Zookeeper 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Google的三篇論文影響了很多很多人,也影響了很多很多系統(tǒng)。這三篇論文一直是分布式領(lǐng)域傳閱的經(jīng)典。根據(jù)MapReduce,于是我們有了Hadoop;根據(jù)GFS,于是我們有了HDFS;根據(jù)BigTable,于是我們有了HBase。而在這三篇論文里都提及Google的一個(gè)Lock Service —— Chubby,哦,于是我們有了Zookeeper。

隨著大數(shù)據(jù)的火熱,Hxx們已經(jīng)變得耳熟能詳,現(xiàn)在作為一個(gè)開發(fā)人員如果都不知道這幾個(gè)名詞出門都好像不好意思跟人打招呼。但實(shí)際上對(duì)我們這些非大數(shù)據(jù)開發(fā)人員而言,Zookeeper是比Hxx們可能接觸到更多的一個(gè)基礎(chǔ)服務(wù)。但是,無(wú)奈的是它一直默默的位于二線,從來(lái)沒有Hxx們那么耀眼。那么到底什么是Zookeeper呢?Zookeeper可以用來(lái)干什么?我們將如何使用Zookeeper?Zookeeper又是怎么實(shí)現(xiàn)的?

什么是Zookeeper

在Zookeeper的官網(wǎng)上有這么一句話:ZooKeeper is a centralized service for maintaining configuration information, naming, providing distributed synchronization, and providing group services。

這大概描述了Zookeeper主要是一個(gè)分布式服務(wù)協(xié)調(diào)框架,實(shí)現(xiàn)同步服務(wù),配置維護(hù)和命名服務(wù)等分布式應(yīng)用。是一個(gè)高性能的分布式數(shù)據(jù)一致性解決方案。

通俗地講,ZooKeeper是動(dòng)物園管理員,它是拿來(lái)管大象 Hadoop、鯨魚 HBase、Kafka等的管理員。

Zookeeper和CAP的關(guān)系

作為一個(gè)分布式系統(tǒng),分區(qū)容錯(cuò)性是一個(gè)必須要考慮的關(guān)鍵點(diǎn)。一個(gè)分布式系統(tǒng)一旦喪失了分區(qū)容錯(cuò)性,也就表示放棄了擴(kuò)展性。因?yàn)樵诜植际较到y(tǒng)中,網(wǎng)絡(luò)故障是經(jīng)常出現(xiàn)的,一旦出現(xiàn)在這種問(wèn)題就會(huì)導(dǎo)致整個(gè)系統(tǒng)不可用是絕對(duì)不能容忍的。所以,大部分分布式系統(tǒng)都會(huì)在保證分區(qū)容錯(cuò)性的前提下在一致性和可用性之間做權(quán)衡。

CAP關(guān)系

ZooKeeper是個(gè)CP(一致性+分區(qū)容錯(cuò)性)的,即任何時(shí)刻對(duì)ZooKeeper的訪問(wèn)請(qǐng)求能得到一致的數(shù)據(jù)結(jié)果,同時(shí)系統(tǒng)對(duì)網(wǎng)絡(luò)分割具備容錯(cuò)性;但是它不能保證每次服務(wù)請(qǐng)求的可用性。也就是在極端環(huán)境下,ZooKeeper可能會(huì)丟棄一些請(qǐng)求,消費(fèi)者程序需要重新請(qǐng)求才能獲得結(jié)果。

ZooKeeper是分布式協(xié)調(diào)服務(wù),它的職責(zé)是保證數(shù)據(jù)在其管轄下的所有服務(wù)之間保持同步、一致;所以就不難理解為什么ZooKeeper被設(shè)計(jì)成CP而不是AP特性的了。而且, 作為ZooKeeper的核心實(shí)現(xiàn)算法Zab,就是解決了分布式系統(tǒng)下數(shù)據(jù)如何在多個(gè)服務(wù)之間保持同步問(wèn)題的。

Zookeeper節(jié)點(diǎn)特性及節(jié)點(diǎn)屬性分析

Zookeeper提供基于類似于文件系統(tǒng)的目錄節(jié)點(diǎn)樹方式的數(shù)據(jù)存儲(chǔ),但是Zookeeper并不是用來(lái)專門存儲(chǔ)數(shù)據(jù)的,它的作用主要是用來(lái)維護(hù)和監(jiān)控你存儲(chǔ)的數(shù)據(jù)的狀態(tài)變化。通過(guò)監(jiān)控這些數(shù)據(jù)狀態(tài)的變化,從而可以達(dá)到基于數(shù)據(jù)的集群管理。

數(shù)據(jù)模型

與Linux文件系統(tǒng)不同的是,Linux文件系統(tǒng)有目錄和文件的區(qū)別,而Zookeeper的數(shù)據(jù)節(jié)點(diǎn)稱為ZNode,ZNode是Zookeeper中數(shù)據(jù)的最小單元,每個(gè)ZNode都可以保存數(shù)據(jù),同時(shí)還可以掛載子節(jié)點(diǎn),因此構(gòu)成了一個(gè)層次化的命名空間,稱為樹。

znode樹形結(jié)構(gòu)圖

Zookeeper中ZNode的節(jié)點(diǎn)創(chuàng)建時(shí)候是可以指定類型的,主要有下面幾種類型。

PERSISTENT:持久化ZNode節(jié)點(diǎn),一旦創(chuàng)建這個(gè)ZNode點(diǎn)存儲(chǔ)的數(shù)據(jù)不會(huì)主動(dòng)消失,除非是客戶端主動(dòng)的delete。

EPHEMERAL:臨時(shí)ZNode節(jié)點(diǎn),Client連接到Zookeeper Service的時(shí)候會(huì)建立一個(gè)Session,之后用這個(gè)Zookeeper連接實(shí)例創(chuàng)建該類型的znode,一旦Client關(guān)閉了Zookeeper的連接,服務(wù)器就會(huì)清除Session,然后這個(gè)Session建立的ZNode節(jié)點(diǎn)都會(huì)從命名空間消失。總結(jié)就是,這個(gè)類型的znode的生命周期是和Client建立的連接一樣的。

PERSISTENT_SEQUENTIAL:順序自動(dòng)編號(hào)的ZNode節(jié)點(diǎn),這種znoe節(jié)點(diǎn)會(huì)根據(jù)當(dāng)前已近存在的ZNode節(jié)點(diǎn)編號(hào)自動(dòng)加 1,而且不會(huì)隨Session斷開而消失。

EPEMERAL_SEQUENTIAL:臨時(shí)自動(dòng)編號(hào)節(jié)點(diǎn),ZNode節(jié)點(diǎn)編號(hào)會(huì)自動(dòng)增加,但是會(huì)隨Session消失而消失

Watcher數(shù)據(jù)變更通知

Zookeeper使用Watcher機(jī)制實(shí)現(xiàn)分布式數(shù)據(jù)的發(fā)布/訂閱功能。

Watcher機(jī)制

Zookeeper的Watcher機(jī)制主要包括客戶端線程、客戶端WatcherManager、Zookeeper服務(wù)器三部分。客戶端在向Zookeeper服務(wù)器注冊(cè)的同時(shí),會(huì)將Watcher對(duì)象存儲(chǔ)在客戶端的WatcherManager當(dāng)中。當(dāng)Zookeeper服務(wù)器觸發(fā)Watcher事件后,會(huì)向客戶端發(fā)送通知,客戶端線程從WatcherManager中取出對(duì)應(yīng)的Watcher對(duì)象來(lái)執(zhí)行回調(diào)邏輯。

ACL保障數(shù)據(jù)的安全

Zookeeper內(nèi)部存儲(chǔ)了分布式系統(tǒng)運(yùn)行時(shí)狀態(tài)的元數(shù)據(jù),這些元數(shù)據(jù)會(huì)直接影響基于Zookeeper進(jìn)行構(gòu)造的分布式系統(tǒng)的運(yùn)行狀態(tài),如何保障系統(tǒng)中數(shù)據(jù)的安全,從而避免因誤操作而帶來(lái)的數(shù)據(jù)隨意變更而導(dǎo)致的數(shù)據(jù)庫(kù)異常十分重要,Zookeeper提供了一套完善的ACL權(quán)限控制機(jī)制來(lái)保障數(shù)據(jù)的安全。

我們可以從三個(gè)方面來(lái)理解ACL機(jī)制:權(quán)限模式 Scheme、授權(quán)對(duì)象 ID、權(quán)限 Permission,通常使用"scheme:id:permission"來(lái)標(biāo)識(shí)一個(gè)有效的ACL信息。

內(nèi)存數(shù)據(jù)

Zookeeper的數(shù)據(jù)模型是樹結(jié)構(gòu),在內(nèi)存數(shù)據(jù)庫(kù)中,存儲(chǔ)了整棵樹的內(nèi)容,包括所有的節(jié)點(diǎn)路徑、節(jié)點(diǎn)數(shù)據(jù)、ACL信息,Zookeeper會(huì)定時(shí)將這個(gè)數(shù)據(jù)存儲(chǔ)到磁盤上。

DataTree:DataTree是內(nèi)存數(shù)據(jù)存儲(chǔ)的核心,是一個(gè)樹結(jié)構(gòu),代表了內(nèi)存中一份完整的數(shù)據(jù)。DataTree不包含任何與網(wǎng)絡(luò)、客戶端連接及請(qǐng)求處理相關(guān)的業(yè)務(wù)邏輯,是一個(gè)獨(dú)立的組件。

DataNode:DataNode是數(shù)據(jù)存儲(chǔ)的最小單元,其內(nèi)部除了保存了結(jié)點(diǎn)的數(shù)據(jù)內(nèi)容、ACL列表、節(jié)點(diǎn)狀態(tài)之外,還記錄了父節(jié)點(diǎn)的引用和子節(jié)點(diǎn)列表兩個(gè)屬性,其也提供了對(duì)子節(jié)點(diǎn)列表進(jìn)行操作的接口。

ZKDatabase:Zookeeper的內(nèi)存數(shù)據(jù)庫(kù),管理Zookeeper的所有會(huì)話、DataTree存儲(chǔ)和事務(wù)日志。ZKDatabase會(huì)定時(shí)向磁盤dump快照數(shù)據(jù),同時(shí)在Zookeeper啟動(dòng)時(shí),會(huì)通過(guò)磁盤的事務(wù)日志和快照文件恢復(fù)成一個(gè)完整的內(nèi)存數(shù)據(jù)庫(kù)。

Zookeeper的實(shí)現(xiàn)原理分析

1. Zookeeper Service網(wǎng)絡(luò)結(jié)構(gòu)

Zookeeper的工作集群可以簡(jiǎn)單分成兩類,一個(gè)是Leader,唯一一個(gè),其余的都是follower,如何確定Leader是通過(guò)內(nèi)部選舉確定的。

Zookeeper架構(gòu)圖

Leader和各個(gè)follower是互相通信的,對(duì)于Zookeeper系統(tǒng)的數(shù)據(jù)都是保存在內(nèi)存里面的,同樣也會(huì)備份一份在磁盤上。

如果Leader掛了,Zookeeper集群會(huì)重新選舉,在毫秒級(jí)別就會(huì)重新選舉出一個(gè)Leader。

集群中除非有一半以上的Zookeeper節(jié)點(diǎn)掛了,Zookeeper Service才不可用。

2. Zookeeper讀寫數(shù)據(jù)

zk讀取數(shù)據(jù)流程

寫數(shù)據(jù),一個(gè)客戶端進(jìn)行寫數(shù)據(jù)請(qǐng)求時(shí),如果是follower接收到寫請(qǐng)求,就會(huì)把請(qǐng)求轉(zhuǎn)發(fā)給Leader,Leader通過(guò)內(nèi)部的Zab協(xié)議進(jìn)行原子廣播,直到所有Zookeeper節(jié)點(diǎn)都成功寫了數(shù)據(jù)后(內(nèi)存同步以及磁盤更新),這次寫請(qǐng)求算是完成,然后Zookeeper Service就會(huì)給Client發(fā)回響應(yīng)。

讀數(shù)據(jù),因?yàn)榧褐兴械腪ookeeper節(jié)點(diǎn)都呈現(xiàn)一個(gè)同樣的命名空間視圖(就是結(jié)構(gòu)數(shù)據(jù)),上面的寫請(qǐng)求已經(jīng)保證了寫一次數(shù)據(jù)必須保證集群所有的Zookeeper節(jié)點(diǎn)都是同步命名空間的,所以讀的時(shí)候可以在任意一臺(tái)Zookeeper節(jié)點(diǎn)上。

3. Zookeeper工作原理

Zab協(xié)議

Zookeeper的核心是廣播,這個(gè)機(jī)制保證了各個(gè)Server之間的同步。實(shí)現(xiàn)這個(gè)機(jī)制的協(xié)議叫做Zab協(xié)議。

Zab(ZooKeeper Atomic Broadcast)原子消息廣播協(xié)議作為數(shù)據(jù)一致性的核心算法,Zab協(xié)議是專為Zookeeper設(shè)計(jì)的支持崩潰恢復(fù)原子消息廣播算法。

Zab協(xié)議核心如下:

所有的事務(wù)請(qǐng)求必須一個(gè)全局唯一的服務(wù)器(Leader)來(lái)協(xié)調(diào)處理,集群其余的服務(wù)器稱為follower服務(wù)器。Leader服務(wù)器負(fù)責(zé)將一個(gè)客戶端請(qǐng)求轉(zhuǎn)化為事務(wù)提議(Proposal),并將該proposal分發(fā)給集群所有的follower服務(wù)器。之后Leader服務(wù)器需要等待所有的follower服務(wù)器的反饋,一旦超過(guò)了半數(shù)的follower服務(wù)器進(jìn)行了正確反饋后,那么Leader服務(wù)器就會(huì)再次向所有的follower服務(wù)器分發(fā)commit消息,要求其將前一個(gè)proposal進(jìn)行提交。

Zab模式

Zab協(xié)議包括兩種基本的模式:崩潰恢復(fù)和消息廣播。

當(dāng)整個(gè)服務(wù)框架啟動(dòng)過(guò)程中或Leader服務(wù)器出現(xiàn)網(wǎng)絡(luò)中斷、崩潰退出與重啟等異常情況時(shí),Zab協(xié)議就會(huì)進(jìn)入恢復(fù)模式并選舉產(chǎn)生新的Leader服務(wù)器。

當(dāng)選舉產(chǎn)生了新的Leader服務(wù)器,同時(shí)集群中已經(jīng)有過(guò)半的機(jī)器與該Leader服務(wù)器完成了狀態(tài)同步之后,Zab協(xié)議就會(huì)退出恢復(fù)模式,狀態(tài)同步是指數(shù)據(jù)同步,用來(lái)保證集群在過(guò)半的機(jī)器能夠和Leader服務(wù)器的數(shù)據(jù)狀態(tài)保持一致。

當(dāng)集群中已經(jīng)有過(guò)半的Follower服務(wù)器完成了和Leader服務(wù)器的狀態(tài)同步,那么整個(gè)服務(wù)框架就可以進(jìn)入消息廣播模式。

當(dāng)一臺(tái)同樣遵守Zab協(xié)議的服務(wù)器啟動(dòng)后加入到集群中,如果此時(shí)集群中已經(jīng)存在一個(gè)Leader服務(wù)器在負(fù)責(zé)進(jìn)行消息廣播,那么加入的服務(wù)器就會(huì)自覺地進(jìn)入數(shù)據(jù)恢復(fù)模式:找到Leader所在的服務(wù)器,并與其進(jìn)行數(shù)據(jù)同步,然后一起參與到消息廣播流程中去。

Zookeeper只允許唯一的一個(gè)Leader服務(wù)器來(lái)進(jìn)行事務(wù)請(qǐng)求的處理,Leader服務(wù)器在接收到客戶端的事務(wù)請(qǐng)求后,會(huì)生成對(duì)應(yīng)的事務(wù)提議并發(fā)起一輪廣播協(xié)議,而如果集群中的其他機(jī)器收到客戶端的事務(wù)請(qǐng)求后,那么這些非Leader服務(wù)器會(huì)首先將這個(gè)事務(wù)請(qǐng)求轉(zhuǎn)發(fā)給Leader服務(wù)器。

消息廣播

消息廣播

Zab協(xié)議的消息廣播過(guò)程使用是一個(gè)原子廣播協(xié)議,類似一個(gè)2PC提交過(guò)程。具體的:

ZooKeeper使用單一主進(jìn)程Leader用于處理客戶端所有事務(wù)請(qǐng)求,并采用Zab的原子廣播協(xié)議,將服務(wù)器數(shù)據(jù)狀態(tài)變更以事務(wù)Proposal的形式廣播Follower上,因此能很好的處理客戶端的大量并發(fā)請(qǐng)求。

另一方面,由于事務(wù)間可能存在著依賴關(guān)系,Zab協(xié)議保證Leader廣播的變更序列被順序的處理,有些狀態(tài)的變更必須依賴于比它早生成的那些狀態(tài)變更。

最后,考慮到主進(jìn)程Leader在任何時(shí)候可能崩潰或者異常退出, 因此Zab協(xié)議還要Leader進(jìn)程崩潰的時(shí)候可以重新選出Leader并且保證數(shù)據(jù)的完整性;Follower收到Proposal后,寫到磁盤,返回Ack。Leader收到大多數(shù)ACK后,廣播Commit消息,自己也提交該消息。Follower收到Commit之后,提交該消息。

Zab協(xié)議簡(jiǎn)化了2PC事務(wù)提交:

去除中斷邏輯移除,follower要么ack,要么拋棄Leader。

Leader不需要所有的Follower都響應(yīng)成功,只要一個(gè)多數(shù)派Ack即可。

崩潰恢復(fù)

上面我們講了Zab協(xié)議在正常情況下的消息廣播過(guò)程,那么一旦Leader服務(wù)器出現(xiàn)崩潰或者與過(guò)半的follower服務(wù)器失去聯(lián)系,就進(jìn)入崩潰恢復(fù)模式。

恢復(fù)模式需要重新選舉出一個(gè)新的Leader,讓所有的Server都恢復(fù)到一個(gè)正確的狀態(tài)。

Zookeeper實(shí)踐,共享鎖,Leader選舉

分布式鎖用于控制分布式系統(tǒng)之間同步訪問(wèn)共享資源的一種方式,可以保證不同系統(tǒng)訪問(wèn)一個(gè)或一組資源時(shí)的一致性,主要分為排它鎖和共享鎖。

排它鎖又稱為寫鎖或獨(dú)占鎖,若事務(wù)T1對(duì)數(shù)據(jù)對(duì)象O1加上了排它鎖,那么在整個(gè)加鎖期間,只允許事務(wù)T1對(duì)O1進(jìn)行讀取和更新操作,其他任何事務(wù)都不能再對(duì)這個(gè)數(shù)據(jù)對(duì)象進(jìn)行任何類型的操作,直到T1釋放了排它鎖。

獨(dú)占鎖

共享鎖又稱為讀鎖,若事務(wù)T1對(duì)數(shù)據(jù)對(duì)象O1加上共享鎖,那么當(dāng)前事務(wù)只能對(duì)O1進(jìn)行讀取操作,其他事務(wù)也只能對(duì)這個(gè)數(shù)據(jù)對(duì)象加共享鎖,直到該數(shù)據(jù)對(duì)象上的所有共享鎖都被釋放。

共享鎖

Leader選舉

Leader選舉是保證分布式數(shù)據(jù)一致性的關(guān)鍵所在。當(dāng)Zookeeper集群中的一臺(tái)服務(wù)器出現(xiàn)以下兩種情況之一時(shí),需要進(jìn)入Leader選舉。

服務(wù)器初始化啟動(dòng)。

服務(wù)器運(yùn)行期間無(wú)法和Leader保持連接。

Zookeeper在3.4.0版本后只保留了TCP版本的 FastLeaderElection 選舉算法。當(dāng)一臺(tái)機(jī)器進(jìn)入Leader選舉時(shí),當(dāng)前集群可能會(huì)處于以下兩種狀態(tài):

集群中已存在Leader。

集群中不存在Leader。

對(duì)于集群中已經(jīng)存在Leader而言,此種情況一般都是某臺(tái)機(jī)器啟動(dòng)得較晚,在其啟動(dòng)之前,集群已經(jīng)在正常工作,對(duì)這種情況,該機(jī)器試圖去選舉Leader時(shí),會(huì)被告知當(dāng)前服務(wù)器的Leader信息,對(duì)于該機(jī)器而言,僅僅需要和Leader機(jī)器建立起連接,并進(jìn)行狀態(tài)同步即可。

而在集群中不存在Leader情況下則會(huì)相對(duì)復(fù)雜,其步驟如下:

(1) 第一次投票。無(wú)論哪種導(dǎo)致進(jìn)行Leader選舉,集群的所有機(jī)器都處于試圖選舉出一個(gè)Leader的狀態(tài),即LOOKING狀態(tài),LOOKING機(jī)器會(huì)向所有其他機(jī)器發(fā)送消息,該消息稱為投票。投票中包含了SID(服務(wù)器的唯一標(biāo)識(shí))和ZXID(事務(wù)ID),(SID, ZXID)形式來(lái)標(biāo)識(shí)一次投票信息。假定Zookeeper由5臺(tái)機(jī)器組成,SID分別為1、2、3、4、5,ZXID分別為9、9、9、8、8,并且此時(shí)SID為2的機(jī)器是Leader機(jī)器,某一時(shí)刻,1、2所在機(jī)器出現(xiàn)故障,因此集群開始進(jìn)行Leader選舉。在第一次投票時(shí),每臺(tái)機(jī)器都會(huì)將自己作為投票對(duì)象,于是SID為3、4、5的機(jī)器投票情況分別為(3, 9),(4, 8), (5, 8)。

(2) 變更投票。每臺(tái)機(jī)器發(fā)出投票后,也會(huì)收到其他機(jī)器的投票,每臺(tái)機(jī)器會(huì)根據(jù)一定規(guī)則來(lái)處理收到的其他機(jī)器的投票,并以此來(lái)決定是否需要變更自己的投票,這個(gè)規(guī)則也是整個(gè)Leader選舉算法的核心所在,其中術(shù)語(yǔ)描述如下

vote_sid:接收到的投票中所推舉Leader服務(wù)器的SID。

vote_zxid:接收到的投票中所推舉Leader服務(wù)器的ZXID。

self_sid:當(dāng)前服務(wù)器自己的SID。

self_zxid:當(dāng)前服務(wù)器自己的ZXID。

每次對(duì)收到的投票的處理,都是對(duì)(vote_sid, vote_zxid)和(self_sid, self_zxid)對(duì)比的過(guò)程。

規(guī)則一:如果vote_zxid大于self_zxid,就認(rèn)可當(dāng)前收到的投票,并再次將該投票發(fā)送出去。

規(guī)則二:如果vote_zxid小于self_zxid,那么堅(jiān)持自己的投票,不做任何變更。

規(guī)則三:如果vote_zxid等于self_zxid,那么就對(duì)比兩者的SID,如果vote_sid大于self_sid,那么就認(rèn)可當(dāng)前收到的投票,并再次將該投票發(fā)送出去。

規(guī)則四:如果vote_zxid等于self_zxid,并且vote_sid小于self_sid,那么堅(jiān)持自己的投票,不做任何變更。

結(jié)合上面規(guī)則,給出下面的集群變更過(guò)程。

Leader選舉

(3) 確定Leader。經(jīng)過(guò)第二輪投票后,集群中的每臺(tái)機(jī)器都會(huì)再次接收到其他機(jī)器的投票,然后開始統(tǒng)計(jì)投票,如果一臺(tái)機(jī)器收到了超過(guò)半數(shù)的相同投票,那么這個(gè)投票對(duì)應(yīng)的SID機(jī)器即為L(zhǎng)eader。此時(shí)Server3將成為L(zhǎng)eader。

由上面規(guī)則可知,通常那臺(tái)服務(wù)器上的數(shù)據(jù)越新(ZXID會(huì)越大),其成為L(zhǎng)eader的可能性越大,也就越能夠保證數(shù)據(jù)的恢復(fù)。如果ZXID相同,則SID越大機(jī)會(huì)越大。



總結(jié)

以上是生活随笔為你收集整理的咱们一起聊聊Zookeeper的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。