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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

Zookeeper与Paxos

發(fā)布時間:2025/3/15 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Zookeeper与Paxos 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

初識Zookeeper

  • zookeeper為分布式應用提供了高效且可靠的分布式協(xié)調(diào)服務,提供了諸如統(tǒng)一命名服務、配置管理和分布式鎖等分布式的基礎(chǔ)服務。
  • 在解決分布式數(shù)據(jù)一致性方面,zk沒有直接采用Paxos算法,而是采用了一種被稱為ZAB(Zookeeper Atomic Broadcast)的一致性協(xié)議。
  • zk可以保證如下分布式一致性特性:
    • 順序一致性:從同一個client發(fā)起的事務請求,最終會被嚴格按照發(fā)起順序被應用到zk中。 --> through為每個請求分配一個全局唯一的遞增編號。
    • 原子性:所有事務請求的處理結(jié)果在整個集群中所有機器上的應用情況一致。
    • 單一視圖:無論client連接哪個zk server,其看到的服務端數(shù)據(jù)模型都是一致的。
    • 可靠性:一旦server端成功應用了一個事務,并成功對client響應,那么該事務所引起的服務端狀態(tài)變更會被一直保存,知道另一個事務變更。
    • 實時性:zk僅保證在一定時間段內(nèi),client最終一定能從server上讀取到最新的數(shù)據(jù)狀態(tài)。

zk設(shè)計目標

  • 簡單的數(shù)據(jù)模型:zk使得分布式程序能夠通過一個共享的、樹形結(jié)構(gòu)的名字空間來進行相互協(xié)調(diào)。
  • 可以構(gòu)建集群:集群中只要有超過一半的機器能正常工作,集群就能對外提供服務。client會和集群中任意一臺機器建立TCP連接,斷開后,client會自動連接到另一臺機器。 ? --> 可用性up
  • 順序訪問:對于client的每個更新請求,zk都會分配一個全局唯一的遞增編號,該編號反應了所有事務操作的先后順序,app可以用zk的這個特性來實現(xiàn)更高層次的同步原語。
  • 高性能:zk將全量數(shù)據(jù)存儲在內(nèi)存中,并直接服務client的所有非事務請求,因此尤其適用于以讀操作為主的應用場景

zk的基本概念

集群角色

  • 集群角色:最典型的集群模式是Master/Slave模式。能夠處理寫操作的稱為master,所以通過異步復制方式獲取最新數(shù)據(jù)并提供讀服務的為slave。
  • zk中沒有沿用傳統(tǒng)的主從模式,而是引入了Leader、Follower和Observer三種角色
  • zk中所有機器通過一個leader選舉過程來選定一臺被稱為leader的機器,leader server為client提供讀寫服務
  • follower和observer都能提供讀服務,唯一區(qū)別在于observer不參與leader選舉過程,也不參與寫操作的“過半寫成功”策略。因此,observer在不影響寫性能的情況下提升集群的讀性能

會話(Session)

  • 在zk中,一個客戶端連接是指client和server之間的一個TCP長連接
  • 通過這個連接,client可以通過心跳檢測與服務器保持有效的會話,也能夠向zk server發(fā)送請求并接受響應。
  • Session的 sessionTimeout值用來設(shè)置一個客戶端會話的超時時間。當服務器壓力太大、網(wǎng)絡(luò)故障或是客戶端主動斷開連接等各種原因?qū)е耤lient連接斷開時,只要在sessionTimeout 時間內(nèi)能夠重新連接上集群中任意一臺服務器,那么之前創(chuàng)建的會話仍然有效。

數(shù)據(jù)節(jié)點(Znode)

  • zk中的節(jié)點,一類是構(gòu)建集群的機器,稱為機器節(jié)點;另一類則是數(shù)據(jù)模型中的數(shù)據(jù)單元,稱為數(shù)據(jù)節(jié)點ZNode。
  • zk將所有數(shù)據(jù)存儲在內(nèi)存中,數(shù)據(jù)模型是一棵樹(ZNode Tree)。
  • 每個znode上會保存自己的數(shù)據(jù)內(nèi)容,同時還會保存一系列屬性信息
  • zk還允許每個節(jié)點添加一個特殊的屬性:SEQUENTIAL。該屬性是一個整形數(shù)字,是一個由父節(jié)點維護的自增數(shù)字。

