敏捷、分布式、ALM過程自動(dòng)化、企業(yè)應(yīng)用架構(gòu)
          posts - 14, comments - 0, trackbacks - 0, articles - 1
            BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

          日歷

          <2012年5月>
          293012345
          6789101112
          13141516171819
          20212223242526
          272829303112
          3456789

          公告

          本博客內(nèi)容均為原創(chuàng)。
          有問題可聯(lián)系郵箱:matuobasyouca@gmail.com

          文章分類(1)

          文章檔案(1)

          搜索

          •  

          最新評(píng)論

          2012年5月15日

          Hadoop實(shí)施已經(jīng)有快一個(gè)月了,對(duì)Hadoop的概念理解、使用,Linux與shell腳本,甚至mysql都有了更多的理解。


          項(xiàng)目背景:用于互聯(lián)網(wǎng)信息收集后的關(guān)鍵詞匹配與內(nèi)容提取。

          主要系統(tǒng)架構(gòu)分為互聯(lián)網(wǎng)爬蟲、分析、業(yè)務(wù)應(yīng)用三塊:

          簡(jiǎn)單架構(gòu)描述

          由于我在當(dāng)中的角色主要負(fù)責(zé)分析架構(gòu)的搭建,所以其他兩塊都畫得簡(jiǎn)單,下面也不會(huì)過多的描述。


          Hadoop理解:提到Hadoop都想到的是云、分布式計(jì)算,在一段時(shí)間的實(shí)施之后有了一些具體的理解。

          Hadoop的優(yōu)勢(shì):

          針對(duì)性能指標(biāo),當(dāng)業(yè)務(wù)數(shù)據(jù)量總量或增速上升到一定級(jí)別,依靠關(guān)系型數(shù)據(jù)庫(kù)一定無法支持。對(duì)于非關(guān)系型數(shù)據(jù)庫(kù),包括Nosql和Solr一類存儲(chǔ)方式,稍顯復(fù)雜,對(duì)于機(jī)器集群性能要求偏高(相對(duì)于文件系統(tǒng))。從數(shù)據(jù)使用模式上來講,目前海量數(shù)據(jù)的常常是不包含復(fù)雜邏輯的簡(jiǎn)單統(tǒng)計(jì)整理(比如上述系統(tǒng)中的關(guān)鍵詞匹配)。這時(shí)候文件系統(tǒng)的優(yōu)勢(shì)反而比較明顯(結(jié)構(gòu)簡(jiǎn)單,邏輯簡(jiǎn)單)。

          如上述系統(tǒng)的應(yīng)用場(chǎng)景是怎么樣的呢,在一個(gè)強(qiáng)大的爬蟲系統(tǒng)之下,每個(gè)小時(shí)的數(shù)據(jù)增量在G到10G的級(jí)別,需要搜索所有的文件,獲取關(guān)鍵字的匹配,并且對(duì)匹配內(nèi)容進(jìn)行摘要。很類似我們windows里面的搜索功能,需要解決的就是如何在這樣增幅的文件系統(tǒng)之下,如何滿足業(yè)務(wù)系統(tǒng)的需求。

          對(duì)分析系統(tǒng)有什么要求呢?

          能夠建立集群,分布式的保存數(shù)據(jù)文件內(nèi)容(統(tǒng)一控制,可配置)。

          有一定的保護(hù)機(jī)制,保證數(shù)據(jù)或節(jié)點(diǎn)丟失不會(huì)影響系統(tǒng)使用。

          如果有一個(gè)任務(wù)腳本執(zhí)行框架機(jī)制就好了(用于并行計(jì)算)。

          能夠進(jìn)行節(jié)點(diǎn)間的數(shù)據(jù)均衡。

          能夠簡(jiǎn)單的查看所有的狀態(tài)與日志(web客戶端)

          可能主要是這些了。若自己實(shí)現(xiàn),確實(shí)是個(gè)復(fù)雜而龐大的工程,現(xiàn)在我們有了Hadoop。


          系統(tǒng)物理架構(gòu):

          我們使用了一臺(tái)服務(wù)器,利用虛擬化,安裝了7套64x位的CentOS。一個(gè)Namenode,6個(gè)Datanode,復(fù)制數(shù)設(shè)置為3。每個(gè)系統(tǒng)分配到一個(gè)cpu,2G內(nèi)存,Datanode掛載了500G的存儲(chǔ)空間。

          理想的Hadoop的搭建環(huán)境,參照《Best Practices for Selecting Apache Hadoop Hardware》(http://hortonworks.com/blog/best-practices-for-selecting-apache-hadoop-hardware/)一文,以及一些其他的文章。

          CPU:最好是雙CPU,8核左右。不用太高了。

          內(nèi)存:推薦48G,但是4G應(yīng)該就可以運(yùn)行Hadoop了。

          硬盤:7200轉(zhuǎn)的SATA硬盤即可,Hadoop很占空間,所以盡量加。

          網(wǎng)絡(luò):內(nèi)部的數(shù)據(jù)交換要求非常高,內(nèi)網(wǎng)最好是千兆網(wǎng)卡,帶寬為1GB。

          理想與現(xiàn)實(shí),有錢與沒錢,呵呵。


          系統(tǒng)軟件架構(gòu):

          Hadoop:版本使用的是1.0.3,再下來就是2了,為了盡量簡(jiǎn)化應(yīng)用,所以不考慮2的新特性。對(duì)Hadoop沒有做太多的設(shè)置,基本基于默認(rèn)。70為Namenode,71-76為Datanode。

          JDK:1.6.0_33 (64x)


          系統(tǒng)實(shí)施過程:

          HDFS部分:

          爬蟲抓取數(shù)據(jù),整理后存放在50文件服務(wù)器,70以外部掛載的形式讀取。網(wǎng)頁(yè)文件比較小,假如直接寫入Hadoop對(duì)Namenode負(fù)載過大,所以入庫(kù)前合并,將每小時(shí)網(wǎng)頁(yè)整合成為一個(gè)文件寫入HDFS,由于區(qū)分類別,所以每小時(shí)基本寫入10個(gè)文件左右,總量在5-8G,耗時(shí)在40-50分鐘。(這個(gè)過程中,由于爬蟲的IO過于頻繁,導(dǎo)致文件讀取困難,所以做了定時(shí)任務(wù),每小時(shí)啟動(dòng)一次,將需要處理的文件先拷貝到臨時(shí)區(qū)域,合并入庫(kù)之后再刪除。此處應(yīng)該是受到單核cpu的限制,所有操作均是串行,包括拷貝(cp)和合并入庫(kù)(java),所以Namenode嚴(yán)重建議配置稍高。)

          此處沒有太多問題。

          MapReduce部分:

          寫入完成后,進(jìn)行分析工作,MapReduce。此處的工作過程為:數(shù)據(jù)庫(kù)定時(shí)生成關(guān)鍵詞列表文件。Job執(zhí)行時(shí)會(huì)讀取列表文件,匹配指定范圍內(nèi)的HDFS文件(過去一小時(shí)),匹配出對(duì)應(yīng)的表達(dá)式與HTML,Map過程結(jié)束。在Reduce階段,會(huì)將Map的所有數(shù)據(jù)入數(shù)據(jù)庫(kù)(Mysql)。

          此處出現(xiàn)過一些問題,記錄下來。

          1. Reduce階段需要加載Mysql的第三方驅(qū)動(dòng)包。我在三個(gè)環(huán)境測(cè)試過(公司、家里、發(fā)布環(huán)境),使用 -libjars 一定可以,有的地方不需要也可以。不明確,懷疑與HADOOP_HOME環(huán)境變量有關(guān)。

          2. MR過程中使用log4j打印日志,在Hadoop臨時(shí)目錄(如果你沒有配置dfs.name.dir,dfs.data.dir,mapred.local.dir.mapred.system.dir等目錄,這些都會(huì)在hadoop.tmp.dir當(dāng)中,我就偷懶都沒配置)mapred文件夾中查看一下。

          整個(gè)過程實(shí)際上還是比較簡(jiǎn)單的,基本編碼量就在Job的部分,但是一個(gè)Java文件就夠了。在目前初級(jí)階段應(yīng)該還是比較好用的。現(xiàn)在還沒有測(cè)試Job的執(zhí)行效率。完成后會(huì)繼續(xù)記錄下來。有什么問題可以提出。我想到什么也會(huì)在本文繼續(xù)更新。

          posted @ 2012-08-08 20:21 一酌散千憂 閱讀(588) | 評(píng)論 (0)編輯 收藏

          硬件資源:

          三臺(tái)CentOS5.6虛擬機(jī)(Vmware

          本機(jī) windows7 64x

           

          基本資源配置:

          三臺(tái)虛擬機(jī)均是克隆自同一個(gè)鏡像

          已經(jīng)安裝了Java環(huán)境(jdk1.6.0_25

          Hadoop路徑在/usr/hadoop/hadoop-0.20.205.0

           

          操作步驟:

          1、機(jī)器名稱規(guī)范

          ip分別為128、129、130,將128設(shè)置為master,其他設(shè)置為slave

          修改

          /etc/sysconfig/network

          /etc/hosts

          兩處配置,名稱分別為hadoop-master\hadoop-slave01\hadoop-slave02

          注意:此處名稱最好不用使用下劃線,有可能引發(fā)namenode的啟動(dòng)異常。

           

          2、修改Hadoop配置 

          master節(jié)點(diǎn)的conf中修改masterslave文件,分別為機(jī)器的ip地址

           

          修改master節(jié)點(diǎn)的conf中:

          core-site.xml

          <property>

          <name>fs.default.name</name>

          <value>hdfs://ip-master:9000</value>

          </property>

           

          mapred-site.xml

          <property>

          <name>mapred.job.tracker</name>                                   

          <value>master:9001</value>                                

          </property>

           

          hdfs-site.xm

          <property>

          <name>dfs.replication</name>

          <value>2</value>

          </property>

          注意此處的端口號(hào)均為默認(rèn)。

           

           

          3、建立m-s之間的ssh連接

          首先masterslave機(jī)器都需要進(jìn)行ssh信任文件生成,執(zhí)行如下命令:

          $ ssh-keygen -t rsa

          中間需要輸入的地方直接回車,接受缺省值即可

           

          由于使用root用戶登錄,所以密鑰文件生成在 /root/.ssh/文件夾下,存有一對(duì)密鑰id_dsaid_dsa.pub。

          此處id_dsa(私鑰)必須為其他用戶不可讀,所以文件屬性應(yīng)當(dāng)是600

           

          master機(jī)器執(zhí)行:

          id_dsa.pub(公鑰)復(fù)制為 authorized_keys

          $ cp id_dsa.pub authorized_keys

          如果是多臺(tái)機(jī)器需要,無密碼登陸,則各自機(jī)器產(chǎn)生公鑰追加到authorized_keys即可.

           

          使用scp協(xié)議覆蓋slave端的密鑰文件夾,使得slave機(jī)器信任來自master的連接:

          $ scp /root/.ssh/* ip-slave:/root/.ssh

           

           

          4、啟動(dòng)服務(wù) 

          建議將$HADOOP_HOME/bin下的所有文件給與執(zhí)行權(quán)限:

          $ chmod 777 bin

           

          master作為namenod需要執(zhí)行如下腳本:

          $HADOOP_HOME/bin/hadoop namenode –format

           

          完成后執(zhí)行 $HADOOP_HOME/bin/start-all.sh

           

          5、問題檢查

          Hadoop根目錄下的logs文件中,檢查各個(gè)服務(wù)日志的啟動(dòng)情況

           

           

          6、其他情況說明:

          Q: $HADOOP_HOME is deprecated

          A: 基本不會(huì)產(chǎn)生任何影響。由于腳本啟動(dòng)時(shí)設(shè)置了該環(huán)境變量,就會(huì)提示用戶原有環(huán)境變量失效。可以取消環(huán)境變量設(shè)置,或者直接去bin/hadoop中找到這句話,去掉即可

           

          Q: 無效的選項(xiàng) -jvm / Unrecognized option: -jvm

          A: 在使用root用戶登錄時(shí) bin/hadoop 腳本就會(huì)進(jìn)行判斷,加上-jvm參數(shù)。此處是為了進(jìn)入jsvchttp://commons.apache.org/daemon/jsvc.html),此處并不確定是否bug,也不再進(jìn)行詳細(xì)的追溯,解決方法就是進(jìn)入 bin/hadoop 腳本中 找到 jvm 參數(shù)并去掉。

           

           

           

           

           

           

           

          posted @ 2012-07-04 07:38 一酌散千憂 閱讀(594) | 評(píng)論 (0)編輯 收藏

          公司里有同事時(shí)常抱怨,項(xiàng)目的用戶體驗(yàn)太差,常常挨領(lǐng)導(dǎo)的罵。大家都認(rèn)為是在用戶體驗(yàn)的設(shè)計(jì)方面,公司人員的能力和經(jīng)驗(yàn)都不足引起的。發(fā)牢騷的時(shí)候也會(huì)說,如果公司能夠請(qǐng)得起“淘寶”的UI設(shè)計(jì)師,咱們的系統(tǒng)肯定會(huì)更上一層樓。我之前也一直認(rèn)為如此,即我們的設(shè)計(jì)是影響項(xiàng)目體驗(yàn)的重要原因。最近被領(lǐng)導(dǎo)調(diào)動(dòng)去協(xié)助一個(gè)項(xiàng)目,產(chǎn)生了一些不一樣的體會(huì)。

          項(xiàng)目背景,一個(gè)新的產(chǎn)品,小型項(xiàng)目,純開發(fā)人員3-4人,2名熟練開發(fā)人員,1名新手,偶爾會(huì)有協(xié)助人員。沒有技術(shù)經(jīng)理,項(xiàng)目經(jīng)理身負(fù)多個(gè)項(xiàng)目,對(duì)項(xiàng)目進(jìn)度關(guān)心不足,部門經(jīng)理會(huì)協(xié)助進(jìn)行工作和進(jìn)度管理。可以看到管理還是比較混亂。

          由于項(xiàng)目進(jìn)度太慢,領(lǐng)導(dǎo)要求從我這邊調(diào)一個(gè)熟練人員協(xié)助開發(fā)。我也基本了解他們的項(xiàng)目狀況,為了不讓我的人進(jìn)去抓瞎,我就和他一起去了解項(xiàng)目情況。

          項(xiàng)目狀況比較糟糕,介入項(xiàng)目時(shí)已經(jīng)開發(fā)了一段時(shí)間,保留的文檔只有兩份,一副數(shù)據(jù)庫(kù)說明,一份非常粗略的需求說明,而且還與開發(fā)進(jìn)度不同步,就是沒有維護(hù)。

          我了解了一下項(xiàng)目目前的難度,開發(fā)人員和我反映一個(gè)是人員熟練程度的問題,二是需求變更的問題。我整體了解了一下項(xiàng)目目前的需求和設(shè)計(jì),以及進(jìn)度。就挑了一個(gè)模塊詢問他們的變更情況,這個(gè)模塊是一個(gè)關(guān)鍵詞匹配功能。結(jié)果是領(lǐng)導(dǎo)看了他們的頁(yè)面之后,嫌信息量太少,就要求提供一些更細(xì)化的數(shù)據(jù)展示。開發(fā)人員問我有什么意見,我就簡(jiǎn)單講了一下頁(yè)面大概怎么構(gòu)建。其中有一個(gè)點(diǎn),是用于變更數(shù)據(jù)范圍,即查詢的表變更,我一開始覺得使用下拉框就可以,產(chǎn)生了一些意見。有人建議分為不同子模塊,或者tab頁(yè),或者分為多塊并列展示。我想了想,就給他們講了我認(rèn)為幾種方案的優(yōu)點(diǎn)缺點(diǎn)及適用范圍。

           

          1.       多塊并行展示:

          多個(gè)不同范圍的數(shù)據(jù)在同一頁(yè)面中分為不同區(qū)域以相同形式展示。原因是由于多塊數(shù)據(jù)之間有一定的關(guān)聯(lián)因果關(guān)系,或值得對(duì)比。適用范圍:如購(gòu)物網(wǎng)站中的多個(gè)物品比較。

          2.       Tab頁(yè):

          同一個(gè)頁(yè)面的多個(gè)tab頁(yè),表示多個(gè)tab頁(yè)中的數(shù)據(jù)可能在一定的領(lǐng)域概念之下有一定的關(guān)聯(lián),但關(guān)聯(lián)度不強(qiáng)。因?yàn)?/span>tab頁(yè)更重要的是強(qiáng)調(diào)一個(gè)同步工作的狀態(tài),即A tab頁(yè)查看一定信息,會(huì)打開B tab頁(yè)查看其他信息,中途還會(huì)切回A tab頁(yè)。適用范圍:如郵箱中,收件箱和草稿箱。

          3.       下拉框

          下拉框作為查詢條件的一部分,常用于有著常規(guī)或固定的可選擇內(nèi)容中(如性別,月份),更多是以過濾的形態(tài)出現(xiàn),即下拉框更適合針對(duì)某表的某個(gè)字段過濾,如果針對(duì)的是數(shù)據(jù)范圍或是對(duì)用戶需要直觀了解的重要業(yè)務(wù)條件則不太合適。適用范圍:如在考試成績(jī)中使用下拉框過濾“男女”或“及格不及格”。

          4.       單選框

          單選框與下拉框的作用范圍相似,但是不同之處在于將被選項(xiàng)全部展示,目的在于能夠讓用戶清楚的了解當(dāng)前數(shù)據(jù)顯示的實(shí)際范圍或條件,以及備選的其他范圍或條件。更適用于選項(xiàng)與實(shí)際業(yè)務(wù)及當(dāng)前展示數(shù)據(jù)關(guān)系重要,不同選項(xiàng)可能會(huì)引發(fā)用戶的不同行為。適用范圍:如銀行系統(tǒng)顯示了當(dāng)前用戶下綁定多個(gè)帳號(hào)時(shí),使用單選框。

           

          經(jīng)過上述討論,我們仔細(xì)分析了這個(gè)模塊中用戶的實(shí)際需求,以及可能后續(xù)操作,最終選擇的單選框的方案。

          目前還沒有后續(xù),但是我想我們基于用戶真是需求的挖掘和后續(xù)操作的認(rèn)真分析,會(huì)讓我們?cè)谂c領(lǐng)導(dǎo)進(jìn)行需求討論的時(shí)候有更加充分合理的依據(jù)。

          回來之后我又看了看淘寶的搜索頁(yè)面,比如就搜索“鞋子”來講,將品牌這欄設(shè)置為單選和下拉將是完全不同的效果,而確定方案的理由則是對(duì)于用戶的需求和實(shí)際行為的深入研究。這個(gè)應(yīng)該是需求分析和調(diào)研的結(jié)果。將搜索條件以tag的形式標(biāo)注于頁(yè)面上,并且可以直接點(diǎn)擊X按鈕進(jìn)行刪除,我覺得更加可以傾向?yàn)橛脩趔w驗(yàn)。滿足并充分考慮了用戶實(shí)際需求的是好的需求分析,能夠簡(jiǎn)化并引導(dǎo)用戶行為的是好的用戶體驗(yàn)。

          當(dāng)我們面臨的系統(tǒng)感覺非常難用的時(shí)候,往往這時(shí)候并非是用戶體驗(yàn)差,我們應(yīng)該檢討的是我們對(duì)用戶需求有沒有好好挖掘,做出來的是不是用戶想要、用戶能用的系統(tǒng)。

          posted @ 2012-05-22 05:02 一酌散千憂 閱讀(266) | 評(píng)論 (0)編輯 收藏

          Zookeeper的核心概念:

          ZNode

          Znode就是核心結(jié)構(gòu),Zookeeper服務(wù)中是由大量的Znode構(gòu)成。Znode一般是由客戶端建立和修改,作為信息或標(biāo)志的載體,甚至本身就是標(biāo)志。

          Znode可以設(shè)置為持久(PERSISTENT)或臨時(shí)(EPHEMERAL),區(qū)別在于臨時(shí)的節(jié)點(diǎn)若斷開連接后就自動(dòng)刪除。建立節(jié)點(diǎn)時(shí)可選擇是否使用序列號(hào)命名(SEQUENTIAL),若啟用則會(huì)自動(dòng)在節(jié)點(diǎn)名后加入唯一序列編號(hào)。

          Session

          作為客戶端和Zookeeper服務(wù)之間交互的憑證。

          Watch

          當(dāng)客戶端對(duì)節(jié)點(diǎn)信息進(jìn)行查詢操作之后,可以選擇是否設(shè)置一個(gè)Watch。其作用就是當(dāng)本次查詢的數(shù)據(jù)在服務(wù)器端發(fā)生變化之后,會(huì)對(duì)設(shè)置Watch的客戶端發(fā)送通知。一次發(fā)送之后,就將刪除該Watch,以后的變更或不再設(shè)置Watch則不會(huì)通知。

          ACLs

          節(jié)點(diǎn)的權(quán)限限制使用ACL,如增刪改查操作。

          Zookeeper的服務(wù)器安裝:

          1、下載對(duì)應(yīng)版本號(hào)的tar.gz文件

          2、使用 tar xzvf zookeeper-3.4.2.tar.gz -C ./ 解壓

          3、設(shè)置,將conf/zoo.example.cfg復(fù)制到conf/zoo.cfg或者手動(dòng)建立一個(gè)新的。

          4、啟動(dòng)Zookeeper服務(wù):bin/zkServer.sh start

          5、啟動(dòng)客戶端連接:bin/zkCli.sh -server 127.0.0.1:2181(此處在本機(jī),且使用了默認(rèn)端口,且在Java環(huán)境中)

          6、使用命令:ls、get、set等。

          7、關(guān)閉Zookeeper服務(wù):bin/zkServer.sh stop

          Zookeeper代碼編寫:

          代碼編寫部分比較簡(jiǎn)單,因?yàn)楸┞兜慕涌诤苌伲饕獜?fù)雜在于項(xiàng)目如何使用節(jié)點(diǎn)以及節(jié)點(diǎn)信息。

          啟動(dòng)Zookeeper服務(wù)之后,客戶端代碼進(jìn)行節(jié)點(diǎn)的增刪,Watch的設(shè)置,內(nèi)容的改查等。

          此處建議查看官方的《Programming with ZooKeeper - A basic tutorial》部分,當(dāng)中舉了兩個(gè)例子來模擬分布式系統(tǒng)的應(yīng)用。

          代碼基本沒有問題,唯一需要注意的就是:若之間按照原版進(jìn)行調(diào)試時(shí),有可能在調(diào)用

           Stat s = zk.exists(root, false);

          這句代碼時(shí)會(huì)出現(xiàn)一個(gè)異常,當(dāng)中包括“KeeperErrorCode = ConnectionLoss for”。

          這個(gè)問題引起的原因可以看一下代碼

                          System.out.println("Starting ZK:");
                          zk 
          = new ZooKeeper(address, 3000this);
                          mutex 
          = new Integer(-1);
                          System.out.println(
          "Finished starting ZK: " + zk);

          最后一行有打印出Zookeeper目前的信息,若未修改的原代碼,此處的State應(yīng)當(dāng)是CONECTING。連接中的時(shí)候去驗(yàn)證是否存在節(jié)點(diǎn)會(huì)報(bào)錯(cuò)。解決的方法也很簡(jiǎn)單,就是等到Zookeeper客戶端以及完全連接上服務(wù)器,State為CONECTED之后再進(jìn)行其他操作。給出代碼示例:

          // 使用了倒數(shù)計(jì)數(shù),只需要計(jì)數(shù)一次
          private CountDownLatch connectedSignal = new CountDownLatch(1); 
          SyncPrimitive(String address) {
              
          if(zk == null){
                  
          try {
                      System.out.println(
          "Starting ZK:");
                      zk 
          = new ZooKeeper(address, 3000this);
                      mutex 
          = new Integer(-1);
                      connectedSignal.await(); 
          // 等待連接完成
                      System.out.println("Finished starting ZK: " + zk);
                  } 
          catch (IOException e) {
                      System.out.println(e.toString());
                      zk 
          = null;
                  } 
          catch (InterruptedException e) {
                      
          // TODO Auto-generated catch block
                      e.printStackTrace();
                  }
              }
              
          //else mutex = new Integer(-1);
          }
          synchronized public void process(WatchedEvent event) {
              
          // 此處設(shè)立在Watch中會(huì)在狀態(tài)變化后觸發(fā)事件
              if (event.getState() == KeeperState.SyncConnected) {
                  connectedSignal.countDown();
          // 倒數(shù)-1
              }
              
                  
          synchronized (mutex) {
                      
          //System.out.println("Process: " + event.getType());
                      mutex.notify();
                  }
          }

          這樣就可以正確運(yùn)行代碼了。

          Zookeeper的應(yīng)用場(chǎng)景及方式:

          此處是為引用,原地址為(http://rdc.taobao.com/team/jm/archives/1232 

          ZooKeeper是一個(gè)高可用的分布式數(shù)據(jù)管理與系統(tǒng)協(xié)調(diào)框架?;趯?duì)Paxos算法的實(shí)現(xiàn),使該框架保證了分布式環(huán)境中數(shù)據(jù)的強(qiáng)一致性,也正是基于這樣的特性,使得zookeeper能夠應(yīng)用于很多場(chǎng)景。網(wǎng)上對(duì)zk的使用場(chǎng)景也有不少介紹,本文將結(jié)合作者身邊的項(xiàng)目例子,系統(tǒng)的對(duì)zk的使用場(chǎng)景進(jìn)行歸類介紹。 值得注意的是,zk并不是生來就為這些場(chǎng)景設(shè)計(jì),都是后來眾多開發(fā)者根據(jù)框架的特性,摸索出來的典型使用方法。因此,也非常歡迎你分享你在ZK使用上的奇技淫巧。

          場(chǎng)景類別

          典型場(chǎng)景描述(ZK特性,使用方法)

          應(yīng)用中的具體使用

          數(shù)據(jù)發(fā)布與訂閱

          發(fā)布與訂閱即所謂的配置管理,顧名思義就是將數(shù)據(jù)發(fā)布到zk節(jié)點(diǎn)上,供訂閱者動(dòng)態(tài)獲取數(shù)據(jù),實(shí)現(xiàn)配置信息的集中式管理和動(dòng)態(tài)更新。例如全局的配置信息,地址列表等就非常適合使用。

          1. 索引信息和集群中機(jī)器節(jié)點(diǎn)狀態(tài)存放在zk的一些指定節(jié)點(diǎn),供各個(gè)客戶端訂閱使用。2. 系統(tǒng)日志(經(jīng)過處理后的)存儲(chǔ),這些日志通常2-3天后被清除。 

          3. 應(yīng)用中用到的一些配置信息集中管理,在應(yīng)用啟動(dòng)的時(shí)候主動(dòng)來獲取一次,并且在節(jié)點(diǎn)上注冊(cè)一個(gè)Watcher,以后每次配置有更新,實(shí)時(shí)通知到應(yīng)用,獲取最新配置信息。

          4. 業(yè)務(wù)邏輯中需要用到的一些全局變量,比如一些消息中間件的消息隊(duì)列通常有個(gè)offset,這個(gè)offset存放在zk上,這樣集群中每個(gè)發(fā)送者都能知道當(dāng)前的發(fā)送進(jìn)度。

          5. 系統(tǒng)中有些信息需要?jiǎng)討B(tài)獲取,并且還會(huì)存在人工手動(dòng)去修改這個(gè)信息。以前通常是暴露出接口,例如JMX接口,有了zk后,只要將這些信息存放到zk節(jié)點(diǎn)上即可。

          Name Service

          這個(gè)主要是作為分布式命名服務(wù),通過調(diào)用zk的create node api,能夠很容易創(chuàng)建一個(gè)全局唯一的path,這個(gè)path就可以作為一個(gè)名稱。

           

          分布通知/協(xié)調(diào)

          ZooKeeper中特有watcher注冊(cè)與異步通知機(jī)制,能夠很好的實(shí)現(xiàn)分布式環(huán)境下不同系統(tǒng)之間的通知與協(xié)調(diào),實(shí)現(xiàn)對(duì)數(shù)據(jù)變更的實(shí)時(shí)處理。使用方法通常是不同系統(tǒng)都對(duì)ZK上同一個(gè)znode進(jìn)行注冊(cè),監(jiān)聽znode的變化(包括znode本身內(nèi)容及子節(jié)點(diǎn)的),其中一個(gè)系統(tǒng)update了znode,那么另一個(gè)系統(tǒng)能夠收到通知,并作出相應(yīng)處理。

          1. 另一種心跳檢測(cè)機(jī)制:檢測(cè)系統(tǒng)和被檢測(cè)系統(tǒng)之間并不直接關(guān)聯(lián)起來,而是通過zk上某個(gè)節(jié)點(diǎn)關(guān)聯(lián),大大減少系統(tǒng)耦合。2. 另一種系統(tǒng)調(diào)度模式:某系統(tǒng)有控制臺(tái)和推送系統(tǒng)兩部分組成,控制臺(tái)的職責(zé)是控制推送系統(tǒng)進(jìn)行相應(yīng)的推送工作。管理人員在控制臺(tái)作的一些操作,實(shí)際上是修改了ZK上某些節(jié)點(diǎn)的狀態(tài),而zk就把這些變化通知給他們注冊(cè)Watcher的客戶端,即推送系統(tǒng),于是,作出相應(yīng)的推送任務(wù)。 

          3. 另一種工作匯報(bào)模式:一些類似于任務(wù)分發(fā)系統(tǒng),子任務(wù)啟動(dòng)后,到zk來注冊(cè)一個(gè)臨時(shí)節(jié)點(diǎn),并且定時(shí)將自己的進(jìn)度進(jìn)行匯報(bào)(將進(jìn)度寫回這個(gè)臨時(shí)節(jié)點(diǎn)),這樣任務(wù)管理者就能夠?qū)崟r(shí)知道任務(wù)進(jìn)度。

          總之,使用zookeeper來進(jìn)行分布式通知和協(xié)調(diào)能夠大大降低系統(tǒng)之間的耦合。

          分布式鎖

          分布式鎖,這個(gè)主要得益于ZooKeeper為我們保證了數(shù)據(jù)的強(qiáng)一致性,即用戶只要完全相信每時(shí)每刻,zk集群中任意節(jié)點(diǎn)(一個(gè)zk server)上的相同znode的數(shù)據(jù)是一定是相同的。鎖服務(wù)可以分為兩類,一個(gè)是保持獨(dú)占,另一個(gè)是控制時(shí)序。 

          所謂保持獨(dú)占,就是所有試圖來獲取這個(gè)鎖的客戶端,最終只有一個(gè)可以成功獲得這把鎖。通常的做法是把zk上的一個(gè)znode看作是一把鎖,通過create znode的方式來實(shí)現(xiàn)。所有客戶端都去創(chuàng)建 /distribute_lock 節(jié)點(diǎn),最終成功創(chuàng)建的那個(gè)客戶端也即擁有了這把鎖。

          控制時(shí)序,就是所有視圖來獲取這個(gè)鎖的客戶端,最終都是會(huì)被安排執(zhí)行,只是有個(gè)全局時(shí)序了。做法和上面基本類似,只是這里 /distribute_lock 已經(jīng)預(yù)先存在,客戶端在它下面創(chuàng)建臨時(shí)有序節(jié)點(diǎn)(這個(gè)可以通過節(jié)點(diǎn)的屬性控制:CreateMode.EPHEMERAL_SEQUENTIAL來指定)。Zk的父節(jié)點(diǎn)(/distribute_lock)維持一份sequence,保證子節(jié)點(diǎn)創(chuàng)建的時(shí)序性,從而也形成了每個(gè)客戶端的全局時(shí)序。

           

          集群管理

          1. 集群機(jī)器監(jiān)控:這通常用于那種對(duì)集群中機(jī)器狀態(tài),機(jī)器在線率有較高要求的場(chǎng)景,能夠快速對(duì)集群中機(jī)器變化作出響應(yīng)。這樣的場(chǎng)景中,往往有一個(gè)監(jiān)控系統(tǒng),實(shí)時(shí)檢測(cè)集群機(jī)器是否存活。過去的做法通常是:監(jiān)控系統(tǒng)通過某種手段(比如ping)定時(shí)檢測(cè)每個(gè)機(jī)器,或者每個(gè)機(jī)器自己定時(shí)向監(jiān)控系統(tǒng)匯報(bào)“我還活著”。 這種做法可行,但是存在兩個(gè)比較明顯的問題:1. 集群中機(jī)器有變動(dòng)的時(shí)候,牽連修改的東西比較多。2. 有一定的延時(shí)。 

          利用ZooKeeper有兩個(gè)特性,就可以實(shí)時(shí)另一種集群機(jī)器存活性監(jiān)控系統(tǒng):a. 客戶端在節(jié)點(diǎn) x 上注冊(cè)一個(gè)Watcher,那么如果 x 的子節(jié)點(diǎn)變化了,會(huì)通知該客戶端。b. 創(chuàng)建EPHEMERAL類型的節(jié)點(diǎn),一旦客戶端和服務(wù)器的會(huì)話結(jié)束或過期,那么該節(jié)點(diǎn)就會(huì)消失。

          例如,監(jiān)控系統(tǒng)在 /clusterServers 節(jié)點(diǎn)上注冊(cè)一個(gè)Watcher,以后每動(dòng)態(tài)加機(jī)器,那么就往 /clusterServers 下創(chuàng)建一個(gè) EPHEMERAL類型的節(jié)點(diǎn):/clusterServers/{hostname}. 這樣,監(jiān)控系統(tǒng)就能夠?qū)崟r(shí)知道機(jī)器的增減情況,至于后續(xù)處理就是監(jiān)控系統(tǒng)的業(yè)務(wù)了。
          2. Master選舉則是zookeeper中最為經(jīng)典的使用場(chǎng)景了。

          在分布式環(huán)境中,相同的業(yè)務(wù)應(yīng)用分布在不同的機(jī)器上,有些業(yè)務(wù)邏輯(例如一些耗時(shí)的計(jì)算,網(wǎng)絡(luò)I/O處理),往往只需要讓整個(gè)集群中的某一臺(tái)機(jī)器進(jìn)行執(zhí)行,其余機(jī)器可以共享這個(gè)結(jié)果,這樣可以大大減少重復(fù)勞動(dòng),提高性能,于是這個(gè)master選舉便是這種場(chǎng)景下的碰到的主要問題。

          利用ZooKeeper的強(qiáng)一致性,能夠保證在分布式高并發(fā)情況下節(jié)點(diǎn)創(chuàng)建的全局唯一性,即:同時(shí)有多個(gè)客戶端請(qǐng)求創(chuàng)建 /currentMaster 節(jié)點(diǎn),最終一定只有一個(gè)客戶端請(qǐng)求能夠創(chuàng)建成功。

          利用這個(gè)特性,就能很輕易的在分布式環(huán)境中進(jìn)行集群選取了。

          另外,這種場(chǎng)景演化一下,就是動(dòng)態(tài)Master選舉。這就要用到 EPHEMERAL_SEQUENTIAL類型節(jié)點(diǎn)的特性了。

          上文中提到,所有客戶端創(chuàng)建請(qǐng)求,最終只有一個(gè)能夠創(chuàng)建成功。在這里稍微變化下,就是允許所有請(qǐng)求都能夠創(chuàng)建成功,但是得有個(gè)創(chuàng)建順序,于是所有的請(qǐng)求最終在ZK上創(chuàng)建結(jié)果的一種可能情況是這樣: /currentMaster/{sessionId}-1 , /currentMaster/{sessionId}-2 , /currentMaster/{sessionId}-3 ….. 每次選取序列號(hào)最小的那個(gè)機(jī)器作為Master,如果這個(gè)機(jī)器掛了,由于他創(chuàng)建的節(jié)點(diǎn)會(huì)馬上小時(shí),那么之后最小的那個(gè)機(jī)器就是Master了。

          1. 在搜索系統(tǒng)中,如果集群中每個(gè)機(jī)器都生成一份全量索引,不僅耗時(shí),而且不能保證彼此之間索引數(shù)據(jù)一致。因此讓集群中的Master來進(jìn)行全量索引的生成,然后同步到集群中其它機(jī)器。2. 另外,Master選舉的容災(zāi)措施是,可以隨時(shí)進(jìn)行手動(dòng)指定master,就是說應(yīng)用在zk在無法獲取master信息時(shí),可以通過比如http方式,向一個(gè)地方獲取master。

          分布式隊(duì)列

          隊(duì)列方面,我目前感覺有兩種,一種是常規(guī)的先進(jìn)先出隊(duì)列,另一種是要等到隊(duì)列成員聚齊之后的才統(tǒng)一按序執(zhí)行。對(duì)于第二種先進(jìn)先出隊(duì)列,和分布式鎖服務(wù)中的控制時(shí)序場(chǎng)景基本原理一致,這里不再贅述。 

          第二種隊(duì)列其實(shí)是在FIFO隊(duì)列的基礎(chǔ)上作了一個(gè)增強(qiáng)。通??梢栽?nbsp;/queue 這個(gè)znode下預(yù)先建立一個(gè)/queue/num 節(jié)點(diǎn),并且賦值為n(或者直接給/queue賦值n),表示隊(duì)列大小,之后每次有隊(duì)列成員加入后,就判斷下是否已經(jīng)到達(dá)隊(duì)列大小,決定是否可以開始執(zhí)行了。這種用法的典型場(chǎng)景是,分布式環(huán)境中,一個(gè)大任務(wù)Task A,需要在很多子任務(wù)完成(或條件就緒)情況下才能進(jìn)行。這個(gè)時(shí)候,凡是其中一個(gè)子任務(wù)完成(就緒),那么就去 /taskList 下建立自己的臨時(shí)時(shí)序節(jié)點(diǎn)(CreateMode.EPHEMERAL_SEQUENTIAL),當(dāng) /taskList 發(fā)現(xiàn)自己下面的子節(jié)點(diǎn)滿足指定個(gè)數(shù),就可以進(jìn)行下一步按序進(jìn)行處理了。

           

          posted @ 2012-05-15 11:02 一酌散千憂 閱讀(4843) | 評(píng)論 (0)編輯 收藏

          主站蜘蛛池模板: 丰原市| 岢岚县| 濮阳市| 安福县| 乃东县| 海林市| 迭部县| 安阳市| 开远市| 静乐县| 弋阳县| 璧山县| 峨山| 龙海市| 澳门| 眉山市| 江西省| 临澧县| 库车县| 仁布县| 台南县| 西林县| 佛冈县| 监利县| 永川市| 鹤峰县| 土默特左旗| 临汾市| 施甸县| 景德镇市| 会宁县| 承德市| 富平县| 上犹县| 唐海县| 行唐县| 沾化县| 都江堰市| 香河县| 福鼎市| 保康县|