Hadoop權威指南:知識梳理(二)

第12章 關於Avro

Apache Avro 獨立於編程語言的數據序列化系統,支持壓縮、可切分

意在解決Hadoop中Writable類型的不足:缺乏語言的可移植性

 

Avro模式

通常用json編寫

Avro有豐富的模式解析能力,讀數據所用的模式不必與寫數據所用的模式相同

 

Avro定義了少量的基本數據類型,通過編寫模式的方式,可以被用於構建應用特定的數據結構

  • 基本類型:null / boolean / int / long / float / double / bytes / string
  • 複雜類型:array / map / record / enum / fixed / union

 

Avro序列化:

(1) 創建Avro模式

StringPair.avsc
{
    "type":"record",
    "name":"StringPair",
    "doc":"A pair of strings",
    "fields":[
        {"name":"left","type":"string"},
        {"name":"right","type":"string"}
    ]
}

 

(2) 加載模式

Schema.Parser parser = new Schema.Parser();

Schema schema = parser.parse(getClass().getResourceAsStream("StringPair.avsc"))

 

(3) 創建實例

GenericRecord datum = new GenericData.Record(schema); //可以用StringPair代替

datum.put("left","L");

datum.put("right","R");

 

(4) 輸出到流

ByteArrayOutputStream out = new ByteArrayOutputStream();

DatuWriter<GenericRecord> writer = new GenericDatumWriter<GenericRecord>(schema);

Encoder encoder = EncoderFactory.get().binaryEncoder(out,null);

writer.write(datum,encoder);

encoder.flush();

out.close();

 

(5) 反向讀回對象

DatumReader<GenericRecord> reader = new GenericDatumReader<GenericRecord>(schema);

Decoder decoder = DecoderFactory.get().binaryDecoder(out.toByteArray(),null);

GenericRecord result = reader.read(null,decoder);

assertThat(result.get("left").toString(),is("L"));

assertThat(result.get("right").toString(),is("R"));

 

Avro容器:

Avro容器主要存儲Avro對象序列,包括:Avro模式 + sync marker + 序列化對象數據塊

Avro格式打印:

java -jar $AVRO_HOME/avro-tools-*.jar tojson pairs.avro


第13章 關於Parquet

 

列式存儲格式,parquet能夠以真正的列式存儲格式來保存具有深度嵌套結構的數據

 

parquet原子類型:boolean int32 int64 int96 float double binary fixed_len_byte_array

parquet邏輯類型:UTF8   ENUM   DECIMAL   DATE   LIST   MAP

舉例:

LIST

message m {

required group a(LIST){

repeated group list{

required int32 element;}

}
}

parquet利用group類型構造複雜的類型,沒有註釋的group就是一個簡單的嵌套記錄

parquet使用Dremel編碼對任意一列數據的讀取都不需要涉及到其他列

parquet由 文件頭 + 多個文件塊 + 文件尾(版本信息、模式信息、鍵值、元數據信息)組成

 

parquet讀數據過程:

       由於元數據保存在文件尾中,因此在讀parquet文件時,首先要找到文件的結尾,然後讀取文件尾中的元數據長度,並根據元數據長度逆向讀取文件尾中的元數據

       parquet不需要sync marker,因爲文件塊之間的邊界信息被保存在文件尾的元數據中,因此parquet文件是可分割且可並行處理的。

 

      Header      Block    Block   Block   Block    Footer    行組     每個文件負責一個行組

                           |

Row group    Column chunck     Column chunck           行組 由 列塊構成,且一個列存儲一列數據

                           |

                       Page Page Page                                     默認1MB 數據以頁爲單位存儲

 

頁是parquet文件的最小存儲單元,要讀取任意一行數據,就必須對這一行數據的頁進行解壓縮和解編碼處理。對於單行查找來說,頁越小,在找到目標值之前需要讀取的值就也少,效率越高

 

parquet自帶的編碼方式:

          差分編碼、遊程長度編碼、字典編碼

Parquet會根據列的類型自動選擇合適的編碼方式,對於嵌套數據來說,每一頁還需要存儲該頁所包含的列定義深度和列元素重複次數。

 

parquet的文件塊大小不能超過其HDFS塊的大小

 

Parquet文件的讀寫:

(1)  Parquet文件

MessageType schema = MessageTypeParser.parseMessageType(

   "message Pair{\n" + "required binary left (UTF8); \n"+

   "required binary right (UTF8); \n"+

"}");

 