版本

  • 對于每個znode,zk都會為其維護一個叫做Stat的數(shù)據(jù)結(jié)構(gòu),Stat記錄了該Znode的三個數(shù)據(jù)版本,分別是version(當前znode的版本)、cversion(當前znode子節(jié)點的版本)和aversion(當前znode的ACL版本)。

Watcher

  • Watcher(事件監(jiān)聽器)是zk中一個很重要的特性。zk允許用戶在指定節(jié)點上注冊一些watcher,并在一些特定事件觸發(fā)時通知感興趣的client。

ACL

  • zk采用ACL(Access Control Lists)策略來進行權(quán)限控制。

ZK的ZAB協(xié)議

ZAB協(xié)議

  • 事實上,zk并沒有完全采用Paxos算法,而是使用了Zookeeper Atomic Broadcast即zk原子消息廣播協(xié)議作為其數(shù)據(jù)一致性的核心算法。
  • ZAB是為zk專門設(shè)計的支持崩潰恢復的原子廣播協(xié)議
  • zk主要依賴ZAB協(xié)議來實現(xiàn)分布式數(shù)據(jù)的一致性。基于該協(xié)議,zk實現(xiàn)了一種主備模式的系統(tǒng)架構(gòu)來保持集群中各副本之間數(shù)據(jù)的一致性
    • 具體的,zk使用一個單一的主進程來接收并處理client的所有事務請求,并采用ZAB的原子廣播協(xié)議,將server數(shù)據(jù)的狀態(tài)變更以事務Proposal的形式廣播到所有的副本進程上。
    • 由于順序執(zhí)行的狀態(tài)變更前后會存在一定的依賴關(guān)系,ZAB協(xié)議需要保證若一個狀態(tài)變更被處理時,所有其依賴的狀態(tài)變更都應該已經(jīng)被處理了。 ?--> 順序性
    • 考慮到主進程可能崩潰,ZAB協(xié)議還需要在主進程崩潰時保持正常工作。 ?--> 高可用性

?協(xié)議介紹

  • ZAB協(xié)議包括兩種基本的模式,分別是崩潰恢復和消息廣播。
  • 當整個服務框架在啟動過程中,或是當leader服務器出現(xiàn)網(wǎng)絡(luò)中斷、崩潰退出與重啟等異常情況時,ZAB協(xié)議就會進入恢復模式并選舉產(chǎn)生新的Leader服務器。當選舉產(chǎn)生了新的Leader服務器,同時集群中已有過半的機器(follower)與Leader完成狀態(tài)同步(即數(shù)據(jù)同步,用以保證集群中存在過半的機器與leader的數(shù)據(jù)狀態(tài)保持一致)后,退出恢復模式。
  • 過半機器同步完成后,整個服務框架就可以進入消息廣播模式了。啟動后新加入的機器會自覺進入數(shù)據(jù)恢復模式(即找到leader并進行數(shù)據(jù)同步)。
  • leader server是唯一允許處理事務請求的機器,若其他機器接收到client的事務請求,會將該請求轉(zhuǎn)發(fā)給leader。接著,leader會生成相應的事務提案并發(fā)起一輪廣播協(xié)議。

