外貿(mào)客戶管理軟件排名排名優(yōu)化方法
Kafka它本身其實不是一個金融級別數(shù)據(jù)可靠的分布式消息系統(tǒng)。
雖然說它存儲到某個topic里的數(shù)據(jù)會先拆分多個partition,這體現(xiàn)了分治的一個思想。每一個partition在最終存儲的時候會保存多個副本,不同的副本存儲在不同的節(jié)點。這樣的話任意一個節(jié)點掛掉,其實數(shù)據(jù)是不丟失的。
但實際上它是存在風險的,因為Kafka它利用了緩存。就是數(shù)據(jù)在真正落盤之前都要存在Block Case里進行緩存。以便增加磁盤的讀寫性能,緩存滿了或者是失效了,緩存里的數(shù)據(jù)才會往磁盤里面進行溢寫。
這種情況下就一定會帶來風險,一旦你的集群斷電了,緩存里的數(shù)據(jù)還沒有來得及往磁盤溢寫,那這個時候數(shù)據(jù)就丟失了。
當然在生產(chǎn)中可以有其他的選型,比如說RabbitMQ,它的性能大概是Kafka的一半甚至一半不到。它是數(shù)據(jù)直寫磁盤的,這樣的話它不存在數(shù)據(jù)安全性的問題。換來的代價是它的性能會下降,延遲會增加。
我們現(xiàn)在要做的是,在保證高性能的同時,還希望數(shù)據(jù)盡量不丟失。這能不能做到?當然能做到。
Kafka生產(chǎn)者產(chǎn)生數(shù)據(jù)進行消息發(fā)送,它會采用這種ack機制,去保證數(shù)據(jù)可靠性。Ack就是當生產(chǎn)者將數(shù)據(jù)寫入到Kafka之后,Kafka會返回一個標志,這個標志叫ack。
min.insync.replicas
它這種ack的機制其實有三種級別,一種是默認級別,即將min.insync.replicas參數(shù)設置為1的時候。生產(chǎn)者只要將數(shù)據(jù)發(fā)送到leader副本,kafka就會返回ack,leader中的數(shù)據(jù)先在緩存中,數(shù)據(jù)寫磁盤需要一段時間。這個過程中如果兩個從副本沒有同步數(shù)據(jù),直接斷電后就會丟數(shù)。
如果ack的級別配置成0,效率更高。不需要kafka返回任何ack的確認。這種的話性能更好,但是丟數(shù)的風險就更高。
當這種ack可以設為-1的時候,數(shù)據(jù)安全性是最高的。0安全級別最低,1安全級別中等。
-1這種情況是,當produce將數(shù)據(jù)發(fā)送到主副本以后,在ISR列表里面,也就是候選人列表中的從副本會立即從leader進行數(shù)據(jù)同步。完成數(shù)據(jù)同步以后,Kafka才會向生產(chǎn)者返回ack。生產(chǎn)者接收到ack后再繼續(xù)發(fā)送其他的消息。
雖然說性能會有下降,但是數(shù)據(jù)可靠性提高了。
因為返回ack的時候,其實數(shù)據(jù)已經(jīng)在多個節(jié)點里了。任意一個節(jié)點掛掉,其實對系統(tǒng)是沒有影響的。
這里有一個細節(jié),如果目前ISR里面的一個從副本,當它長時間與leader數(shù)據(jù)不同步,也就是落后了很多消息。超過一定時間之后它就會被移出ISR,ISR現(xiàn)在只剩一個從副本了。這個時候可靠性就會降級。
還有一種極端情況就是,兩個follower都被移出ISR,ISR現(xiàn)在為空。這個時候ack這種-1級別,也被稱為all級別,就降級成了1這個級別。
這種時候我們該怎么去限制?我們可以調(diào)整ISR最小副本數(shù)min.insync.replicas。
min.insync.replicas
這個參數(shù)它一定是配合ack等于all (-1)來使用。比如說min.insync.replicas限制為1,就是說ISR里面必須有1個副本,這樣的話它才能保證數(shù)據(jù)的一個可靠性。如果小于1的話就是ISR為空,在生產(chǎn)者往Kafka里面寫數(shù)據(jù)的時候就會報錯。報NotEnoughReplicaseException異常。沒有足夠的副本,保證不了數(shù)據(jù)安全。
所以一般來說它倆是配合來使用的,避免ack=all降級為ack=1,能夠提升我們數(shù)據(jù)安全級別。
ISR假設為空,或者小于最小副本數(shù),生產(chǎn)者往Kafka寫數(shù)據(jù)的時候一直會報錯,不能說它一報錯Kafka生產(chǎn)者就直接終止,我們肯定要設置一個重試次數(shù),來提升程序的健壯性。
retries
即使我們ack開到all(-1),它數(shù)據(jù)還是先會寫緩存,從副本同步的數(shù)據(jù)也在緩存里。當Kafka向生產(chǎn)者返回ack后,假設集群掛掉了。leader掛了,數(shù)據(jù)丟不丟失?不丟失,因為另外兩個從副本也有數(shù)據(jù)。那現(xiàn)在整個集群同時宕機了,緩存中的數(shù)據(jù)肯定就都給清理掉了。就一定會出現(xiàn)數(shù)據(jù)丟失的情況。
所以我們也印證了前面說的,為什么Kafka它不是一個金融級別可用的,或者金融級別數(shù)據(jù)安全的消息系統(tǒng)。原因就在這里。
當然每個產(chǎn)品有它自己的使用場景,Kafka本身就是用來抗壓的,它的性能越高越好,數(shù)據(jù)可靠性的要求要低一些。
這個時候有的同學就很矛盾了,我既想用Kafka的這種高性能高吞吐,但是我又不希望它丟數(shù),我們換一種思路該怎么辦?
先依賴Kafka,讓它完成抗壓的作用,數(shù)據(jù)可靠性既然不能依賴Kafka來完成,可以依賴誰來完成?依賴生產(chǎn)者。
生產(chǎn)者在將數(shù)據(jù),向Kafka里寫入的時候,能不能順手將這個數(shù)據(jù)寫到數(shù)據(jù)庫里呢?比如Mysql。寫入完成后再把數(shù)據(jù)推到Kafka中。
當然不寫數(shù)據(jù)庫也可以,可以先本地做備份,備份完以后再往Kafka里推送。一旦Kafka發(fā)生丟數(shù),沒關系,生產(chǎn)者可以拿到備份的數(shù)據(jù)進行補數(shù)操作。
如果補數(shù)的時候數(shù)據(jù)重復了,這個時候靈活一點,消費者這里是不是可以去重?就可以解決數(shù)據(jù)重復問題。
依賴kafka的高性能同時,盡量減少對kafka數(shù)據(jù)可靠性的依賴,并協(xié)調(diào)生產(chǎn)者與消費者去保障數(shù)據(jù)問題,這種解決方案能夠滿足生產(chǎn)上多數(shù)需求。
那Kafka的數(shù)據(jù)可靠性,就聊到這里,謝謝大家。