(2)  構造Message

GroupFactory groupFactory = new SimpleGroupFactory(schema);

Group group = groupFactory.newGroup().append("left","L").append("right","R");

 

(3) 寫入 WriteSupport

Configuration conf = new Configuration();
Path path = new Path("data.parquet");
GroupWriteSupport writeSupport = new GroupWriteSupport();
GroupWriteSupport.setSchema(schema,conf);
ParquetWriter<Group> writer = new ParquetWriter<Group>(path,writeSupport,
    ParquetWriter.DEFAULT_COMPRESSION_CODEC_NAME,
    ParquetWriter.DEFAULT_BOLOCK_SIZE,
    ParquetWriter.DEFAULT_PAGE_SIZE,
    ParquetWriter.DEFAULT_PAGE_SIZE,
    ParquetWriter.DEFAULT_IS_DECTIONARY_ENABLED,
    ParquetWriter.DEFAULT_IS_VALIDATING_ENABLED,
    ParquetWriter.WriterVersion.PARQEUT_1_0,conf
)
writer.write(group);
writer.close();

 

(4) 讀取 ReadSupport

GroupReadSupport readSupport = new GroupReadSupport();
ParquetReader<Group> reader = new ParquetReader<Group>(path,readSupport);
Group result = reader.read();
assertThat(result.getString("left",0),is("L"));

 

AvroParquetWriter、ProtoParquetWriter、ThriftParquetWriter


第14章 關於Flume

      source --- channel --- sink

flume-ng agent \

--conf-file spool-to-logger.properties \     屬性配置

--name agent1

--conf $FLUME_HOME/conf \   通用配置

-Dflume.root.logger=INFO,console

 

一旦事務中的所有事件全部傳遞到channel且提交成功,那麼source就將該文件標註爲完成

如果channel到sink無法記錄,事務會回滾,而所有的事件仍保留在channel中

 

寫文件的結束條件:

  1. 超過給定的打開時間
  2. 達到給定的文件大小
  3. 寫滿了給定數量的事件

 

分區存儲方式:agent1.sinks.sink1.hdfs.path=xxx/year=%Y/month=%m/day=%d

一個Flume事件被寫入到哪個分區是由事件的header中的timestamp決定的,默認情況下沒有時間戳,它通過Flume的攔截器添加

 

爲source1增加一個時間戳攔截器,將source產生的每個時間添加一個timestamp header

agent1.sources.source1.interceptors = interceptor1

agent1.sources.source1.interceptors.interceptor1.type = timestamp

 

扇出:從一個source向多個channel,多個sink傳遞事件

agent1.sources = source1

agent1.sinks = sink1a sink1b

agent1.channels = channel1a channel1b

 

agent1.sources.source1.channels = channel1a channel1b

agent1.sinks.sink1a.channel = channel1a

agent1.sinks.sink1b.channel = channel1b

 

agent1.sources.source1.type = spooldir

agent1.sources.source1.spoolDir = /tmp/spooldir

 

agent1.sinks.sink1a.type = hdfs

agent1.sinks.sink1a.hdfs.path = /tmp/flume

agent1.sinks.sink1a.hdfs.filePrefix = events-%{host}

agent1.sinks.sink1a.hdfs.fileSuffix = .log

agent1.sinks.sink1a.hdfs.fileType = DataStream

 

agent1.sinks.sink1b.type = logger

 

agent1.channels.channel1a.type = file

agent1.channels.channel1b.type = memory

 

複用選擇器:某些事件發送到特定channel

Flume事件匯聚、Flume代理:p388

事務、交付保證:(1)多個類似的agent代理,防止agent掛掉 (2)多個類似的sink組

 

Sink組:多個sink當作一個sink處理,以實現故障轉移和負載均衡

               如果某個sink不可用,就嘗試下一個sink,如果都不可用,事件也不會從channel中刪除

               processor.backoff參數:防止重複連接sink組中的故障sink

 

Flume掌握:source、channel、sink、interceptor

 

p396:source、channel、sink、interceptor基本類別


第15章 關於Sqoop

Apache Sqoop是一個開源工具,允許用戶將數據從結構化存儲器抽取到Hadoop中,用於進一步處理

 