消息廣播

  • ZAB協(xié)議的消息廣播過程使用的是一個原子廣播協(xié)議,類似于一個二階段提交過程。
  • 當過半的follower反饋Ack之后就可以提交事務Proposal了。
  • 但是該模型無法處理leader崩潰退出而帶來的數(shù)據(jù)不一致問題。因此,在ZAB協(xié)議中添加了另一模式,即采用崩潰恢復模式來解決這個問題。
  • 另外,整個消息廣播協(xié)議是基于具有FIFO特性的TCP協(xié)議來進行網(wǎng)絡(luò)通信的,因此能夠很容易地保證消息廣播過程中消息接收與發(fā)送的順序性。(zk采用單一主線程來處理client請求)
  • 在整個消息廣播過程中,leader服務器會為每個事物請求生成對應的Proposal來進行廣播,并且在廣播事務Proposal之前,為proposal分配一個全局單調(diào)遞增的唯一ID,即事務ID(ZXID)
  • 具體而言,在消息廣播過程中,leader server會為每個follower分配一個單獨的隊列,然后將需要廣播的事務proposal依次放入這些隊列中,并且根據(jù)FIFO策略發(fā)送消息。每個follower接收到proposal后,會首先將其以事務日志形式寫入本地磁盤,并且在成功寫入后反饋給leader。當leader收到超過半數(shù)的ack后,會廣播一個commit消息給所有的follower以通知其進行事務提交,同時leader自身也會完成對事務的提交,而follower也會在接收到commit消息后,完成對事務的提交。 My Summary: 從上述具體的流程可以看到,整個消息廣播流程本質(zhì)上是一個2PC過程:
    • Phase1: leader發(fā)送事務proposal --> follower將proposal以事務形式寫入本地磁盤,并且反饋ack給leader。
    • Phase2: leader在收到半數(shù)ack后,會廣播一個commit消息給所有follower --> leader完成事務提交 --> follower完成事務的提交。
    My Summary: 回顧一下2PC的幾個固有缺點是:同步阻塞大大降低了系統(tǒng)性能、coordinator單點故障、coordinator崩潰可能引發(fā)數(shù)據(jù)不一致。
    • 過半follower寫入成功,可以提高系統(tǒng)可用性,即在leader崩潰之后可以選擇數(shù)據(jù)一致的follower替換當前l(fā)eader。而只需要過半寫入成功,也可以提高整個過程的效率,縮短阻塞時間。(zk在整個過程中并沒有阻塞,是通過為每個follower維護一個proposal queue,并且用TCP來保證FIFO。)
    • 這個過程中,為了保證事務的順序性,為每個事務proposal分配了全局唯一的ZXID,發(fā)送端以FIFO的方式發(fā)送proposal,并且使用一個單一的主線程以TCP協(xié)議發(fā)送事務,從這兩個方面保證了事務發(fā)送&接收的順序性。
    • 除了上述兩個方面,zk還需要解決2PC帶來的單點故障和數(shù)據(jù)不一致的問題,這就引入了下面一小節(jié)要介紹的“崩潰恢復”啦。

崩潰恢復

  • zk中一旦leader崩潰(或者可能是由于網(wǎng)絡(luò)原因?qū)е耹eader失去了與過半follower的聯(lián)系),那么就會進入崩潰恢復模式
  • 在ZAB協(xié)議中,為保證程序的正確運行,整個恢復過程結(jié)束后需要選舉出一個新的leader server。因此,ZAB協(xié)議需要一個高效且可靠的leader選舉算法。leader選舉算法需要保證leader以及集群中其他機器都知道誰是leader。
  • 由上一小節(jié)了解到,zk本質(zhì)上類似于一個2PC的過程,而崩潰恢復就是為了應對2PC存在的“單點故障”和“數(shù)據(jù)不一致問題”的。
    • 其中,“單點故障”是通過leader selection來處理的,也就是說在leader崩潰(失去與過半follower聯(lián)系)時會進入崩潰恢復模式。
    • 而對于數(shù)據(jù)不一致問題,我們首先考慮可能產(chǎn)生數(shù)據(jù)不一致的情況:
      在zk處理事務的流程中(具體見上一小節(jié)),考慮所有l(wèi)eader可能崩潰的時間點,可以發(fā)現(xiàn):
      • leader發(fā)生proposal后崩潰:則leader有proposal,而follower中沒有(本地磁盤)。
      • leader在發(fā)送commit消息前崩潰:則leader提交了proposal,而follower未提交。

