架構(gòu)師是互聯(lián)網(wǎng)行業(yè)高薪又緊俏的資源,。成為架構(gòu)師最基本的是設(shè)計(jì)能力。設(shè)計(jì)與設(shè)計(jì)的區(qū)別主要體現(xiàn)在兩方面: 1,,深度:要解決哪些問(wèn)題,?這個(gè)問(wèn)題背后的根本問(wèn)題是什么?還有什么問(wèn)題沒(méi)有發(fā)現(xiàn),?對(duì)應(yīng)的能力是發(fā)現(xiàn)和解決問(wèn)題的能力,。 2,體系:要解決的問(wèn)題的屬于哪一類的問(wèn)題,?這類問(wèn)題能否進(jìn)一步抽象,,讓系統(tǒng)解決更大的問(wèn)題?對(duì)應(yīng)的抽象歸納和體系化思維的能力,。 而做架構(gòu)的基本功就是研究成熟成功的系統(tǒng),,并總結(jié)歸納為一種設(shè)計(jì)方法添加到自己的設(shè)計(jì)庫(kù)中。今天我們來(lái)看看文件存儲(chǔ)機(jī)制的通用實(shí)現(xiàn)及原理-談Kafka,、Redis,、基于Lucene的搜索引擎等中間件和數(shù)據(jù)庫(kù)的文件存儲(chǔ)機(jī)制。如果你有九年義務(wù)教育以上學(xué)歷,,并且覺(jué)得看不懂這篇文章,,請(qǐng)給我留言~~ 順便插一句,不知道大家有沒(méi)有奇怪靜兒最近都沒(méi)有寫高可用方面的文章,。事情是這樣的,對(duì)于高可用的很多設(shè)計(jì),、架構(gòu),,靜兒都在進(jìn)行專利申請(qǐng)中,為了避免對(duì)公司造成影響和損失,,暫時(shí)處于多想不說(shuō)的階段,。 一個(gè)商業(yè)化中間件的性能好壞,其文件存儲(chǔ)機(jī)制設(shè)計(jì)是衡量一個(gè)消息隊(duì)列服務(wù)技術(shù)水平和最關(guān)鍵指標(biāo)之一。下面先介紹一下各個(gè)中間件的存儲(chǔ)機(jī)制,??床欢芍苯犹阶詈蟆?/p> 1Kafka Kafka是最初由Linkedin公司開發(fā),,是一個(gè)分布式,、分區(qū)的、多副本的,、多訂閱者,,基于zookeeper協(xié)議的分布式日志系統(tǒng)(也可以當(dāng)做MQ系統(tǒng)),常見(jiàn)可以用于web/nginx日志,、訪問(wèn)日志,,消息服務(wù)等等,Linkedin于2010年貢獻(xiàn)給了Apache基金會(huì)并成為頂級(jí)開源項(xiàng)目,。 設(shè)計(jì)特點(diǎn)
一張圖解釋一下剛才說(shuō)的特點(diǎn): 從上面的圖中可以看到,,生產(chǎn)者和消費(fèi)者并沒(méi)有直接的交互。這就達(dá)到了生產(chǎn)者消費(fèi)者模式的第一個(gè)好處:解耦,。作為消費(fèi)者,,可以自定義消費(fèi)線程數(shù)和消費(fèi)者數(shù)量。這就達(dá)到了生產(chǎn)者消費(fèi)者模式的第二個(gè)好處:限流,。這也是大家使用MQ一般想要達(dá)到的目的,。 2Redis 談redis首先要糾正一個(gè)誤區(qū):緩存比mysql快。為了說(shuō)明這個(gè)問(wèn)題,,下面是靜兒自己動(dòng)手得到的數(shù)據(jù),。 結(jié)論:使用了緩存后響應(yīng)時(shí)間不穩(wěn)定 結(jié)論:mysql的響應(yīng)時(shí)間非常穩(wěn)定 從cat監(jiān)控中可以看到緩存的get時(shí)間確實(shí)較長(zhǎng)。 順便跑題一下,,靜兒測(cè)試中還發(fā)現(xiàn)在jvm正常執(zhí)行業(yè)務(wù)邏輯,,不太復(fù)雜無(wú)外部調(diào)用,一般是1到2毫秒,。但是如果拋出了異常,,這段代碼執(zhí)行時(shí)間要變成100ms+,。所以一般代碼中禁止用拋出非必要異常來(lái)代替正常邏輯。 之所以給大家打這個(gè)預(yù)防針,,是因?yàn)橄旅嬉o出Redis的描述了,。 Redis本質(zhì)上是一個(gè)key-value類型的內(nèi)存數(shù)據(jù)庫(kù),整個(gè)數(shù)據(jù)庫(kù)加載在內(nèi)存當(dāng)中進(jìn)行操作,,定期通過(guò)異步操作把數(shù)據(jù)庫(kù)數(shù)據(jù)flush到硬盤上進(jìn)行保存,。因?yàn)槭羌儍?nèi)存操作,Redis的性能非常出色,,每秒可以處理超過(guò)10萬(wàn)次讀寫操作,,是已經(jīng)性能最快的key-value DB。 Redis存儲(chǔ)機(jī)制分成兩種Snapshot和AOF,。無(wú)論是哪種機(jī)制,,Redis都是將數(shù)據(jù)存儲(chǔ)在內(nèi)存中。 AOF工作原理:是將數(shù)據(jù)先存在內(nèi)存,,但是在存儲(chǔ)的時(shí)候會(huì)使用fsync(無(wú)阻塞進(jìn)程的)來(lái)完成對(duì)本次寫操作的日志記錄,。AOF最關(guān)鍵的配置就是關(guān)于調(diào)用fsync追加日志文件的頻率,有兩種預(yù)設(shè)頻率,。always:每次記錄進(jìn)來(lái)都添加,。everysecond每秒添加一次。 存儲(chǔ)模式性能和安全比較: 1.性能 snapshot性能是要明顯高于AOP方式的,,原因有兩點(diǎn): 1>采用二進(jìn)制方式存儲(chǔ),,數(shù)據(jù)文件小,加載快速,。 2>存儲(chǔ)的時(shí)候是按照配置中的save策略來(lái)存儲(chǔ),,每次都是聚合很多數(shù)據(jù)批量存儲(chǔ),寫入的效率高,。AOF一般都是工作在實(shí)時(shí)或準(zhǔn)實(shí)時(shí)模式下,。相對(duì)存儲(chǔ)頻率高,效率低,。 2.數(shù)據(jù)安全 AOF數(shù)據(jù)安全性高于Snapshot,,原因: snapshot存儲(chǔ)是基于累積批量的思想,累積的數(shù)據(jù)越多寫入效率越高,,但是如果長(zhǎng)時(shí)間數(shù)據(jù)不寫入RDB(redis的數(shù)據(jù)庫(kù)),,redis遇到了崩潰,沒(méi)寫入的數(shù)據(jù)就無(wú)法恢復(fù),。 Redis中有rewrite功能,,AOF的存儲(chǔ)是按照記錄日志的方式去工作的,成千上萬(wàn)的數(shù)據(jù)插入必然導(dǎo)致日志文件的擴(kuò)大,,Redis這個(gè)時(shí)候會(huì)根據(jù)配置合理觸發(fā)rewrite操作,。這個(gè)操作是將最終保留值記錄到日志文件中,從而縮小日志文件的大小,。這個(gè)類似于lucene的optimize操作,。 3Mysql/MariaDB Mysql與目前流行的nosql數(shù)據(jù)庫(kù)最大的不同是規(guī)定了嚴(yán)格的數(shù)據(jù)類型。數(shù)據(jù)類型因?yàn)樵趧?chuàng)建表時(shí)在內(nèi)存中嚴(yán)格劃定了地址空間,,所以能限定字段的數(shù)據(jù)存儲(chǔ)長(zhǎng)度,。 數(shù)據(jù)類型限定范圍的方式有兩種:1是嚴(yán)格限定空間,劃分了多少空間就只能存儲(chǔ)多少數(shù)據(jù),,超出的數(shù)據(jù)將被切斷,;2是使用額外的字節(jié)的bit位來(lái)標(biāo)記某個(gè)數(shù)據(jù),存儲(chǔ)了就進(jìn)行標(biāo)記,,不存儲(chǔ)就不標(biāo)記,。下面介紹3種類型的存儲(chǔ)方式。 1.整形的存儲(chǔ) 它嚴(yán)格限定空間,,每個(gè)已劃分的字節(jié)上的bit位上的0和1直接可以計(jì)算出數(shù)值,,所以它的范圍是根據(jù)bit位的數(shù)量值來(lái)計(jì)算的。一個(gè)字節(jié)有8個(gè)bit位,,一個(gè)bit位可以構(gòu)成2的8次方=256個(gè)數(shù)值,。同理2字節(jié)共2的16次方=65526個(gè)數(shù)值。也就是說(shuō),,在0-255之間的數(shù)字都只占用1個(gè)字節(jié),,256-65535之間的數(shù)字占用2個(gè)字節(jié)。 2.char的存儲(chǔ) char類型是常被成為定長(zhǎng)字符串類型,,它嚴(yán)格限定空間長(zhǎng)度,,但它限定的是字符數(shù)不是字節(jié)數(shù)。它有“短了就使用空格補(bǔ)足”的能力,。 3.varchar常被稱為“變長(zhǎng)字符串類型”,。它存儲(chǔ)數(shù)據(jù)時(shí)使用額外的字節(jié)的bit位來(lái)標(biāo)記某個(gè)字節(jié)是否存儲(chǔ)了數(shù)據(jù)。每存儲(chǔ)1個(gè)字節(jié)占用一個(gè)bit位進(jìn)行標(biāo)記,。一個(gè)額外的字節(jié)可以標(biāo)記256個(gè)字節(jié),,2個(gè)額外的字節(jié)可以標(biāo)記65536個(gè)字節(jié)。MySQL/mariadb限制了最大能存儲(chǔ)65536個(gè)字節(jié),。這表示,,如果是單字節(jié)的字符,它最多能存儲(chǔ)65536個(gè)字符,,如果是多字節(jié)字符,,如UTF8的每個(gè)字節(jié)占用3個(gè)字節(jié),它最多能存儲(chǔ)65536/3=21845個(gè)字符,。 4基于Lucene的搜索引擎 提到基于Lucene的搜索引擎,,大家可能更熟悉ElasticSearch(ES),。靜兒有段時(shí)間專門負(fù)責(zé)公司的搜索,沒(méi)有現(xiàn)在這么忙,,本應(yīng)該是非常難得和寶貴的機(jī)會(huì),。有大把的時(shí)間研究源碼,可惜當(dāng)時(shí)整個(gè)心都不在工作上,。當(dāng)時(shí)用的還是solr4.X.X(solr是基于Lucene的搜索引擎系統(tǒng),,lucene和solr版本同步更新,目前最新是7.6.0),,當(dāng)時(shí)solr每月發(fā)布一個(gè)新版本,。版本有很多bug,我當(dāng)時(shí)是在源碼上做了很多修復(fù)補(bǔ)丁的,。但是當(dāng)時(shí)各種意識(shí)都很薄弱,。如果當(dāng)初給apache提patch,有些應(yīng)該是能通過(guò)的,。這就能形成了一個(gè)良好的反饋循環(huán),,可能現(xiàn)在的狀況截然不同。 想起dubbo有段時(shí)間已經(jīng)不更新版本,,后來(lái)捐給了apache,,給這個(gè)項(xiàng)目又重新注入了生機(jī)。其中的一個(gè)教訓(xùn)就是大家一定要有很強(qiáng)的開源意識(shí),。這種意識(shí)還包括在自己做功能方案和開發(fā)實(shí)現(xiàn)的時(shí)候要有業(yè)界調(diào)研和對(duì)標(biāo)的意識(shí),。 靜兒的夢(mèng)想是實(shí)現(xiàn)自己的搜索引擎中間件,所以目前從事的是和這個(gè)原理有很深淵源的工作:容器調(diào)度,。什么,?看不出來(lái)聯(lián)系?那這個(gè)以后再慢慢聊,。 Lucene的數(shù)據(jù)都存在一個(gè)目錄下,,一個(gè)目錄構(gòu)成了一個(gè)索引。Lucene經(jīng)多年演進(jìn)優(yōu)化,,現(xiàn)在的一個(gè)索引文件可以分為4個(gè)部分:詞典,、倒排表、正向文件,、列式存儲(chǔ),。一張表解釋lucene的存儲(chǔ)原理: 1.高頻讀取操作放于內(nèi)存。 2.文件分段減少磁盤IO操作,。 3.磁盤存儲(chǔ)防止數(shù)據(jù)丟失,。 4.更好的結(jié)構(gòu)化可以提升存儲(chǔ)和讀取效率。 以上です。不解釋,。 之前和同事聊天,,同事說(shuō)他們架構(gòu)師基于原來(lái)的版本設(shè)計(jì)了一個(gè)非常完美的2.0方案。但是這個(gè)方案并不解決現(xiàn)有的任何問(wèn)題,。這也是靜兒想做架構(gòu)并且可以很輕松的找到一個(gè)架構(gòu)師職位,,但一直都是在項(xiàng)目組內(nèi)自己動(dòng)手寫代碼的原因:一個(gè)旁觀者想了解內(nèi)部的痛點(diǎn)很困難。 前段時(shí)間大家紛紛剖析拼多多優(yōu)惠券事件背后的技術(shù)問(wèn)題,。不可否認(rèn),技術(shù)是有點(diǎn)菜,。但是拼多多目前整體看是成功的,。成功在哪里呢?它成功的解決了商家(其他平臺(tái)門檻高,,入住不了)和消費(fèi)者(以更低的價(jià)格買到商品)的痛點(diǎn),。所以這點(diǎn)狀況并未傷及元?dú)狻?br> 在做設(shè)計(jì)的時(shí)候,我會(huì)首先問(wèn)自己一個(gè)問(wèn)題:現(xiàn)在哪里最痛,?架構(gòu)講究深度和體系,。深度解決的是痛點(diǎn)根本性的問(wèn)題。體系解決的是未來(lái)的痛點(diǎn)問(wèn)題,。不以解決問(wèn)題為目的設(shè)計(jì)的系統(tǒng)都是“成功之母”,。 |
|