Sqoop1 與 Sqoop2:

      Sqoop2對Sqoop進行了重寫,以解決Sqoop1架構上的侷限性

  • Sqoop1是命令行工具,不提供Java api,編寫新的連接器需要做大量的工作
  • Sqoop2具有以運行作業的服務器組件和一整套客戶端,包括命令行接口、用戶界面、REST API、Java api,Sqoop2的CLI與Sqoop1的CLI並不兼容

%sqoop

%sqoop help

%sqoop help import

 

Sqoop連接器:一個Sqoop連接器就是這個框架下的一個模塊化組件,用於支持Sqoop的導入和導出操作。包括:mysql、postgresql、oracle、Sql Server、DB2、Netezza

 

導入數據:

sqoop import --connect jdbc:mysql://localhost/hadoopguide --table widgets -m 1

默認情況下,該作業會並行使用4個map任務來加速導入過程

 

生成代碼:

sqoop codegen --connect jdbc:mysql://localhost/hadoopguide --table widgets --class-name Wight

  • Sqoop查詢是根據劃分列:--split
  • Sqoop導入控制:--where --query
  • 定時運行導入:只有當特定列(--check-column)的值大於指定值(--last-value)時,Sqoop纔會導入數據
  • 直接模式導入:--direct (比基於JDBC的導入更加高效)

 

Sqoop導入到Hive

        Sqoop根據關係源數據中的表來生成一個Hive表

sqoop create-hive-table --connect jdbc:mysql://localhost/hadoopguide \

--table wights --fields-terminated-by ',' -m 1 --hive-import

 

Sqoop保存大對象

        大對象通常保存在CLOB或BLOB類型的列中,一般大對象和他們的行分開存儲,在訪問大對象時,需要通過行中包含的引用來打開它

 

Sqoop導出

sqoop export --connect jdbc:mysql://localhost/hadoopguide -m 1 \

--table sales_by_zip --export-dir /usr/hive/warehouse/zip_profits \

--input-fileds-terminated-by '\0001'

 

Sqoop導出過程:

Sqoop將數據導出到一個臨時階段表中,然後在導出任務完成前,在一個事務中將臨時階段表中的數據全部轉移到目標表中


第17章 關於Hive

 

Hive執行引擎:mapreduce、tez、spark

       在使用mapreduce時,中間作業的輸出會被“物化”存儲在hdfs上,tez和spark則不同,會根據Hive規劃器的請求,把中間結果寫到本地磁盤上,甚至在內村中緩存,以避免額外的複製開銷

 

寫時模式:傳統數據庫在寫入時檢查,寫時模式有利於提高查詢性能

讀時模式:Hive在讀數據時檢查,不需要解析,數據的加載僅僅是文件複製或移動

 

       Hdfs不提供就地文件更新,因此插入、更新和刪除操作引起的一切變化都會保存在一個較小的增量文件中,由metastore在後臺運行的mapreduce作業會定期將這些增量合併到“基表”文件中

 

事務:Hive在0.13.0引入事務

鎖:Hive在0.7.0版本引入了表級和分區級的鎖,鎖由zookeeper透明管理

 

Hive索引:緊湊索引、位圖索引。緊湊索引存儲每個值的hdfs塊號,位圖索引使用壓縮的位集合來高效存儲具有某個特殊值的行

 

其他SQL-on-Hadoop:Impala、Presto、Spark SQL、Phoenix(SQL on HBase)

 

Hive的數據類型:boolean、tinyint、samllint、int、bigint、float、double、decimal、string、varchar、char、binary、timestamp、date、array、map、struct、union

 

  • TINYINT:1字節有符號整數,-128 - 127,對應java byte
  • SMALLINT:2字節有符號整數,-32768 - 32767,對應java short
  • INT:4字節有符號整數,-2147483648 - 2147483647,對應java int
  • BIGINT:8字節有符號整數,對應java long
  • FLOAT:4字節單精度浮點數
  • DOUBLE:8字節雙精度浮點數
  • DECIMAL:任意精度有符號小數

 

  • STRING:無上限可變長度字符串
  • VARCHAR:可變長度字符串
  • CHAR:固定長度字符串

 

  • ARRAY:例:array(1,2)
  • Map:例:map('a',1,'b',2)
  • STRUCT:struct(‘a’,1,1.0)
  • UNION:create_union(1,'a',63)

 

Hive隱式類型轉換:任何數值類型都可以隱式轉換爲一個範圍更廣的類型或者文本類型(STRING VARCHAR CHAR)