基本特性

  • 在崩潰過程中,可能會出現(xiàn)的兩個數(shù)據(jù)不一致的隱患及針對這些情況ZAB協(xié)議所需要保證的特性。
  • ZAB協(xié)議需要保證那些已經(jīng)在leader server上提交的事務最終被所有server都提交
    • 假設(shè)一個事務已經(jīng)得到過半follower的ack,并且已經(jīng)在leader上被提交了,但是在它將commit消息發(fā)送給所有follower之前,leader掛了。
      比如,leader先后廣播了P1、P2、C1、P3和C2,其中,當leader將C2(Commit of Proposal2)發(fā)出后就立即崩潰退出了,針對這種情況,ZAB協(xié)議需要確保proposal2最終能夠在所有的服務器上都被提交成功,否則將出現(xiàn)不一致。
  • ZAB協(xié)議需要確保丟棄那些只在leader server上被提出的事務
    • 相反,如果崩潰恢復過程中出現(xiàn)一個需要被丟棄的提案,那么崩潰恢復結(jié)束后需要跳過該事務proposal。
      比如,leader在提出了proposal3之后就崩潰退出了,從而導致集群中其他服務器都沒有收到這個事務proposal。于是當server1恢復過來再次加入到集群中時,ZAB協(xié)議需要確保丟棄proposal3這個事務。
  • 結(jié)合上述兩個需求,ZAB協(xié)議必須設(shè)計一個這樣的leader選舉算法:能夠確保提交已經(jīng)被leader提交的事務proposal,同時丟棄已經(jīng)被跳過的事務proposal。因為
    • 已經(jīng)被leader提交的proposal,必定已經(jīng)被超過半數(shù)的follower執(zhí)行,只是可能還未提交。既然已經(jīng)被leader提交,為了保證一致性,需要保證所有follower也提交。
    • 還未被leader提交的proposal,意味著還沒有超過半數(shù)的follower執(zhí)行。既然leader還未提交,那么必定沒有follower提交,那么可以直接丟棄該proposal。
  • Solution:如果leader選舉算法能夠保證新選舉出來的leader服務器擁有集群中所有機器最高編號(即ZXID最大)的事務proposal,那么就可以保證這個新選舉出來的lader一定具有所有已提交的提案。更為重要的是,如果讓具有最高編號事務proposal的機器成為leader,就可以省去leader server檢查proposal的提交和丟棄工作這一操作了。

數(shù)據(jù)同步

  • 完成leader選舉之后,在正式開始工作(即接收客戶端的事務請求,然后提出新的提案)之前,leader server會首先確認事務日志中的所有proposal是否都已經(jīng)被集群中過半的機器提交了,即是否完成數(shù)據(jù)同步
  • 下面來看ZAB協(xié)議的數(shù)據(jù)同步過程:
    • 首先,leader需要確保所有的follower能夠接收到每一條proposal,并且能正確地將所有已提交的proposal應用到內(nèi)存數(shù)據(jù)庫中去。具體的:
      • leader為每個follower準備一個隊列,并將那么未被各follower同步的事務以proposal消息的形式逐個發(fā)送給follower,并在每個proposal后緊接著一個commit消息,表明該事務已提交
      • 等到follower將其所有尚未同步的事務proposal都從leader上同步過來并成功應用到本地數(shù)據(jù)庫中后,leader會將follower加入到真正的可用follower列表中。
  • 還需要考慮如何處理那些需要被丟棄的事務proposal(即上面一條處理的需要被所有follower提交的事務):
    • ZAB的事務編號ZXID被設(shè)計為一個64位的數(shù)字,其中低32位可以看作一個簡單的單調(diào)遞增的計數(shù)器,leader在產(chǎn)生一個新的proposal的時候,都會加一;而高32位則代表了leader周期epoch的編號,每當產(chǎn)生一個新的leader,就會從這個leader上取出起本地日志的最大事務proposal的ZXID,并從該ZXID中解析出對應的epoch值,然后加1作為新的epoch,并將低32位置0來開始生成新的ZXID。從而,ZAB協(xié)議可以通過epoch編號來區(qū)分leader周期變化的策略,有效避免不同的leader錯誤地使用相同的ZXID編號提出不一樣的proposal的異常情況。
    • 基于這樣的策略,當一個包含了上一個leader周期中尚未提交的proposal的server啟動時肯定無法成為leader,因為其不可能擁有最高ZXID的proposal。那么該server會成為follower,當其連接上leader后,會被leader要求進行回退操作,即回退到一個確實已經(jīng)被集群中過半機器提交的最新的proposal。

深入理解ZAB協(xié)議

  • 前面的內(nèi)容介紹了ZAB協(xié)議的大體內(nèi)容以及在實際運行過程中消息廣播和崩潰恢復這兩個基本模式,下面將從系統(tǒng)模型、問題描述、算法描述和運行分析四方面來深入理解ZAB協(xié)議。

