• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            posts - 200, comments - 8, trackbacks - 0, articles - 0

                 摘要: 1.malloc怎么分配空間    malloc與new的關系    看完下面的2再回答這個問題。2. linux對內存的結構描述    a)         /proc/${pid}/         存放進程運行時候所有的信息。程序一結...  閱讀全文

            posted @ 2012-12-26 19:55 鑫龍 閱讀(600) | 評論 (0)編輯 收藏

            倒騰了一天,終于在CentOS上裝上了hadoop-0.21.0,特此記錄,以備后用。

            操作系統:CentOS 5.5

            Hadoop:hadoop-0.21.0
            JDK:1.6.0_17
            namenode主機名:master,namenode的IP:192.168.90.91
            datanode主機名:slave,datanode的IP:192.168.90.94

            第一步:安裝并啟動ssh服務

            CentOS 5.5安裝完畢之后以及默認啟動了sshd服務,可以在“系統”->“管理”->“服務”中查看sshd服務是否啟動。當然了,如果機器上沒有安裝ssh服務,則執行命令sudo yum install ssh來安裝。安裝rsync,它是一個遠程數據同步工具,可通過 LAN/WAN 快速同步多臺主機間的文件,執行命令sudo yum install rsync。修改每個節點的/etc/hosts文件,將 namenode和datanode的IP信息加入到該文件的尾部:

            192.168.90.91 master
            192.168.90.94 slave

            第二步,配置SSH服務

            (1),(2)是針對每一臺機器

            (1)創建hadoop用戶名與用戶組

                 運行命令su - root,注意,不是命令su root,后者不能攜帶root用戶的參數信息,是不能執行創建用戶組和用戶命令的。執行命令:groupadd hadoop和命令useradd -g hadoop hadoop。注意不能在/home目錄下創建hadoop目錄,否則創建hadoop用戶會失敗。創建好用戶以后最好是重新啟動計算機,以hadoop用戶登錄系統。這樣在之后的操作中就不需要su到hadoop用戶下,而且也不會糾纏于文件的owner問題。

            (2)生成ssh密鑰

                 如果是其他用戶登錄的則切換到hadoop用戶下,執行命令su - hadoop,在/home/hadoop目錄下執行命令:ssh-keygen -t rsa(一路回車,選擇默認的保存路徑),密鑰生成成功之后,進入.ssh目錄,執行cd .ssh,執行命令:cp id_rsa.pub authorized_keys。這個時候運行ssh localhost,讓系統記住用戶,之后ssh localhost就不需要再輸入密碼了。

            (3)交換公鑰

                 將namenode上的公鑰拷貝到datanode,在hadoop用戶的用戶目錄下(/home/hadoop)下執行命令ssh-copy-id -i $HOME/.ssh/id_rsa.pub hadoop@slave。同理,也可以將datanode上的公鑰拷貝到namenode,但這不是必須的。這樣兩臺機器在hadoop用戶下互相ssh就不需要密碼了。

             

            第三步,安裝JDK1.6或以上(每臺機器)

            (1)執行命令yum install jdk

            (2)如果第一步沒有找到源碼包,那么就需要到官網上下載了,https://cds.sun.com/is-bin/INTERSHOP.enfinity/WFS/CDS-CDS_Developer-Site/en_US/-/USD/ViewProductDetail-Start?ProductRef=jdk-6u22-oth-JPR@CDS-CDS_Developer。

            (3)新建目錄/usr/java,將源碼包jdk-6u22-linux-i586.bin復制到該目錄下,執行命令chmod a+x jdk-6u22-linux-i586.bin
                  使當前用戶擁有對jdk-6u22-linux-i586.bin的執行權限。執行命令sudo ./jdk-6u22-linux-i586.bin進行安裝

            (4)修改/etc/profile來添加環境變量,/etc/profile中設置的環境變量就像Windows下環境變量中的系統變量一樣,所有用戶都可以使用。
                  用文本編輯器打開/etc/profile
                  # vi /etc/profile
                  在最后加入以下幾行:
                  export JAVA_HOME=/usr/java/jdk1.6.0_22
                  export CLASSPATH=.:$JAVA_HOME/jre/lib/rt.jar:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
                  export PATH=$PATH:$JAVA_HOME/bin
                  這樣我們就設置好了JDK,在centos下 source /etc/profile 就可以生效了.

            運行命令java -version可以判斷是否安裝成功

             

            第四步,安裝hadoop

            原來現在才開始安裝hadoop,準備工作也作得太多了,廢話少說。

            (1)新建目錄/usr/local/hadoop,將hadoop-0.21.0.tar.gz解壓縮到該目錄下,執行命令sudo tar -xvzf hadoop-0.21.0.tar.gz,修改/etc/profile文件,將hadoop的安裝目錄append到文件最后:

            export HADOOP_HOME=/usr/local/hadoop/hadoop-0.21.0
            export PATH=$HADOOP_HOME/bin:$PATH
            (2)配置/conf/hadoop-env.sh文件,修改java_home環境變量
            export JAVA_HOME=/usr/java/jdk1.6.0_22/
            export HADOOP_CLASSPATH=.
            (3)配置 core-site.xml 文件
            <configuration>
                  <property>
                        <name>hadoop.tmp.dir</name>
                        <value>/usr/local/hadoop/hadoop-0.21.0/tmp</value>
                       (注意,請先在 hadoopinstall 目錄下建立 tmp 文件夾)
                        <description>A base for other temporary directories.</description>
                  </property>
            <!-- file system properties -->
                  <property>
                        <name>fs.default.name</name>
                  <value>hdfs://master:54310</value>
                  </property>
            </configuration>
            (4)配置 hdfs-site.xml 文件
            <configuration>
                  <property>
                        <name>dfs.replication</name>
                        <value>1</value>(這里共兩臺機器,如果將主節點也配置為datanode,則這里可以寫2)
                  </property>
            <configuration>
            (5)配置 mapred-site.xml 文件
            <configuration>
                  <property>
                        <name>mapred.job.tracker</name>
                        <value>master:54311</value>
                  </property>
            </configuration>
            (6)配置 conf/masters 文件,加入 namenode 的 ip 地址
            master
            (7)配置 slaves 文件, 加入所有 datanode 的 ip 地址

            slave

             

            (如果之前的hdfs-site.xml文件中的拷貝數設置為2,則需要將master也加入到slaves文件中)

            (8)將 namenode 上 配 置 好 的 hadoop 所 在 文 件 夾 hadoop-0.21.0 復 制 到
            datanode 的/usr/lcoal/hadoop/目錄下(實際上 masters,slavers 文件時不必要的, 復制了也
            沒問題)。
            (9)配置datanode的/etc/profile 文件,在文件尾append下列內容:
            export HADOOP_HOME=/usr/local/hadoop/hadoop-0.21.0
            export PATH=$HADOOP_HOME/bin:$PATH

            第五步,啟動hadoop
            首先記得關閉系統的防火墻,root用戶下執行命令/etc/init.d/iptables stop,運行命令/etc/init.d/iptables status檢查防火墻狀態。hadoop用戶下,在namenode的/usr/local/hadoop/hadoop-0.21.0/bin目錄下打開終端,執行命令hadoop namenode -format,格式化目錄節點。注意,/usr/local/hadoop/hadoop-0.21.0/tmp目錄是可以寫的,否則在格式化時會出現異常。執行命令start-all.sh啟動hadoop集群,執行命令jps查看進程,執行命令hadoop dfsadmin -report查看狀態。在瀏覽器中輸入http://master:50070以web方式查看集群狀態。查看jobtraker的運行狀態:http://www.ibm.com/developerworks/cn/linux/l-hadoop-2/index.html
            PS:格式化namenode的時候最好將節點的tmp目錄清空、刪除logs目錄中的文件。

            到這里,基于CentOS5.5的hadoop集群搭建完畢!

             

            參考資料:http://www.ibm.com/developerworks/cn/linux/l-hadoop-2/index.html

            posted @ 2012-12-25 20:54 鑫龍 閱讀(300) | 評論 (0)編輯 收藏

            第一步:查看Linux自帶的JDK是否已安裝 (卸載centOS已安裝的1.4)

            安裝好的CentOS會自帶OpenJdk,用命令 java -version ,會有下面的信息:

            java version "1.6.0"
            OpenJDK Runtime Environment (build 1.6.0-b09)
            OpenJDK 64-Bit Server VM (build 1.6.0-b09, mixed mode)

            最好還是先卸載掉openjdk,在安裝sun公司的jdk.

            先查看 rpm -qa | grep java

            顯示如下信息:

            java-1.4.2-gcj-compat-1.4.2.0-40jpp.115
            java-1.6.0-openjdk-1.6.0.0-1.7.b09.el5

            卸載:

            rpm -e --nodeps java-1.4.2-gcj-compat-1.4.2.0-40jpp.115
            rpm -e --nodeps java-1.6.0-openjdk-1.6.0.0-1.7.b09.el5

            還有一些其他的命令

            rpm -qa | grep gcj

            rpm -qa | grep jdk

            如果出現找不到openjdk source的話,那么還可以這樣卸載

            yum -y remove java java-1.4.2-gcj-compat-1.4.2.0-40jpp.115
            yum -y remove java java-1.6.0-openjdk-1.6.0.0-1.7.b09.el5

             

             

            <1># rpm -qa|grep jdk ← 查看jdk的信息或直接執行 
            或 
            # rpm -q jdk 
            或 
            # java -version 
            <2># rpm -qa | grep gcj ← 確認gcj的版本號 
            <3># yum -y remove java-1.4.2-gcj-compat ← 卸載gcj 

            第二步:安裝JDK 
            <1>從SUN下載jdk-1_5_0_14-linux-i586-rpm.bin或jdk-1_5_0_14-linux-i586.bin 
            在/usr下新建java文件夾,將安裝包放在/usr/java目錄下 
            # mkdir /usr/java 
            <2>安裝JDK 
            # cd /usr/java 
            ①jdk-1_5_0_14-linux-i586-rpm.bin文件安裝 
            # chmod 777 jdk-1_5_0_14-linux-i586-rpm.bin ← 修改為可執行 
            # ./jdk-1_5_0_14-linux-i586-rpm.bin ← 選擇yes同意上面的協議 
            # rpm -ivh jdk-1_5_0_14-linux-i586.rpm ← 選擇yes直到安裝完畢 
            ②jdk-1_5_0_14-linux-i586.bin文件安裝 
            # chmod a+x jdk-1_5_0_14-linux-i586.bin ← 使當前用戶擁有執行權限 
            # ./jdk-1_5_0_14-linux-i586.bin ← 選擇yes直到安裝完畢 

            第三步:配置環境變量 
            <1># vi /etc/profile 
            <2>在最后加入以下幾行: 
            export JAVA_HOME=/usr/java/jdk1.6.0_10 
            export CLASSPATH=.:$JAVA_HOME/jre/lib/rt.jar:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar 
            export PATH=$PATH:$JAVA_HOME/bin 
            <3># reboot ← 重啟機器配置生效

            posted @ 2012-12-25 19:17 鑫龍 閱讀(336) | 評論 (0)編輯 收藏

            引子:

            怎么對容器中的所有對象都進行同一個操作?我們可能首先想到的是用循環來實現。
            比如有如下的一個類:

            class ClxECS{
            public:
                int DoSomething() { 
                cout << "Output from method DoSomething!" << endl; // 這里以輸出一句話來代替具體的操作
                return 0;
                };
            };


            現在定義如下一個vector:

            vector<ClxECS*> vECS;

            for(int i = 0; i < 13; i++){
                ClxECS *pECS = new ClxECS;
                vECS.push_back(pECS);
            }


             如果要對容器vECS中的所有對象都進行DoSomething()的操作,那么下面的循環可能是首先想到的方案:

            for(int i = 0; i < vECS.size(); i++)
                vECS.at(i)->DoSomething();
               

             當然,我們也可以用iterator:

            for(vector<ClxECS*>::iterator it = vECS.begin(); it != vECS.end(); ++it)
                (*it)->DoSomething();


             但是,有很多C++的高手和牛人們都會給我們一個忠告,那就是:在處理STL里面的容器的時候,盡量不要自己寫循環。
            那么,我們就只好用STL算法里面的for_each了。
            首先,添加如下一個函數:

            int DoSomething(ClxECS *pECS)
            {
                return pECS->DoSomething();
            }
            然后就可以用for_each來實現我們想要的功能:

            for_each(vECS.begin(), vECS.end(), &DoSomething);
            說了半天,似乎跟mem_fun和mem_fun_ref沒有什么關系。其實,說那么多都是為了引出mem_fun和mem_fun_ref。在用for_each的時候,如果我們不添加上面的那個函數,該怎么辦呢?


            這個時候就該mem_fun和mem_fun_ref隆重登場了。用如下這一行代碼就行了:

            for_each(vECS.begin(), vECS.end(), mem_fun(&ClxECS::DoSomething));
            實際上就是由迭代器去調用成員函數.

             

            例子:

            list<Widget *> lpw;
            for_each(lpw.begin(), lpw.end(),mem_fun(&Widget::test)); // pw->test();

            vector<Widget> vw;
            for_each(vw.begin(), vw.end(),mem_fun_ref(&Widget::test)); // w.test();

            成員函數有參數的情況:將值傳入,再bind1st為this

            std::for_each(m_erased.begin(), m_erased.end(),std::bind1st(std::mem_fun(&SocketSet::_replace_with_last), this));
            //相當于this->_replace_with_last(iter)  //iter

            兩者區別:
            mem_fun_ref的作用和用法跟mem_fun一樣,唯一的不同就是:

            當容器中存放的是對象實體的時候用mem_fun_ref,

            當容器中存放的是對象的指針的時候用mem_fun。

            posted @ 2012-12-25 17:06 鑫龍 閱讀(2662) | 評論 (0)編輯 收藏

                 摘要:        本文的技術可以參考本博客:  Traits 技術 --- 模板元編程 (轉)          迭代器可以區分為不同的類型,每個類型都有特定的迭代器功能。        根據迭代器類型,將算法根據類型的不同實現出更加有效率的版本,將會很...  閱讀全文

            posted @ 2012-12-24 21:38 鑫龍 閱讀(532) | 評論 (0)編輯 收藏

                 問題的由來:
            vector<int> coll;
            .....
            sort(++coll.begin(),coll.end());
                對于sort那句,如果vecotor的底層是用指針實現(通常就是用指針實現),那么編譯無法通過。
               
                其實此次問題該系列上一次文章類似<<c++標準程序庫----p55----為什么需要auto_ptr_ref? (轉)>>,都是臨時對象惹的禍。
               c++不允許任何修改基本類型(包括指針)臨時值的行為,但對于類類型則允許。怎么理解呢?舉個例子:
            #include <iostream>
            using namespace std;
             
             
            class node
            {
             
            public:
                node(int j = 0):i(j){}
                int i;
                void operator++()//這里重定義一個賦值操作符=,為下面的賦值做準備。
                {
                    i++;
                }
            };
             
            node fun()                          
            {
                node temp(1);
                return temp;//這里返回一個類的臨時變量
            }
             
            int* fun2()
            {
                int a =1;
                int* b = &a;  //這里返回存在棧中局部變量的地址是不對的,但只是做實驗! 
                return b;//這里返回一個普通int臨時變量
             
            }
            int main()
            {
                ++fun();   // ok!
                ++fun2(); //這句無法通過編譯 
                system("pause");
             
            }
                上面的例子fun()返回類類型的臨時變量可以被修改,但fun2()返回的指針的臨時變量不能被修改。
                回到開始的例子,因為vector的迭代器底層是用指針實現,所以begin()函數返回的是一個指針類型的臨時變量,如果用++操作去修改,那就違反了c++的設計原則,所以無法編譯通過。做到底還是左值不能被修改!!!

            posted @ 2012-12-23 22:18 鑫龍 閱讀(652) | 評論 (0)編輯 收藏

                        從hadoop框架與MapReduce模式中談海量數據處理

            前言

                幾周前,當我最初聽到,以致后來初次接觸Hadoop與MapReduce這兩個東西,我便稍顯興奮,覺得它們很是神秘,而神秘的東西常能勾起我的興趣,在看過介紹它們的文章或論文之后,覺得Hadoop是一項富有趣味和挑戰性的技術,且它還牽扯到了一個我更加感興趣的話題:海量數據處理。

                由此,最近凡是空閑時,便在看“Hadoop”,“MapReduce”“海量數據處理”這方面的論文。但在看論文的過程中,總覺得那些論文都是淺嘗輒止,常常看的很不過癮,總是一個東西剛要講到緊要處,它便結束了,讓我好生“憤懣”。

                盡管我對這個Hadoop與MapReduce知之甚淺,但我還是想記錄自己的學習過程,說不定,關于這個東西的學習能督促我最終寫成和“經典算法研究系列”一般的一系列文章。

                Ok,閑話少說。本文從最基本的mapreduce模式,Hadoop框架開始談起,然后由各自的架構引申開來,談到海量數據處理,最后談談淘寶的海量數據產品技術架構,以為了兼備淺出與深入之效,最終,希望得到讀者的喜歡與支持。謝謝。

                由于本人是初次接觸這兩項技術,文章有任何問題,歡迎不吝指正。再謝一次。Ok,咱們開始吧。

            第一部分、mapreduce模式與hadoop框架深入淺出

            架構扼要

                     想讀懂此文,讀者必須先要明確以下幾點,以作為閱讀后續內容的基礎知識儲備:

            1. Mapreduce是一種模式。
            2. Hadoop是一種框架。
            3. Hadoop是一個實現了mapreduce模式的開源的分布式并行編程框架。

                所以,你現在,知道了什么是mapreduce,什么是hadoop,以及這兩者之間最簡單的聯系,而本文的主旨即是,一句話概括:在hadoop的框架上采取mapreduce的模式處理海量數據。下面,咱們可以依次深入學習和了解mapreduce和hadoop這兩個東西了。

            Mapreduce模式

                前面說了,mapreduce是一種模式,一種什么模式呢?一種云計算的核心計算模式,一種分布式運算技術,也是簡化的分布式編程模式,它主要用于解決問題的程序開發模型,也是開發人員拆解問題的方法。

                Ok,光說不上圖,沒用。如下圖所示,mapreduce模式的主要思想是將自動分割要執行的問題(例如程序)拆解成map(映射)和reduce(化簡)的方式,流程圖如下圖1所示:

                在數據被分割后通過Map 函數的程序將數據映射成不同的區塊,分配給計算機機群處理達到分布式運算的效果,在通過Reduce 函數的程序將結果匯整,從而輸出開發者需要的結果。

                MapReduce 借鑒了函數式程序設計語言的設計思想,其軟件實現是指定一個Map 函數,把鍵值對(key/value)映射成新的鍵值對(key/value),形成一系列中間結果形式的key/value 對,然后把它們傳給Reduce(規約)函數,把具有相同中間形式key 的value 合并在一起。Map 和Reduce 函數具有一定的關聯性。函數描述如表1 所示:

                MapReduce致力于解決大規模數據處理的問題,因此在設計之初就考慮了數據的局部性原理,利用局部性原理將整個問題分而治之。MapReduce集群由普通PC機構成,為無共享式架構。在處理之前,將數據集分布至各個節點。處理時,每個節點就近讀取本地存儲的數據處理(map),將處理后的數據進行合并(combine)、排序(shuffle and sort)后再分發(至reduce節點),避免了大量數據的傳輸,提高了處理效率。無共享式架構的另一個好處是配合復制(replication)策略,集群可以具有良好的容錯性,一部分節點的down機對集群的正常工作不會造成影響。

                ok,你可以再簡單看看下副圖,整幅圖是有關hadoop的作業調優參數及原理,圖的左邊是MapTask運行示意圖,右邊是ReduceTask運行示意圖:

                如上圖所示,其中map階段,當map task開始運算,并產生中間數據后并非直接而簡單的寫入磁盤,它首先利用內存buffer來對已經產生的buffer進行緩存,并在內存buffer中進行一些預排序來優化整個map的性能。而上圖右邊的reduce階段則經歷了三個階段,分別Copy->Sort->reduce。我們能明顯的看出,其中的Sort是采用的歸并排序,即merge sort。

                了解了什么是mapreduce,接下來,咱們可以來了解實現了mapreduce模式的開源框架—hadoop。

            Hadoop框架

                前面說了,hadoop是一個框架,一個什么樣的框架呢?Hadoop 是一個實現了MapReduce 計算模型的開源分布式并行編程框架,程序員可以借助Hadoop 編寫程序,將所編寫的程序運行于計算機機群上,從而實現對海量數據的處理。

                此外,Hadoop 還提供一個分布式文件系統(HDFS)及分布式數據庫(HBase)用來將數據存儲或部署到各個計算節點上。所以,你可以大致認為:Hadoop=HDFS(文件系統,數據存儲技術相關)+HBase(數據庫)+MapReduce(數據處理)。Hadoop 框架如圖2 所示:

                借助Hadoop 框架及云計算核心技術MapReduce 來實現數據的計算和存儲,并且將HDFS 分布式文件系統和HBase 分布式數據庫很好的融入到云計算框架中,從而實現云計算的分布式、并行計算和存儲,并且得以實現很好的處理大規模數據的能力。

            Hadoop的組成部分

                我們已經知道,Hadoop是Google的MapReduce一個Java實現。MapReduce是一種簡化的分布式編程模式,讓程序自動分布到一個由普通機器組成的超大集群上并發執行。Hadoop主要由HDFS、MapReduce和HBase等組成。具體的hadoop的組成如下圖:

                由上圖,我們可以看到:

                1、             Hadoop HDFS是Google GFS存儲系統的開源實現,主要應用場景是作為并行計算環境(MapReduce)的基礎組件,同時也是BigTable(如HBase、HyperTable)的底層分布式文件系統。HDFS采用master/slave架構。一個HDFS集群是有由一個Namenode和一定數目的Datanode組成。Namenode是一個中心服務器,負責管理文件系統的namespace和客戶端對文件的訪問。Datanode在集群中一般是一個節點一個,負責管理節點上它們附帶的存儲。在內部,一個文件其實分成一個或多個block,這些block存儲在Datanode集合里。如下圖所示(HDFS體系結構圖):

                2、             Hadoop MapReduce是一個使用簡易的軟件框架,基于它寫出來的應用程序能夠運行在由上千個商用機器組成的大型集群上,并以一種可靠容錯的方式并行處理上TB級別的數據集。

                一個MapReduce作業(job)通常會把輸入的數據集切分為若干獨立的數據塊,由 Map任務(task)以完全并行的方式處理它們。框架會對Map的輸出先進行排序,然后把結果輸入給Reduce任務。通常作業的輸入和輸出都會被存儲在文件系統中。整個框架負責任務的調度和監控,以及重新執行已經失敗的任務。如下圖所示(Hadoop MapReduce處理流程圖):

                3、             Hive是基于Hadoop的一個數據倉庫工具,處理能力強而且成本低廉。

            主要特點

            存儲方式是將結構化的數據文件映射為一張數據庫表。提供類SQL語言,實現完整的SQL查詢功能。可以將SQL語句轉換為MapReduce任務運行,十分適合數據倉庫的統計分析。

            不足之處:

            采用行存儲的方式(SequenceFile)來存儲和讀取數據。效率低:當要讀取數據表某一列數據時需要先取出所有數據然后再提取出某一列的數據,效率很低。同時,它還占用較多的磁盤空間。

            由于以上的不足,有人(查禮博士)介紹了一種將分布式數據處理系統中以記錄為單位的存儲結構變為以列為單位的存儲結構,進而減少磁盤訪問數量,提高查詢處理性能。這樣,由于相同屬性值具有相同數據類型和相近的數據特性,以屬性值為單位進行壓縮存儲的壓縮比更高,能節省更多的存儲空間。如下圖所示(行列存儲的比較圖):

            4、             HBase

                HBase是一個分布式的、面向列的開源數據庫,它不同于一般的關系數據庫,是一個適合于非結構化數據存儲的數據庫。另一個不同的是HBase基于列的而不是基于行的模式。HBase使用和 BigTable非常相同的數據模型。用戶存儲數據行在一個表里。一個數據行擁有一個可選擇的鍵和任意數量的列,一個或多個列組成一個ColumnFamily,一個Fmaily下的列位于一個HFile中,易于緩存數據。表是疏松的存儲的,因此用戶可以給行定義各種不同的列。在HBase中數據按主鍵排序,同時表按主鍵劃分為多個HRegion,如下圖所示(HBase數據表結構圖):

                Ok,行文至此,看似洋洋灑灑近千里,但若給讀者造成閱讀上的負擔,則不是我本意。接下來的內容,我不會再引用諸多繁雜的專業術語,以給讀者心里上造成不良影響。

                我再給出一副圖,算是對上文所說的hadoop框架及其組成部分做個總結,如下圖所示,便是hadoop的內部結構,我們可以看到,海量的數據交給hadoop處理后,在hadoop的內部中,正如上文所述:hadoop提供一個分布式文件系統(HDFS)及分布式數據庫(Hbase)用來存儲或部署到各個計算點上,最終在內部采取mapreduce的模式對其數據進行處理,然后輸出處理結果:


            第二部分、淘寶海量數據產品技術架構解讀—學習海量數據處理經驗

                在上面的本文的第一部分中,我們已經對mapreduce模式及hadoop框架有了一個深入而全面的了解。不過,如果一個東西,或者一個概念不放到實際應用中去,那么你對這個理念永遠只是停留在理論之內,無法向實踐邁進。

                Ok,接下來,本文的第二部分,咱們以淘寶的數據魔方技術架構為依托,通過介紹淘寶的海量數據產品技術架構,來進一步學習和了解海量數據處理的經驗。

            淘寶海量數據產品技術架構

                如下圖2-1所示,即是淘寶的海量數據產品技術架構,咱們下面要針對這個架構來一一剖析與解讀。

                相信,看過本博客內其它文章的細心讀者,定會發現,圖2-1最初見于本博客內的此篇文章:從幾幅架構圖中偷得半點海量數據處理經驗之上,同時,此圖2-1最初發表于《程序員》8月刊,作者:朋春。

                在此之前,有一點必須說明的是:本文下面的內容大都是參考自朋春先生的這篇文章:淘寶數據魔方技術架構解析所寫,我個人所作的工作是對這篇文章的一種解讀與關鍵技術和內容的抽取,以為讀者更好的理解淘寶的海量數據產品技術架構。與此同時,還能展示我自己讀此篇的思路與感悟,順帶學習,何樂而不為呢?。

                Ok,不過,與本博客內之前的那篇文章(幾幅架構圖中偷得半點海量數據處理經驗)不同,本文接下來,要詳細闡述這個架構。我也做了不少準備工作(如把這圖2-1打印了下來,經常琢磨):

             

                                                          圖2-1 淘寶海量數據產品技術架構

                好的,如上圖所示,我們可以看到,淘寶的海量數據產品技術架構,分為以下五個層次,從上至下來看,它們分別是:數據源,計算層,存儲層,查詢層和產品層。我們來一一了解這五層:

            1. 數據來源層。存放著淘寶各店的交易數據。在數據源層產生的數據,通過DataX,DbSync和Timetunel準實時的傳輸到下面第2點所述的“云梯”。
            2. 計算層。在這個計算層內,淘寶采用的是hadoop集群,這個集群,我們暫且稱之為云梯,是計算層的主要組成部分。在云梯上,系統每天會對數據產品進行不同的mapreduce計算。
            3. 存儲層。在這一層,淘寶采用了兩個東西,一個使MyFox,一個是Prom。MyFox是基于MySQL的分布式關系型數據庫的集群,Prom是基于hadoop Hbase技術 的(讀者可別忘了,在上文第一部分中,咱們介紹到了這個hadoop的組成部分之一,Hbase—在hadoop之內的一個分布式的開源數據庫)的一個NoSQL的存儲集群。
            4. 查詢層。在這一層中,有一個叫做glider的東西,這個glider是以HTTP協議對外提供restful方式的接口。數據產品通過一個唯一的URL來獲取到它想要的數據。同時,數據查詢即是通過MyFox來查詢的。下文將具體介紹MyFox的數據查詢過程。
            5.  產品層。簡單理解,不作過多介紹。

                接下來,咱們重點來了解第三層-存儲層中的MyFox與Prom,然后會稍帶分析下glide的技術架構,最后,再了解下緩存。文章即宣告結束。

                我們知道,關系型數據庫在我們現在的工業生產中有著廣泛的引用,它包括Oracle,MySQL、DB2、Sybase和SQL Server等等。

            MyFOX

                淘寶選擇了MySQL的MyISAM引擎作為底層的數據存儲引擎。且為了應對海量數據,他們設計了分布式MySQL集群的查詢代理層-MyFOX。

            如下圖所示,是MySQL的數據查詢過程:

                                                                        圖2-2 MyFOX的數據查詢過程

                在MyFOX的每一個節點中,存放著熱節點和冷節點兩種節點數據。顧名思義,熱節點存放著最新的,被訪問頻率較高的數據;冷節點,存放著相對而來比較舊的,訪問頻率比較低的數據。而為了存儲這兩種節點數據,出于硬件條件和存儲成本的考慮,你當然會考慮選擇兩種不同的硬盤,來存儲這兩種訪問頻率不同的節點數據。如下圖所示:

                                                                       圖2-3 MyFOX節點結構

                 “熱節點”,選擇每分鐘15000轉的SAS硬盤,按照一個節點兩臺機器來計算,單位數據的存儲成本約為4.5W/TB。相對應地,“冷數據”我們選擇了每分鐘7500轉的SATA硬盤,單碟上能夠存放更多的數據,存儲成本約為1.6W/TB。

            Prom

            出于文章篇幅的考慮,本文接下來不再過多闡述這個Prom了。如下面兩幅圖所示,他們分別表示的是Prom的存儲結構以及Prom查詢過程:

                                                          圖2-4 Prom的存儲結構

             

                                                                      圖2-5 Prom查詢過程

            glide的技術架構

                

                                                           圖2-6 glider的技術架構

                在這一層-查詢層中,淘寶主要是基于用中間層隔離前后端的理念而考慮。Glider這個中間層負責各個異構表之間的數據JOIN和UNION等計算,并且負責隔離前端產品和后端存儲,提供統一的數據查詢服務。

            緩存

                除了起到隔離前后端以及異構“表”之間的數據整合的作用之外,glider的另外一個不容忽視的作用便是緩存管理。我們有一點須了解,在特定的時間段內,我們認為數據產品中的數據是只讀的,這是利用緩存來提高性能的理論基礎。

            在上文圖2-6中我們看到,glider中存在兩層緩存,分別是基于各個異構“表”(datasource)的二級緩存和整合之后基于獨立請求的一級緩存。除此之外,各個異構“表”內部可能還存在自己的緩存機制。

                                                                       圖2-7 緩存控制體系

                圖2-7向我們展示了數據魔方在緩存控制方面的設計思路。用戶的請求中一定是帶了緩存控制的“命令”的,這包括URL中的query string,和HTTP頭中的“If-None-Match”信息。并且,這個緩存控制“命令”一定會經過層層傳遞,最終傳遞到底層存儲的異構“表”模塊。

                緩存系統往往有兩個問題需要面對和考慮:緩存穿透與失效時的雪崩效應。

            1. 緩存穿透是指查詢一個一定不存在的數據,由于緩存是不命中時被動寫的,并且出于容錯考慮,如果從存儲層查不到數據則不寫入緩存,這將導致這個不存在的數據每次請求都要到存儲層去查詢,失去了緩存的意義。至于如何有效地解決緩存穿透問題,最常見的則是采用布隆過濾器(這個東西,在我的此篇文章中有介紹:),將所有可能存在的數據哈希到一個足夠大的bitmap中,一個一定不存在的數據會被這個bitmap攔截掉,從而避免了對底層存儲系統的查詢壓力。

                而在數據魔方里,淘寶采用了一個更為簡單粗暴的方法,如果一個查詢返回的數據為空(不管是數據不存在,還是系統故障),我們仍然把這個空結果進行緩存,但它的過期時間會很短,最長不超過五分鐘。

                  2、緩存失效時的雪崩效應盡管對底層系統的沖擊非常可怕。但遺憾的是,這個問題目前并沒有很完美的解決方案。大多數系統設計者考慮用加鎖或者隊列的方式保證緩存的單線程(進程)寫,從而避免失效時大量的并發請求落到底層存儲系統上。

                在數據魔方中,淘寶設計的緩存過期機制理論上能夠將各個客戶端的數據失效時間均勻地分布在時間軸上,一定程度上能夠避免緩存同時失效帶來的雪崩效應。

            本文參考:

            1. 基于云計算的海量數據存儲模型,侯建等。
            2. 基于hadoop的海量日志數據處理,王小森
            3. 基于hadoop的大規模數據處理系統,王麗兵。
            4. 淘寶數據魔方技術架構解析,朋春。
            5. Hadoop作業調優參數整理及原理,guili。

            讀者點評@xdylxdyl:

            1. We want to count all the books in the library. You count up shelf #1, I count up shelf #2. That's map. The more people we get, the faster it goes. Now we get together and add our individual counts. That's reduce。
            2. 數據魔方里的緩存穿透,架構,空數據緩存這些和Hadoop一點關系都么有,如果是想講一個Hadoop的具體應用的話,數據魔方這部分其實沒講清楚的。
            3. 感覺你是把兩個東西混在一起了。不過這兩個都是挺有價值的東西,或者說數據魔方的架構比Hadoop可能更重要一些,基本上大的互聯網公司都會選擇這么做。Null對象的緩存保留五分鐘未必會有好的結果吧,如果Null對象不是特別大,數據的更新和插入不多也可以考慮實時維護。
            4. Hadoop本身很笨重,不知道在數據魔方里是否是在扮演著實時數據處理的角色?還是只是在做線下的數據分析的?

            結語:寫文章是一種學習的過程。尊重他人勞動成果,轉載請注明出處。謝謝。July、2011/8/20。完。

            轉自:
            http://blog.csdn.net/v_july_v/article/details/6704077

            posted @ 2012-12-23 19:55 鑫龍 閱讀(351) | 評論 (0)編輯 收藏

            1.模塊子系統(Module Subsystem)、統一設備模型(Unified Device Model)和 PnP支持模塊子系統發生了重大變化。
                
            2.穩定性有所提高 
                為了徹底避免內核加載或者導出正在被使用的內核模塊,或者至少為了減少加載或者卸載模塊的同時使用該模塊的可能性(這有時會導致系統崩潰),內核加載和導出內核模塊的過程都得到了改進。
                我一直以為Linux不會死機,直到我的基于2.4內核Linux突然死機,造成重大損失。所以,強烈建議所有基于2.4內核的Linux應用系統馬上升級內核,一定注意,升級前備份系統,防止升級出錯造成重大損失,也要防止硬件不兼容、應用系統不兼容問題,最好先測試一下,再上線運行!

            3.統一設備模型 
                統一設備模型的創建是 2.6 內核最重要的變化之一。它促進了模塊接口的標準化,其目的是更好地控制和管理設備,例如:更準確地確定系統設備。 電源管理和設備電源狀態。 改進的系統總線結構管理。

            4.即插即用(PnP)支持 
                運行 2.6 內核的 Linux 成為一個真正即插即用的 OS。例如,對 ISA PnP 擴展、遺留 MCA 和 EISA 總線以及熱插拔設備的 PnP 支持。

            5.內核基礎設施的變化 
                為了區別以 .o 為擴展名的常規對象文件,內核模塊現在使用的擴展名是 .ko。 創建了新的 sysfs 文件系統,當內核發現設備樹時就會描述它。 內存支持,NUMA 支持 ,支持更大數量的 RAM。2.6 內核支持更大數量的 RAM,在分頁模式下最高可達 64GB。

            6.NUMA 
                對非一致內核訪問(Non-Uniform Memory Access - NUMA)系統的支持是 2.6 內核中新出現的。

            7.線程模型,NPTL 
                相對于 v2.4 的 LinuxThreads,在版本 2.6 中新出現的是 NPTL(Native POSIX Threading Library)。 NPTL 為 Linux 帶來了企業級線程支持,提供的性能遠遠超過了 LinuxThreads。它所基于的用戶與內核線程的比率是 1:1。 
                在 2003 年 10 月,GNU C 程序庫 glibc 中融入了 NPTL 支持,Red Hat 率先在 Red Hat Linux 9 和 Red Hat Enterprise Linux 中使用定制的 v2.4 內核實現了 NPTL。

            8.性能改進 
                新的調度器算法 ,2.6 Linux 內核引入了新的 O(1) 算法。在高負載情況下它運行得特別好。新的調度器基于每個 CPU 來分布時間片, 這樣就消除了全局同步和重新分配循環,從而提高了性能。 
                內核搶占(Kernel Preemption) ,新的 2.6 內核是搶占式的。這將顯著地提高交互式和多媒體應用程序的性能。 
                I/O 性能改進,Linux 的 I/O 子系統也發生了重大的變化,通過修改 I/O 調度器來確保不會有進程駐留在隊列中過長時間等待進行輸入/輸出操作, 這樣就使得 I/O 操作的響應更為迅速。
                快速用戶空間互斥(Fast User-Space Mutexes) ,“futexes”(快速用戶空間互斥)可以使線程串行化以避免競態條件,引入它也提高了響應速度。 通過在內核空間中部分實現“futexes”以允許基于競爭設置等待任務的優先級而實現改進。

            9.擴展性改進 
                處理器數目更多,Linux 內核 2.6 最多可以支持 64 個 CPU。支持更大的內存,歸功于 PAE(物理地址擴展,Physical Address Extensions),在 32-位系統上分頁模式下所支持的內存增加到了 64GB。 
                用戶和組,惟一用戶和組的數量從 65,000 增至 40 多億,也就是從 16-位增加到了 32-位。 
                PID 的數量,PID 的最大數量從 32,000 增至 10 億。 
                打開文件描述符的數量,打開文件描述符的數量沒有增加,但是不再需要事先設置該參數,它將自行調節。

            10.支持更多的設備
                在 Linux 內核 2.6 之前,內核中有可以約束大型系統的限制,比如每條鏈 256 個設備。v2.6 內核徹底地打破了這些限制, 不但可以支持更多類型的設備,而且支持更多同類型的設備。在 Linux 2.6 系統中,可以支持 4095 種主要的設備類型, 每一個單獨的類型可以有超過一百萬個子設備。 文件系統大小, Linux 內核 2.6 所允許的可尋址文件系統大小最大為 16 TB。

            11.文件系統 
                ext2、ext3 和 ReiserFS 等傳統 Linux 文件系統得到了顯著的改進。最值得注意的改進是擴展屬性(或文件元數據)的引入。 最重要的是 POSIX ACL 的實現,這是對普通 UNIX 權限的擴展,可以支持更細化的用戶訪問控制。

            12.除了對傳統 Linux 文件系統的改進支持以外,新的內核完全支持在 Linux 中相對較新的 XFS 文件系統。 Linux 2.6 內核現在還引入了對 NTFS 文件系統的改進的支持,現在允許以讀/寫模式安裝 NTFS 文件系統。

            posted @ 2012-12-19 16:14 鑫龍 閱讀(268) | 評論 (0)編輯 收藏

                 摘要: 轉自https://www.ibm.com/developerworks/cn/linux/l-ipc/part6/, 作者:鄭彥興一個套接口可以看作是進程間通信的端點(endpoint),每個套接口的名字都是唯一的(唯一的含義是不言而喻的),其他進程可以發現、連接并且 與之通信。通信域用來說明套接口通信的協議,不同的通信域有不同的通信協議以及套接口的地址結構等等,因此,創建一個套接口時,要指明它...  閱讀全文

            posted @ 2012-12-18 14:04 鑫龍 閱讀(282) | 評論 (0)編輯 收藏

                 摘要: 轉自http://www.ibm.com/developerworks/cn/linux/l-ipc/part5/index1.html, 作者:鄭彥興采用共享內存通信的一個顯而易見的好處是效率高,因為進程可以直接讀寫內存,而不需要任何數據的拷貝。對于像管道和消息隊列等通信方式,則需要在內 核和用戶空間進行四次的數據拷貝,而共享內存則只拷貝兩次數據[1]:一次從輸入文件到共享內存區,另一次從共享內...  閱讀全文

            posted @ 2012-12-18 14:03 鑫龍 閱讀(259) | 評論 (0)編輯 收藏

            僅列出標題
            共20頁: First 7 8 9 10 11 12 13 14 15 Last 
            理论片午午伦夜理片久久| 亚洲国产成人久久综合一区77 | 色狠狠久久AV五月综合| 久久久久久午夜精品| 色综合久久久久久久久五月| 国内精品伊人久久久久av一坑| 9999国产精品欧美久久久久久| 日韩AV毛片精品久久久| 久久综合九色综合网站| 久久久久国色AV免费看图片| 热re99久久精品国99热| 精品久久久久久无码中文字幕 | 久久久久亚洲精品中文字幕| 色综合久久久久综合体桃花网| 狠狠色综合久久久久尤物| 99久久夜色精品国产网站 | 久久中文字幕一区二区| 久久福利资源国产精品999| 91精品国产色综久久 | 精品少妇人妻av无码久久| 天堂无码久久综合东京热| 亚洲国产天堂久久综合网站| 久久亚洲国产成人精品性色| 亚洲一级Av无码毛片久久精品| 久久99精品久久久久久野外 | 99久久综合国产精品免费| 久久久久国产精品嫩草影院| 久久精品9988| 狠狠干狠狠久久| 精品久久一区二区三区| 99久久99久久久精品齐齐| 日韩精品无码久久久久久| 久久无码中文字幕东京热| 免费久久人人爽人人爽av| 18禁黄久久久AAA片| 久久天天躁夜夜躁狠狠| 中文成人无码精品久久久不卡| 日韩亚洲国产综合久久久| 久久久久久噜噜精品免费直播| 久久久精品人妻无码专区不卡 | 国产精品日韩欧美久久综合|