Hive強制類型轉換: cast('xxx' as int) 轉換失敗會返回null

 

查看分區:show partitions xxx

 

存儲格式:

  • 默認的行內分隔符不是製表符,而是ASCII控制碼集合中的Control-A
  • 集合類元素的默認分隔符爲字符Control-B

 

導入數據:CATS:create table ...... as select

多表插入:

from source

insert overwrite table xxx select col1,col2

insert overwirte table yyy select col3

 

sort by < order by < distribute by < cluster by

  • sort by : 爲每個reducer排序
  • order by :全排序
  • distribute by :分配同一個reducer之中

 

視圖:視圖是隻讀的,無法通過視圖爲基表加載或插入數據

 

  1. UDF:一個輸入行,一個輸出行
  2. UDAF:多個輸入行,一個輸出行
  3. UDTF:一個輸入行,多個輸出行

第19章 關於Spark

 

DAG引擎:Spark作業是由任意的多階段有向無環圖(DAG)構成

                   job -----> 多個stage ----->運行在RDD分區上

 

RDD:彈性分佈式數據集,在集羣中跨多個機器分區存儲的一個只讀的對象集合

加載或執行轉換並不會立即觸發任何數據處理的操作,只不過創建了一個計算的計劃,只有當RDD執行某個動作時,纔會觸發真正的計算

 

RDD的創建:

  1. 來自內存中的對象集合: sc.parallelize(1 to 10,10)
  2. 使用外部存儲器中的數據集(如HDFS): RDD[String] = sc.textFile(inputPath)
  3. 對現有RDD進行轉換

 

RDD的轉換:(1)轉換 (2)動作

                      如果返回類型是一個RDD,則爲轉換,否則爲動作

 

  • reduceByKey() 不需要初始值

val pairs:RDD[(String,Int)] = sc.parallelize(Array(("a",3)))

val sums:RDD[(String,Int)] = pairs.reduceByKey(_+_)

  • foldByKey()需要初始值

val sums:RDD[(String,Int)] = pairs.foldByKey(0)(_+_)

  • aggregateByKey

val sets:RDD[(String,HashSet[Int])] = pairs.aggregateByKey(new HashSet[Int])(_+=_,_++=_)

 

第一個函數負責把Int合併到HashSet[Int]中

第二個函數負責合併兩個HashSet[Int]中的值

例如:Array((“a”,3),(“a”,1),(“b”,7),("a",5))

結果爲:((“a”,Set(1,3,5)),("b",7))

 

持久化:cache()並不會立即緩存RDD,它用一個標誌來對RDD進行標記,以指示RDD應當在Spark作業運行時被緩存

持久化級別:MEMORY_ONLY MEMEORY_ONLY_SER

 

序列化:

           Kryo序列化: conf.set("spark.serializer","org.apache.spark.serializer.KryoSerializer")

 

廣播變量:

在經過序列化後發送給各個executor,然後緩存在那裏,以便後期任務可以在需要時訪問它

val lookup:Broadcast[Map[Int,String]] = sc.broadcast(Map(1 ->"a",2->"e",3->"i",4->"o"))

val result = sc.parallelize(Array(2,1,3)).map(lookup.value(_))

 

累加器:只做加法的累加器,類似於MapReduce中的計數器

val count:Accumulator[Int] = sc.accumulator(0)

val result = sc.parallelize(Array(1,2,3)).map(i => {count +=1; i}}) .reduce((x,y) => x+y)

 

Spark program

          |

SparkContext

          |

DAGScheduler

          |

TaskScheduler

          |

SchedulerBackend----------->ExecutorBackend

                                                        |

     dirver                                     Executor

                                                        |

                                            ShuffleMapTask

 

                                                   executor

 

dirver:負責託管應用並作爲作業調度任務

executor:專屬應用

 

兩種類型的任務:shuffle map任務 、 result任務

  • shuffle map任務運行在除最終階段之外的其他所有階段中,返回一些可以讓下一階段檢索其分區的信息
  • result任務運行在最終階段,每個result任務在它自己的RDD分區上計算,並把結果發送給driver,driver進行彙總

 

執行管理模式:

  • 本地模式:有一個executor和dirver運行在同一個JVM中

local 、local[n]、local(*) (機器的每一個內核一個線程)

  • 獨立模式
  • Mesos模式
  • Yarn模式:yarn-client 、 yarn-cluster

                         yarn是唯一一個能夠與Hadoop的Kerberos集成的管理器

 