系統(tǒng)模型

  • ZAB協(xié)議需要構(gòu)建的分布式系統(tǒng)模型:
    • 在一個由一組進程 {P1, P2, ..., Pn}組成的分布式系統(tǒng)中,其每個進程都有各自的存儲設(shè)備,進程間通過相互通信來實現(xiàn)消息的傳遞。
    • 每個進程隨時有可能崩潰退出(進入DOWN狀態(tài)),在退出后還有可能再次加入(重新進入UP狀態(tài))。
    • 集群中存在過半的處于UP狀態(tài)的進程組成一個進程子集(Quorum)之后就可以進行正常的消息廣播了。

問題描述

  • zk是一個高可用的分布式協(xié)調(diào)服務,在yahoo的很多大型系統(tǒng)上得到應用。這類應用有個共同的特點,即通常都存在大量的客戶端進程,并且都依賴zk來完成一系列諸如可靠的配置存儲和運行時狀態(tài)記錄等分布式協(xié)調(diào)工作。
  • 因而,zk必須具有高吞吐和低延遲的特性,并且能夠很好地在高并發(fā)情況下完成分布式數(shù)據(jù)的一致性處理,同時能夠優(yōu)雅地處理運行時故障,并具備快速故障恢復的能力。
  • ZAB協(xié)議時整個zk框架的核心所在,其規(guī)定來任何時候都需要保證只有一個主進程負責進行消息廣播,并且在主進程崩潰的時候進行l(wèi)eader選舉。?

事務

  • 假設(shè)各個進程都存在一個類似transaction(v, z)這樣的函數(shù)調(diào)用,來實現(xiàn)主進程對狀態(tài)變更的廣播。主進程每個對transaction(v, z)的調(diào)用都包含了:事務內(nèi)容v和事務標識z,而每個事務標識z又由z = <e, c>兩部分組成,前者是主進程周期e,后者是當前主進程周期內(nèi)的事務計數(shù)c。
  • 針對一個新事務,主進程首先遞增事務計數(shù)c。

算法描述

  • 下面將從算數(shù)描述角度來深入理解ZAB協(xié)議的內(nèi)部原理。
  • 整個ZAB協(xié)議主要包括消息廣播和崩潰恢復兩個過程。進一步可以細分為發(fā)現(xiàn)(discovery)、同步(synchronization)和廣播(broadcast)三個階段。組成ZAB協(xié)議的每一個分布式進程,會循環(huán)地執(zhí)行這三個階段,這樣的一個循環(huán)稱為一個主進程周期
  • 首先,給出ZAB協(xié)議中一些專有術(shù)語的定義

