㈠ linux磁碟分區的Linux磁碟分區
在Windows操作系統中,是先將物理地址分開,再在分區上建立目錄.在Windows操作系統中,所有路徑都是從盤符開始,如C://program file。
Linux正好相反,是先有目錄,再將物理地址映射到目錄中。在Linux操作系統中,所有路徑都是從根目錄開始。Linux默認可分為3個分區,分別是boot分區、swap分區和根分區。
無論是Windows操作系統,還是Linux操作系統,每個分區均可以有不同的文件系統,如FAT32、NTFS、Yaffs2等。
(1)boot分區
該分區對應於/boot目錄,約100MB.該分區存放Linux的Grub(bootloader)和內核源碼。用戶可通過訪問/boot目錄來訪問該分區.換句話說,用戶對/boot目錄的操作就是操作該分區。
(2)swap分區
該分區沒有對應的目錄,故用戶無法訪問。
Linux下的swap分區即為虛擬內存.虛擬內存用於當系統內存空間不足時,先將臨時數據存放在swap分區,等待一段時間後,然後再將數據調入到內存中執行.所以說,虛擬內存只是暫時存放數據,在該空間內並沒有執行。
Ps:虛擬內存
虛擬內存是指將硬碟上某個區域模擬為內存.因此虛擬內存的實際物理地址仍然在硬碟上.虛擬內存,或者說swap分區只能由系統訪問,其大小為物理內存的2倍。
(3)根分區
在Linux操作系統中,除/boot目錄外的其它所有目錄都對應於該分區.因此,用戶可通過訪問除/boot目錄外的其它所有目錄來訪問該分區。
Attention!!!
(1)在Linux操作系統中,用戶可根據需要進行修改分區.修改後的分區中,同一目錄下的文件可能在不同分區中.比如/home目錄下有a、b、c三個目錄,可將不同的分區掛載到這三個目錄下,這種操作是允許的。
(2) 邏輯分割的數量依操作系統而不同,在Linux系統中,IDE硬碟最多有59個) 邏輯分割(5號到63號), SATA硬碟則有11個) 邏輯分割(5號到15號)。 (鳥哥版的)
不過根據最新的 linux內核技術規范 中指示,邏輯分區可以無限。
<1>硬碟上至少有1個主分區。
<2>邏輯分區不能再進行分區。
(3)Linux分區目錄和盤符的關系:
假如硬碟安裝在IDE1的主盤,並用戶想分區成6個可以使用的硬碟分區,則可以採用下面兩種方式。
方式一:採用3個主分區和3個邏輯分區
方式二:採用1個主分區和5個邏輯分區
當然還有其他的分區方式,只要滿足上述說的規則就行
安裝Linux時,默認分為三個區,分別是/boot分區、根分區和swap分區.這三個分區分別對應的盤符是hda1、hda2、hda3。
(4)Linux允許使用fdisk -l命令和df -h命令來查詢其硬碟分區.其中,df無法顯示出swap分區的大小。
[root@localhost /]#df -h
文件系統 容量 已用 可用 已用% 掛載點
/dev/hda2 8.8GB 3.1GB 5.3GB 38% / (根分區)
/dev/hda1 99MB 9.2MB 85MB 10% /boot (boot分區)
(5)在PC機下,A、B盤並不存在,這兩個盤在Linux下類似於hda1/hda3,而C盤類似於hda2,D、E、F盤類似於hda5、hda6、hda7。
(6)swap分區不對應盤符。
(7)若硬碟的MBR已壞,則該磁碟就不能再作為引導盤,只能作為數據盤.因為MBR位於硬碟的起始處,用戶不能通過軟體進行修復,也不能跳過起始處.而硬碟中間的某個磁軌壞了,用戶可以軟體修復,也可以跳過該磁軌。
㈡ uboot源碼怎麼查看nandflash分區表
你只能通過NandFlash控制器訪問NandFlash,即是只要知道Nand控制器的寄存器地址即可。NandFlash 不是一個RamLike的器件。Uboot放入nand中,在nand的0地址開始存放,移植時候需要注意頁對齊,這樣Uboot才可以可以通過StepingStone引導。
㈢ 描述安裝LINUX至少需要哪兩個分區,還有哪些常用分區
一般來說我們需要一個swap分區,一個/boot分區,一個/usr分區,一個/home
分區,一個/var/log分區。當然這沒有什麼規定,完全是依照你個人來定的。但記住至少要有兩個分區,一個swap分區,一個/分區。
分區介紹:
swap分區是linux暫時存儲數據的交換分區,它主要是把主內存上暫時不用得數據存起來,在需要的時候再調進內存內,且作為swap使用的分區不用指定「mout
point」(載入點),既然它作為交換分區,我們理所當然應給它指定大小,它至少要等於系統上實際內存的量,一般來說它的大小是內存的兩倍,如果你是16mb的內存,那麼swap分區的大小是32mb左右,以此類推。但必須還要注意一點,swap分區不要大於128mb,因為系統不需要太大的交換分區。以此類推,如果你是128mb或更大的內存,swap分區也只能最大被定為127mb。況且你還必須注意的是如果你是128mb(或更大)的內存,你必須提醒系統你有這么大的內存,要不然它可不認你這個128mb內存。具體如下:當順利啟動了安裝過程後,會顯示一個boot:提示符,這時你只要鍵入boot:linux
mem=128mb就可以了。另外你也可以創建和使用一個以上的交換分區,最多16個。
*linux
native是存放系統文件的地方,它只能用ext2的分區類型,上面已說過。對windows用戶來說,操作系統必須裝在同一分區里,它是商業軟體嗎!所以你沒有選擇的餘地!對red
hat
linux來說,你有了較大的選擇餘地,你可以把系統文件分幾個區來裝(必須要說明載入點),也可以就裝在同一個分區中(載入點是「/」)。下面我們看看可以創建哪些分區(僅列常用幾種)。
/boot分區,它包含了操作系統的內核和在啟動系統過程中所要用到的文件,建這個分區是有必要的,因為目前大多數的pc機要受到bios的限制,況且如果有了一個單獨的/boot啟動分區,即使主要的根分區出現了問題,計算機依然能夠啟動。這個分區的大小約在50mb—100mb之間。
/usr分區,是red
hat
linux系統存放軟體的地方,如有可能應將最大空間分給它。
/home分區,是用戶的home目錄所在地,這個分區的大小取決於有多少用戶。如果是多用戶共同使用一台電腦的話,這個分區是完全有必要的,況且根用戶也可以很好地控制普通用戶使用計算機,如對用戶或者用戶組實行硬碟限量使用,限制普通用戶訪問哪些文件等。其實單用戶也有建立這個分區的必要,因為沒這個分區的話,那麼你只能以根用戶的身份登陸系統,這樣做是危險的,因為根用戶對系統有絕對的使用權,可一旦你對系統進行了誤操作,麻煩也就來了。
/var/log分區,是系統日誌記錄分區,如果設立了這一單獨的分區,這樣即使系統的日誌文件出現了問題,它們也不會影響到操作系統的主分區。
/tmp分區,用來存放臨時文件。
/bin分區,存放標准系統實用程序。
/dev分區,存放設備文件。
/opt分區,存放可選的安裝的軟體。
/sbin分區,存放標准系統管理文件。
㈣ 如何確定Kafka的分區數,key和consumer線程數
一、客戶端/伺服器端需要使用的內存就越多
先說說客戶端的情況。Kafka 0.8.2之後推出了Java版的全新的procer,這個procer有個參數batch.size,默認是16KB。它會為每個分區緩存消息,一旦滿了就打包將消息批量發出。看上去這是個能夠提升性能的設計。不過很顯然,因為這個參數是分區級別的,如果分區數越多,這部分緩存所需的內存佔用也會更多。假設你有10000個分區,按照默認設置,這部分緩存需要佔用約157MB的內存。而consumer端呢?我們拋開獲取數據所需的內存不說,只說線程的開銷。如果還是假設有10000個分區,同時consumer線程數要匹配分區數(大部分情況下是最佳的消費吞吐量配置)的話,那麼在consumer client就要創建10000個線程,也需要創建大約10000個Socket去獲取分區數據。這裡面的線程切換的開銷本身已經不容小覷了。
伺服器端的開銷也不小,如果閱讀Kafka源碼的話可以發現,伺服器端的很多組件都在內存中維護了分區級別的緩存,比如controller,FetcherManager等,因此分區數越多,這種緩存的成本越久越大。
二、文件句柄的開銷
每個分區在底層文件系統都有屬於自己的一個目錄。該目錄下通常會有兩個文件: base_offset.log和base_offset.index。Kafak的controller和ReplicaManager會為每個broker都保存這兩個文件句柄(file handler)。很明顯,如果分區數越多,所需要保持打開狀態的文件句柄數也就越多,最終可能會突破你的ulimit -n的限制。
三、降低高可用性
Kafka通過副本(replica)機制來保證高可用。具體做法就是為每個分區保存若干個副本(replica_factor指定副本數)。每個副本保存在不同的broker上。期中的一個副本充當leader 副本,負責處理procer和consumer請求。其他副本充當follower角色,由Kafka controller負責保證與leader的同步。如果leader所在的broker掛掉了,contorller會檢測到然後在zookeeper的幫助下重選出新的leader——這中間會有短暫的不可用時間窗口,雖然大部分情況下可能只是幾毫秒級別。但如果你有10000個分區,10個broker,也就是說平均每個broker上有1000個分區。此時這個broker掛掉了,那麼zookeeper和controller需要立即對這1000個分區進行leader選舉。比起很少的分區leader選舉而言,這必然要花更長的時間,並且通常不是線性累加的。如果這個broker還同時是controller情況就更糟了。
說了這么多「廢話」,很多人肯定已經不耐煩了。那你說到底要怎麼確定分區數呢?答案就是:視情況而定。基本上你還是需要通過一系列實驗和測試來確定。當然測試的依據應該是吞吐量。雖然LinkedIn這篇文章做了Kafka的基準測試,但它的結果其實對你意義不大,因為不同的硬體、軟體、負載情況測試出來的結果必然不一樣。我經常碰到的問題類似於,官網說每秒能到10MB,為什麼我的procer每秒才1MB? —— 且不說硬體條件,最後發現他使用的消息體有1KB,而官網的基準測試是用100B測出來的,因此根本沒有可比性。不過你依然可以遵循一定的步驟來嘗試確定分區數:創建一個只有1個分區的topic,然後測試這個topic的procer吞吐量和consumer吞吐量。假設它們的值分別是Tp和Tc,單位可以是MB/s。然後假設總的目標吞吐量是Tt,那麼分區數 = Tt / max(Tp, Tc)
Tp表示procer的吞吐量。測試procer通常是很容易的,因為它的邏輯非常簡單,就是直接發送消息到Kafka就好了。Tc表示consumer的吞吐量。測試Tc通常與應用的關系更大, 因為Tc的值取決於你拿到消息之後執行什麼操作,因此Tc的測試通常也要麻煩一些。
另外,Kafka並不能真正地做到線性擴展(其實任何系統都不能),所以你在規劃你的分區數的時候最好多規劃一下,這樣未來擴展時候也更加方便。
消息-分區的分配
默認情況下,Kafka根據傳遞消息的key來進行分區的分配,即hash(key) % numPartitions,如下圖所示:
def partition(key: Any, numPartitions: Int): Int = {
Utils.abs(key.hashCode) % numPartitions
}
這就保證了相同key的消息一定會被路由到相同的分區。如果你沒有指定key,那麼Kafka是如何確定這條消息去往哪個分區的呢?
復制代碼
if(key == null) { // 如果沒有指定key
val id = sendPartitionPerTopicCache.get(topic) // 先看看Kafka有沒有緩存的現成的分區Id
id match {
case Some(partitionId) =>
partitionId // 如果有的話直接使用這個分區Id就好了
case None => // 如果沒有的話,
val availablePartitions = topicPartitionList.filter(_.leaderBrokerIdOpt.isDefined) //找出所有可用分區的leader所在的broker
if (availablePartitions.isEmpty)
throw new LeaderNotAvailableException("No leader for any partition in topic " + topic)
val index = Utils.abs(Random.nextInt) % availablePartitions.size // 從中隨機挑一個
val partitionId = availablePartitions(index).partitionId
sendPartitionPerTopicCache.put(topic, partitionId) // 更新緩存以備下一次直接使用
partitionId
}
}
復制代碼
可以看出,Kafka幾乎就是隨機找一個分區發送無key的消息,然後把這個分區號加入到緩存中以備後面直接使用——當然了,Kafka本身也會清空該緩存(默認每10分鍾或每次請求topic元數據時)
如何設定consumer線程數
我個人的觀點,如果你的分區數是N,那麼最好線程數也保持為N,這樣通常能夠達到最大的吞吐量。超過N的配置只是浪費系統資源,因為多出的線程不會被分配到任何分區。讓我們來看看具體Kafka是如何分配的。
topic下的一個分區只能被同一個consumer group下的一個consumer線程來消費,但反之並不成立,即一個consumer線程可以消費多個分區的數據,比如Kafka提供的ConsoleConsumer,默認就只是一個線程來消費所有分區的數據。——其實ConsoleConsumer可以使用通配符的功能實現同時消費多個topic數據,但這和本文無關。
再討論分配策略之前,先說說KafkaStream——它是consumer的關鍵類,提供了遍歷方法用於consumer程序調用實現數據的消費。其底層維護了一個阻塞隊列,所以在沒有新消息到來時,consumer是處於阻塞狀態的,表現出來的狀態就是consumer程序一直在等待新消息的到來。——你當然可以配置成帶超時的consumer,具體參看參數consumer.timeout.ms的用法。
下面說說Kafka提供的兩種分配策略: range和roundrobin,由參數partition.assignment.strategy指定,默認是range策略。本文只討論range策略。所謂的range其實就是按照階段平均分配。舉個例子就明白了,假設你有10個分區,P0 ~ P9,consumer線程數是3, C0 ~ C2,那麼每個線程都分配哪些分區呢?
C0 消費分區 0, 1, 2, 3
C1 消費分區 4, 5, 6
C2 消費分區 7, 8, 9
具體演算法就是:
復制代碼
val nPartsPerConsumer = curPartitions.size / curConsumers.size // 每個consumer至少保證消費的分區數
val nConsumersWithExtraPart = curPartitions.size % curConsumers.size // 還剩下多少個分區需要單獨分配給開頭的線程們
...
for (consumerThreadId <- consumerThreadIdSet) { // 對於每一個consumer線程
val myConsumerPosition = curConsumers.indexOf(consumerThreadId) //算出該線程在所有線程中的位置,介於[0, n-1]
assert(myConsumerPosition >= 0)
// startPart 就是這個線程要消費的起始分區數
val startPart = nPartsPerConsumer * myConsumerPosition + myConsumerPosition.min(nConsumersWithExtraPart)
// nParts 就是這個線程總共要消費多少個分區
val nParts = nPartsPerConsumer + (if (myConsumerPosition + 1 > nConsumersWithExtraPart) 0 else 1)
...
}
復制代碼
針對於這個例子,nPartsPerConsumer就是10/3=3,nConsumersWithExtraPart為10%3=1,說明每個線程至少保證3個分區,還剩下1個分區需要單獨分配給開頭的若干個線程。這就是為什麼C0消費4個分區,後面的2個線程每個消費3個分區,具體過程詳見下面的Debug截圖信息:
ctx.myTopicThreadIds
nPartsPerConsumer = 10 / 3 = 3
nConsumersWithExtraPart = 10 % 3 = 1
第一次:
myConsumerPosition = 1
startPart = 1 * 3 + min(1, 1) = 4 ---也就是從分區4開始讀
nParts = 3 + (if (1 + 1 > 1) 0 else 1) = 3 讀取3個分區, 即4,5,6
第二次:
myConsumerPosition = 0
startPart = 3 * 0 + min(1, 0) =0 --- 從分區0開始讀
nParts = 3 + (if (0 + 1 > 1) 0 else 1) = 4 讀取4個分區,即0,1,2,3
第三次:
myConsumerPosition = 2
startPart = 3 * 2 + min(2, 1) = 7 --- 從分區7開始讀
nParts = 3 + if (2 + 1 > 1) 0 else 1) = 3 讀取3個分區,即7, 8, 9
至此10個分區都已經分配完畢
說到這里,經常有個需求就是我想讓某個consumer線程消費指定的分區而不消費其他的分區。坦率來說,目前Kafka並沒有提供自定義分配策略。做到這點很難,但仔細想一想,也許我們期望Kafka做的事情太多了,畢竟它只是個消息引擎,在Kafka中加入消息消費的邏輯也許並不是Kafka該做的事情。
㈤ 一文解密Kafka,Kafka源碼設計與實現原理剖析,真正的通俗易懂
Apache Kafka (簡稱Kafka )最早是由Linkedln開源出來的分布式消息系統,現在是Apache旗下的一個子項目,並且已經成為開冊、領域應用最廣泛的消息系統之 Kafka社區也非常活躍,從 版本開始, Kafka 的標語已經從「一個高吞吐量、分布式的消息系統」改為「一個分布式的流平台」
關於Kafka,我打算從入門開始講起,一直到它的底層實現邏輯個原理以及源碼,建議大家花點耐心,從頭開始看,相信會對你有所收獲。
作為 個流式數據平台,最重要的是要具備下面 個特點
消息系統:
消息系統 也叫作消息隊列)主要有兩種消息模型:隊列和發布訂Kafka使用消費組( consumer group )統 上面兩種消息模型 Kafka使用隊列模型時,它可以將處理 作為平均分配給消費組中的消費者成員
下面我們會從 個角度分析Kafka 的幾個基本概念,並嘗試解決下面 個問題
消息由生產者發布到 fk 集群後,會被消費者消費 消息的消費模型有兩種:推送模型( pu和拉取模型( pull 基於推送模型的消息系統,由消息代理記錄消費者的消費狀態 消息代理在將消息推送到消費者後 標記這條消息為已消費
但這種方式無法很好地保證消息的處理語義 比如,消息代理把消息發送出去後,當消費進程掛掉或者由於網路原因沒有收到這條消息時,就有可能造成消息丟失(因為消息代理已經 這條消息標記為自己消費了,但實際上這條消息並沒有被實際處理) 如果要保證消息的處理語義,消息代理發送完消息後,要設置狀態為「已發送」,只有收到消費者的確認請求後才更新為「已消費」,這就需要在消息代理中記錄所有消息的消費狀態,這種做法也是不可取的
Kafka每個主題的多個分區日誌分布式地存儲在Kafka集群上,同時為了故障容錯,每個分區都會以副本的方式復制到多個消息代理節點上 其中一個節點會作為主副本( Leader ),其 節點作為備份副本( Follower ,也叫作從副本)
主副本會負責所有的客戶端讀寫操作,備份副本僅僅從主副本同步數據 當主副本 IH 現在故障時,備份副本中的 副本會被選擇為新的主副本 因為每個分區的副本中只有主副本接受讀寫,所以每個服務端都會作為某些分區的主副本,以及另外一些分區的備份副本這樣Kafka集群的所有服務端整體上對客戶端是負載均衡的
消息系統通常由生產者「pro ucer 消費者( co sumer )和消息代理( broke 大部分組成,生產者會將消息寫入消息代理,消費者會從消息代理中讀取消息 對於消息代理而言,生產者和消費者都屬於客戶端:生產者和消費者會發送客戶端請求給服務端,服務端的處理分別是存儲消息和獲取消息,最後服務端返回響應結果給客戶端
新的生產者應用程序使用 af aP oce 對象代表 個生產者客戶端進程 生產者要發送消息,並不是直接發送給 務端 ,而是先在客戶端 消息放入隊列 然後 一個 息發送線程從隊列中消息,以 鹽的方式發送消息給服務端 Kafka的記 集器( Reco dACCUl'lUlato )負責緩存生產者客戶端產生的消息,發送線程( Sende )負責讀取 集器的批 過網路發送給服務端為了保證客戶端 絡請求 快速 應, Kafka 用選擇器( Selecto 絡連接 讀寫 理,使網路連接( Netwo kCl i.ent )處理客戶端 絡請求
追加消息到記錄收集器時按照分區進行分組,並放到batches集合中,每個分區的隊列都保存了將發送到這個分區對應節點上的 記錄,客戶端的發送線程可 只使用 Sende 線程迭 batches的每個分區,獲取分區對應的主劇本節點,取出分區對應的 列中的批記錄就可以發送消息了
消息發送線程有兩種消息發送方式 按照分區直接發送 按照分區的目標節點發迭 假設有兩台伺服器, 題有 個分區,那麼每台伺服器就有 個分區 ,消息發送線程迭代batches的每個分 接往分區的主副本節點發送消息,總共會有 個請求 所示,我 先按照分區的主副本節點進行分組, 屬於同 個節點的所有分區放在一起,總共只有兩個請求做法可以大大減少網路的開銷
消息系統由生產者 存儲系統和消費者組成 章分析了生產者發送消息給服務端的過程,本章分析消費者從服務端存儲系統讀取生產者寫入消息的過程 首先我 來了解消費者的 些基礎知識
作為分布式的消息系統, Kafka支持多個生產者和多個消費者,生產者可以將消息發布到集群中不同節點的不同分區上;「肖費者也可以消費集群中多個節點的多個分區上的消息 寫消息時,多個生產者可以 到同 個分區 讀消息時,如果多個消費者同時讀取 個分區,為了保證將日誌文件的不同數據分配給不同的消費者,需要採用加鎖 同步等方式,在分區級別的日誌文件上做些控制
相反,如果約定「同 個分區只可被 個消費者處理」,就不需要加鎖同步了,從而可提升消費者的處理能力 而且這也並不違反消息的處理語義:原先需要多個消費者處理,現在交給一個消費者處理也是可以的 3- 給出了 種最簡單的消息系統部署模式,生產者的數據源多種多樣,它們都統寫人Kafka集群 處理消息時有多個消費者分擔任務 ,這些消費者的處理邏輯都相同, 每個消費者處理的分區都不會重復
因為分區要被重新分配,分區的所有者都會發生變 ,所以在還沒有重新分配分區之前 所有消費者都要停止已有的拉取錢程 同時,分區分配給消費者都會在ZK中記錄所有者信息,所以也要先刪ZK上的節點數據 只有和分區相關的 所有者 拉取線程都釋放了,才可以開始分配分區
如果說在重新分配分區前沒有釋放這些信息,再平衡後就可能造成同 個分區被多個消費者所有的情況 比如分區Pl 原先歸消費者 所有,如果沒有釋放拉取錢程和ZK節點,再平衡後分區Pl 被分配給消費者 了,這樣消費者 和消費者 就共享了分區Pl ,而這顯然不符合 fka 中關於「一個分區只能被分配給 個消費者」的限制條件 執行再平衡操作的步驟如下
如果是協調者節點發生故障,服務端會有自己的故障容錯機制,選出管理消費組所有消費者的新協調者節,點消費者客戶端沒有權利做這個工作,它能做的只是等待一段時間,查詢服務端是否已經選出了新的協調節點如果消費者查到現在已經有管理協調者的協調節點,就會連接這個新協調節,哉由於這個協調節點是服務端新選出來的,所以每個消費者都應該重新連接協調節點
消費者重新加入消費組,在分配到分區的前後,都會對消費者的拉取工作產生影響 消費者發送「加入組請求」之前要停止拉取消息,在收到「加入組響應」中的分區之後要重新開始拉取消息時,為了能夠讓客戶端應用程序感知消費者管理的分區發生變化,在加入組前後,客戶端還可以設置自定義的「消費者再平衡監聽器」,以便對分區的變化做出合適的處理