yarn-client    客戶端模式的driver在客戶端運行

yarn-cluster  集羣模式的driver在yarn的application master上運行


第20章 關於HBase

        面向列的分佈式數據庫,可以實時隨機訪問超大規模數據集

基本概念:

  • 行鍵
  • 列族    每個列都具有相同的前綴 列族:修飾符

                  一個表的列族要提前給出,列可以在更新中提供。只要列族存在,列可以隨時加進去

 

Master ---------------------------> ZooKeeper Cluster 【hbase:meta 目標主控機等信息】

    |

Regionserver

    |

HDFS

 

hbase:meta

      特殊目錄表,維護着當前集羣上所有區域的列表、狀態和位置

      hbase:meta表中的項使用區域名作爲鍵(有序),區域名由所屬的表名、區域的起始行、區域的創建時間以及MD5哈希值組成

例如:TestTable,xyz,12379989859898.1sds123ffdf

      區域變化:分裂、禁用、啓用等操作,目錄表會進行相應的更新

 

客戶端通過hbase:meta查找到所有節點及其位置,然後直接連接regionserver進行交互

客戶端會對hbase:meta的內容進行緩存,一旦發生錯誤,再去查看hbase:meta獲取新位置

  • “重做”日誌內容
  • 文件壓縮
  • 文件分割

 

hbase shell
create 'test','data'
list
scan 'test'
put 'test','row1','data:1','value1'
get 'test','row1'
disable 'test'
drop 'test'
表的離線:disable
表的在線:enable

HBase特性:

  • 沒有真正的索引
  • 自動分區
  • 線性擴展和新節點的自動管理
  • 普通商用硬件支持
  • 容錯
  • 批處理

 

HBase使用HDFS的方式 與 Mapreduce使用HDFS方式 區別:

  • Mapreduce首先打開HDFS文件,然後map任務流失處理文件內容,最後關閉文件
  • HBase中,數據文件在啓動時就被打開,並在處理過程中始終保持打開的狀態

第21章 關於ZooKeeper

      ZooKeeper是Hadoop分佈式協調服務,不能避免分佈式出現部分失敗

 

ZooKeeper具有以下特點:

  • 簡單、精簡
  • 可以實現多種協調數據結構和協議:分佈式隊列、分佈式鎖、領導者選舉
  • 避免系統出現單點故障,構建可靠應用程序
  • 松耦合交互方式
  • 提供了通用協調模式實現方法的開源共享庫

 

znode:既可以保存數據的容器,也可以保存其他znode容器

             創建znode的參數:路徑、znode內容、控制列表、znode類型

//ZooKeeper創建組
public class CreateGroup imploements Wather{
    
    private static final int SESSION_TIMEOUT = 5000;
    
    private ZooKeeper zk;
    private CountDownLatch connectedSignal = new CountDownLatch(1);
    
    public void connect(String hosts) throws Exception{
        zk = new ZooKeeper(hosts,SESSION_TEIMOUT,this);
        //主機地址、會話超時參數、Watcher實例
        connectedSignal.await();
    }
    
    @Override
    public void process(WatchedEvent event){
        if(event.getState()== KeeperState.SyncConnected){
            connectedSignal.countDown();
        }
    }
    
    public void create(String groupName) throws Exception{
        String path = "/" + groupName;
        String createdPath = zk.create(path,null,Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT);
    }
    
    public void close() throws Exception{
        zk.close();
    }
}

Znode類型:

  • 短暫的:短暫znode會被zk服務刪除,依賴客戶端會話
  • 持久的:不依賴會話

 

列出列表:zkCli.sh -server locahost ls /zoo

 

刪除組:

           節點路徑、版本號

 

如果提供的版本號一致,ZooKeeper會刪除這個znode

如果版本號設置成-1,可以繞過版本檢測機制,不管znode版本號都會刪除

 

zk的目的:

ZooKeeper用來協調服務,不是用來大容量數據存儲,因此一個znode能存儲的數據限制在1MB以內。且zk訪問具有原子性,zk允許客戶端讀到的數據滯後於zookeeper服務的最新狀態

 

zk順序號:

如果創建znode時設置了順序標誌,在創建znode會附加一個值,這個值由一個單調遞增的計數器添加

在一個分佈式系統中,順序號可以被哦用於爲所有的事件進行全局排序,這樣客戶端就可以通過順序號來推斷事件的順序

 