階段一:發(fā)現(xiàn)

  • 階段一主要就是leader選舉過程,用于在多個分布式進程中選舉出主進程,準leader L和follower F的工作流程如下:
    • 步驟F.1.1 follower將自己最后接受的事務proposal的epoch值CEPOCH(F.p)發(fā)送給準leader L
    • 步驟L.1.1 當接收到過半follower的CEPOCH(F.p)消息后,準Leader L會生成NEWEPOCH(e')消息給這些過半的follower
    • 步驟 F.1.2 當follower接收到來自準leader L的NEWPOCH(e')后,如果其檢測到當前的CEPOCH(F.p)值小于e',那么就會將CEPOCH(F.p)賦值為e', 同時向準leader L發(fā)送ack。這個反饋消息(ACK-E(F.p, hf))中,包含了當前該follower的epoch CEPOCH(F.p)以及該follower的歷史proposal集合: hf。
  • 當leader L收到來自過半follower的ack后,L就會從這過半服務器中選舉一個follower,使用其作為初始化事務集合Ie'。
    • 選取方式:對Quorum中其他任意一個Follower F',F需要滿足以下兩個條件之一:
  • 至此,ZAB協(xié)議完成階段一的工作流程。

階段二:同步

  • 步驟 L.2.1 Leader L會將e' 和 Ie' 以NEWLEADER(e', Ie')消息的形式發(fā)送給所有Quorum中的follower。
  • 步驟 F.2.2 當follower接收到來自L的NEWLEADER(e', Ie')消息后,若follower發(fā)現(xiàn)CEPOCH(F.p) 不等于 e',那么直接進入下一輪循環(huán)。若想等,則follower會執(zhí)行事務應用操作。具體的,對于每個事務Proposal:<v, z>屬于Ie',follower會接收<e', <v, z>>。最后反饋給leader,表明自己已經(jīng)接受并處理了所有Ie'中的事務proposal。
  • 步驟 L2.2 當leader接收到來自過半follower針對NEWLEADER(e', Ie')的ack后,就會向所有follower發(fā)commit消息。至此leader完成階段二。
  • 當follower收到leader的commit消息后,會依次處理并提交所有在Ie''中未處理的事務。至此follower完成階段二。

階段三:廣播

  • 完成同步之后,ZAB協(xié)議就可以正式開始接受客戶端的事務請求,并進行消息廣播流程。
  • 步驟 L.3.1 Leader L接收到client新的事務請求后,會生成proposal,并根據(jù)ZXID的順序向所有follower發(fā)送提案<e', <v, z>>,其中epoch(z) = e'。
  • 步驟 F.3.1 follower根據(jù)消息接收的先后次序來處理這些來自leader的事務proposal,并將他們追加到hf中去,之后反饋給leader。
  • 步驟 L.3.1 當leader接收到過半follower的針對proposal?<e', <v, z>>的ack后,就會發(fā)送commit<e', <v, z>>消息給所有follower。
  • 步驟 F.3.2 當follower F接收到來自leader的commit<e', <v, z>>后,會開始提交proposal<e', <v, z>>。需要注意的是,此時follower F必定已經(jīng)提交了事務proposal?<v', z'>, 其中<v', z'> 屬于hf,z' < z。
  • 在正常運行過程中,ZAB協(xié)議會一直運行于階段三來反復地進行消息廣播流程。如果出現(xiàn)leader崩潰或其他原因?qū)е耹eader缺失,ZAB會再次進入階段一。

運行分析

  • 在ZAB協(xié)議的設(shè)計中,每個進程都可能處于以下三種狀態(tài)之一:
    • LOOKING: leader選舉階段
    • FOLLOWING: follower和leader保持同步狀態(tài)
    • LEADING: leader作為主進程領(lǐng)導狀態(tài)

ZAB與Paxos算法的聯(lián)系與區(qū)別

  • ZAB協(xié)議并不是Paxos算法的一個典型實現(xiàn)
  • 兩者的聯(lián)系:
    • 兩者都存在一個類似于leader進程的角色,由其負責協(xié)調(diào)多個follower進程的運行;
    • leader進程會等待超過半數(shù)的follower作出正確的反饋后,才會將一個提案進行提交;
    • 在ZAB協(xié)議中,每個proposal都包含一個epoch值,用以代表當前的leader周期,在Paxos算法中,同樣存在一個這樣的標識,只是名字變成了Ballot。
  • 在Paxos算法中,一個新選舉的主進程會進行兩個階段的工作,第一階段被稱為讀階段,在這個階段中,這個新的主進程會通過和所有其他進程進行通信的方式來收集上一個主進程提出的提案,并將它們提交。第二階段稱為寫階段,在這個階段,當前主進程開始提出自己的提案。
  • ZAB協(xié)議在Paxos基礎(chǔ)上,ZAB額外添加了一個同步階段。在同步階段之前,ZAB協(xié)議也存在一個和Paxos讀階段非常類似的過程,即發(fā)現(xiàn)階段。在同步階段,新的leader會確保存在過半的follower已經(jīng)提交了之前l(fā)eader周期中的所有事務proposal。一旦同步完成之后,ZAB就會執(zhí)行和Paxos類似的寫階段。
  • 總的來說,ZAB和Paxos算法的本質(zhì)區(qū)別在于,兩者的設(shè)計目標不太一樣。ZAB主要用于構(gòu)建一個高可用的分布式數(shù)據(jù)主備系統(tǒng),例如zk。而Paxos算法則是用于構(gòu)建一個分布式的一致性狀態(tài)機系統(tǒng)。

?

轉(zhuǎn)載于:https://www.cnblogs.com/wttttt/p/7500663.html

總結(jié)

以上是生活随笔為你收集整理的Zookeeper与Paxos的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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