觀察、觸發事件

exsits、getData、getChildren

 

基本操作

create、delete、exists、getACL、setACL、getChildren、getData、setData、sync

quota:用來設置某個節點的子字節數和本身的數據長度:setquota /xx -n number -b byte

 

ACL列表:

ACL依賴於ZooKeeper的客戶端身份驗證機制

  • digest 通過用戶名和密碼識別客戶端
  • sasl 通過Kerberos來識別客戶端
  • ip 通過客戶端的ip地址來識別客戶端

 

ZooKeeper運行方式:

  • 獨立模式:只有一個ZooKeeper服務器
  • 複製模式:ZooKeeper通過複製模式來實現高可用性,只要集羣中半數以上的機器處於可用狀態,就能夠提供服務。確保對znode樹上的每一個修改都會被複制到集羣中超過半數的機器上

 

ZooKeeper使用了Zab協議(非Paxos,依靠TCP保證消息順序)

  1. 領導者選舉:一旦半數的跟隨者已經將其狀態與領導者同步,則表明這個階段已完成
  2. 原子廣播:所有的寫請求都會轉發給領導者,再由領導者將更新廣播給跟隨者,當半數跟隨者已經將修改持久化後,領導者纔會提交這個更新,客戶端纔會收到更新成功的響應

 

        如果領導者出現故障,其餘的機器會選出另外一個領導者,並和新的領導者一起繼續提供服務。如果之前的領導者恢復正常,則會成爲更隨者

 

領導者負責提供寫請求、跟隨者負責響應讀請求

 

一致性:

  1. 順序一致性:對znode的更新都賦予了全局ID。會按照發送順序被提交
  2. 原子性
  3. 單一系統映象:一個客戶端無論連接那一臺服務器,都將看到同樣的系統視圖
  4. 持久性
  5. 及時性:任何客戶端所看到的滯後系統視圖都是有限的,在讀數據之前調用sync

 

Zookeeper“滴答”:

tick time:會好超時參數的值不可以小於2個滴答其不可以大於20個滴答

一般zk的服務器越多,會話超時的設置應該越大;連接超時、讀超時、ping設置越小

 

Zookeeper狀態轉移:

Connecting --- > Connected ---> Closed

 

Zookeeper兩種異常:

  • InterruptedException:interrupt 連接異常
  • KeeperException:通信問題

 

分佈式鎖:可用於大型分佈式系統中實現領導者選舉

                  分佈式鎖能夠在一組進程之間提供互斥機制,使得任何時刻只有一個進程可以持有鎖

 

實現原理:

指定一個鎖的znode

希望獲得鎖的客戶端創建一些短暫順序的znode作爲znode的子節點,爲競爭者進行強制排序

在任何時間點,順序號最小的客戶端將持有鎖

例如:/leader節點下,/leader/lock-1 和 /leader/lock-2    lock-1會持有鎖

 

釋放鎖:

       刪除節點即可

 

分佈式鎖造成的問題:

  1. 羊羣效應:每次鎖釋放或一個新進程開始申請鎖的時候,觀察者會被觸發通知每一個客戶端, 而只有一個客戶端獲得鎖,這個過程會產生峯值流量,對zk造成壓力

解決方法:當前子節點消失時通知下一個客戶端

 

     2.  可恢復異常:連接丟失導致操作失敗,重新連接會造成刪不掉的孤兒znode,導致死鎖

解決方法:znode名稱嵌入一個ID,如果客戶端出現連接丟失,重新連接後可以對鎖節點的所有子節點進行檢查,查看是否包含ID,如果有,則知道自己創建成功,不需要再創建

 

zookeeper觀察節點:

沒有投票權的跟隨者,在不影響寫性能的情況下提高讀性能

 

myid:每個服務器的id

Zookeeper配置:

tickTime = 2000

dataDir=/disk1/zookeeper

dataLogDir=/disk2/zookeeper clientPort=2181 //客戶端端口

initLimit=5//跟隨者與領導者同步的時間範圍,半數以上的跟隨者需未完成,領導者將棄位,重新領導者選舉

syncLimit=2 //允許跟隨者與領導者同步的時間,未完成,跟隨者會重啓

server.1=zookeeper1:2888:3888 //2888:跟隨者端口

server.2=zookeeper1:2888:3888 //3888:領導者選舉階段與其他服務器連接端口

server.3=zookeeper1:2888:3888

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章