第一部分
第一章
1.講了一個現(xiàn)代應(yīng)用系統(tǒng)的基本架構(gòu)和對軟件來講至關(guān)重要的三個問題:可靠性,可擴(kuò)展性,可維護(hù)性。中位數(shù)的性能判定法。總之哦,好像和我這種搬磚的離的太遠(yuǎn)了。還有擴(kuò)展在水平(加機(jī)器)和垂直(升級機(jī)器)之間做取舍。
第二章
1.nosql的誕生
講了一下nosql的誕生和其優(yōu)點(diǎn):更好的可伸縮和更大的吞吐量,以及一些關(guān)系所不支持的特殊的查詢操作.
2.對象關(guān)系不匹配
即數(shù)據(jù)庫存儲的結(jié)構(gòu)(table)和應(yīng)用代碼中的對象不匹配需要一層轉(zhuǎn)換層(orm框架),存儲json(或者xml這種結(jié)構(gòu)化的格式)雖然可以在一定程度上減少這種不匹配,但是大大提高了局部修改的代價,且降低了條件查詢的能力(es的倒排索引是解決方案之一),因?yàn)橐粚Χ嗟臄?shù)據(jù)是一個樹狀結(jié)構(gòu)用json可以獲得比關(guān)系型存儲更好的表達(dá)性.但是這樣在一行中存儲冗余信息的方式又不符合關(guān)系性存儲的規(guī)范,所以還是要根據(jù)實(shí)際情況去取舍.雖然json可以很好的表達(dá)一對多的關(guān)系,但卻沒法表達(dá)多對多的關(guān)系,這是文檔結(jié)構(gòu)無法逃避的缺點(diǎn)
大部分情況下當(dāng)我們?nèi)ヒ闷渌鹴able的信息的時候我們都會存儲其id這樣相當(dāng)于存儲了對應(yīng)數(shù)據(jù)的引用,其內(nèi)容發(fā)生改變的時候其他的引用了該表的表無需進(jìn)行修改,但是有些時候也需要存儲非引用的冗余字段,因?yàn)檫@些數(shù)據(jù)可能會被delete,這時我們存儲的冗余字段就相當(dāng)于當(dāng)時快照了.但是就需要考慮這些的數(shù)據(jù)的一致性問題,即發(fā)生更新時需要,將所有的副本都更新.所以這類問題可以歸屬為副本問題.
網(wǎng)絡(luò)模型
暫時給我感覺就是圖數(shù)據(jù)庫,查詢數(shù)據(jù)需要有查詢的路徑,要不然就只能從多條路徑中自己去取舍.
文檔模型中的模式靈活性
這里說文檔數(shù)據(jù)庫是不會強(qiáng)制存儲的數(shù)據(jù)的但是可以通過模式的選擇決定要不要規(guī)定文檔的基本格式即schema(es需要建立索引已經(jīng)是顯式啦!),當(dāng)然現(xiàn)在關(guān)系性數(shù)據(jù)庫也支持文檔類型了比如pg.
第三章
講了lsm tree和b+,行存列存,列存優(yōu)化,OLTP主要是對數(shù)據(jù)的增刪改,OLAP是對數(shù)據(jù)的查詢。
第四章
講了一些編碼格式,明文格式(如json),以及降低可讀性減小數(shù)據(jù)大小的二進(jìn)制格式,還有rpc如何做向前向后兼容的(這類東西是第一次系統(tǒng)的看,過一段時間估計就忘了).
第二部分
第五章
這部講的是分布式下數(shù)據(jù)復(fù)制問題,如何保障一致性,和6.824搭配使用更佳.
第六章
講分區(qū),分庫分表,負(fù)載均衡,冷熱分離等等這些都是分區(qū)的手段.
第七章
事務(wù)的定義以及實(shí)現(xiàn)原理.
讀已提交.需要保存數(shù)據(jù)的至少兩個版本,之前已經(jīng)提交的版本(舊),和當(dāng)前正在提交中的版本(新).
update被翻譯為delete and insert
觀察一致性快照的可見性規(guī)則
1.當(dāng)前事務(wù)開始的時候,尚未提交或者中止的事務(wù)的寫入會被忽略
2.被中止事務(wù)所執(zhí)行的寫入會被忽略
3.具有較晚事務(wù)id的,即事務(wù)id大于當(dāng)前事務(wù)的id,這些事務(wù)的寫入會被忽略
4.所有寫入對應(yīng)用都是可見的
5.讀事務(wù)開始時,創(chuàng)建該對象的事務(wù)已經(jīng)提交。對象未被標(biāo)記為刪除,或如果被標(biāo)記為刪除,請求刪除的事務(wù)在讀事務(wù)開始時尚未提交。
第八章
分布式系統(tǒng)的麻煩
1.部分節(jié)點(diǎn)失效
2.異步,擁塞控制使得網(wǎng)絡(luò)不可靠
3.需要同步和物理石英石時鐘的變化使得時鐘不可靠
第九章
1.線性一直,保證全序
2.蘭伯特時間戳提供了因果全序,但無法保證操作全序
全序廣播的兩個關(guān)鍵點(diǎn)
可靠交付(reliable delivery)
沒有消息丟失:如果消息被傳遞到一個節(jié)點(diǎn),它將被傳遞到所有節(jié)點(diǎn)。
全序交付(totally ordered delivery)
消息以相同的順序傳遞給每個節(jié)點(diǎn)。
比如raft中的狀態(tài)機(jī)復(fù)制
全序廣播是異步的,所以不同節(jié)點(diǎn)可能進(jìn)度不一致.
而線性一致是及時的,即讀取一定能看到最新寫入的值.
可以通過將全序廣播當(dāng)作僅追加日志的方式來實(shí)現(xiàn)線性的cas操作.
此時寫入雖然是線性一致的,但讀取并不是,因?yàn)閷懭胧钱惒降?所以讀取還是可能讀到舊的版本,可以通過在日志中添加一條讀取消息來實(shí)現(xiàn)線性一致的讀取,這樣相當(dāng)于標(biāo)記了讀取的時間,當(dāng)所有寫入完成后到達(dá)讀取時間點(diǎn)再讀取,這樣就不會讀取到舊的版本了.更簡單的方法是,直接讀取同步更新的副本.
使用線性一致實(shí)現(xiàn)全序廣播:
首先使用線性一致的到一個自增的值,然后將值作為序列號附加到消息中,接收者按照序列號傳輸消息(就像raft需要term作為類似序列號的做法一樣).
分布式事務(wù)與共識
2pc兩階段提交:
coordinator(協(xié)調(diào)者,事務(wù)管理器).
prepare(準(zhǔn)備)
commit(提交)
1.每次啟動一個事務(wù)的時候,協(xié)調(diào)者生成全局唯一的id,標(biāo)識這次事務(wù).
2.每個參與該次事務(wù)的節(jié)點(diǎn)的單點(diǎn)事務(wù)都需要帶上這個全局事務(wù)id
3.prepare階段,任意一個節(jié)點(diǎn)超時或者失敗,則協(xié)調(diào)向所有參與本次事務(wù)的節(jié)點(diǎn)發(fā)送終止該事務(wù)id的請求.
4.參與者受到prepare請求時,需要確保在任意情況下都確??梢蕴峤皇聞?wù).這包括將所有事務(wù)數(shù)據(jù)寫入磁盤,以及檢查是否存在任何沖突等等,總之只要答應(yīng)了,就不能反悔,事務(wù)一定可以不出錯的提交.
5.協(xié)調(diào)者收集所有答復(fù),就會做出決定,提交還是終止,并將這個決定寫在磁盤的事務(wù)日志上,如果稍后協(xié)調(diào)者崩潰也可以同日志恢復(fù),這個被稱為commit point.
6.一旦決定落盤,該決定就會發(fā)送給所有的參與者,如果這個請求失敗或者超時,協(xié)調(diào)者必須無限重試,直到成功.如果參與者崩潰,則事務(wù)在參與者恢復(fù)后提交.
7.參與在prepare階段回復(fù)是,且協(xié)調(diào)者崩潰,參與者只能等待協(xié)調(diào)者恢復(fù),事務(wù)處于(存疑)in doubt狀態(tài).
8.存疑事務(wù)可能導(dǎo)致,事務(wù)獲取的鎖長時間無法釋放,在極端情況下只能依靠運(yùn)維去手動去釋放鎖.
XA事務(wù):跨異構(gòu)兩階段提交,一般情況下為一個庫,被加載到應(yīng)用程序的進(jìn)程中.heuristic decisions(啟發(fā)式?jīng)Q策)用于參與者,單方面處理一個存疑事務(wù).
容錯共識
共識的性質(zhì)
一致同意(Uniform agreement)
沒有兩個節(jié)點(diǎn)的決定不同。
完整性(Integrity)
沒有節(jié)點(diǎn)決定兩次。
有效性(Validity)
如果一個節(jié)點(diǎn)決定了值 v ,則 v 由某個節(jié)點(diǎn)所提議。
終止(Termination)
由所有未崩潰的節(jié)點(diǎn)來最終決定值。
第十章
mapreduce因?yàn)橐呀?jīng)寫過6.824的lab了,所以這里就不過多記錄了.但是這部分講的mapreduce對于容錯所做的設(shè)計,站在我的角度去看就是虛擬容器對資源的調(diào)度導(dǎo)致的,是屬于谷歌基于自己的實(shí)際情況設(shè)計的,大部分用戶的離線計算還是放在專有服務(wù)器上運(yùn)行的,其次map,reduce的編寫方式也確實(shí)不如現(xiàn)在批流計算引擎方便,被淘汰也屬于意料之內(nèi)(寫過一點(diǎn)點(diǎn)flink,有一點(diǎn)點(diǎn)感悟).
可以將消費(fèi)某些數(shù)據(jù)的任務(wù)和生產(chǎn)這些數(shù)據(jù)的任務(wù)放在同樣的服務(wù)器上,這樣就可以通過共享內(nèi)存來傳輸數(shù)據(jù),而不是通過網(wǎng)絡(luò).
算子的中間狀態(tài)寫入本地內(nèi)存或者磁盤,比寫入hdfs需要更少的io,在flink中這個點(diǎn)被稱為checkpoint.
第十一章
流處理與批處理最大的不同就是數(shù)據(jù)的有界和無界,批處理你總能獲取一批大小明確的數(shù)據(jù),但流處理你并不知道數(shù)據(jù)什么時候會來,來多少.流處理對比批處理的好處就是計算更及時,用戶體驗(yàn)更好.
流處理的編寫過程類似于消息隊列的消費(fèi),當(dāng)生產(chǎn)速度大于消費(fèi)速度的時候,我們就需要和外的存儲系統(tǒng)來保存未消費(fèi)的數(shù)據(jù),而不是去壓榨消費(fèi)者使其崩潰.
我們可以使用數(shù)據(jù)庫存儲嗎?當(dāng)然可以,但是我們每次獲取數(shù)據(jù)都會依據(jù)上一次的消費(fèi)時間作為起點(diǎn)向后獲取數(shù)據(jù),我們并不知道數(shù)據(jù)庫中是否已經(jīng)存儲了最新的數(shù)據(jù),每次請求也許會一無所獲,在網(wǎng)絡(luò)io上是一種很大的浪費(fèi),所以消息系統(tǒng)是一種更好的選擇,不僅從主動拉取變成了被動接受,而且消息系統(tǒng)通常也會有持久化,一次消費(fèi)的語義保證,讓流處理的編寫變的更專注于數(shù)據(jù)的處理,當(dāng)然也有不得不使用數(shù)據(jù)庫的場景,面對一些業(yè)務(wù)的場景,這種不爽有時候也不得不接受.
基于binlog的同步系統(tǒng)是美好的,因?yàn)閎inlog是全序的,在異構(gòu)之下也可以良好的工作.(之前就寫過一點(diǎn)基于阿里云的dts同數(shù)據(jù)到es的事情,不過他們的sdk是真不好用哈哈,client就是基于kafka二次開發(fā)的).遺憾就是復(fù)制延遲問題.
要校正不正確的設(shè)備時鐘,一種方法是記錄三個時間戳
1.事件發(fā)生的時間,取決于設(shè)備時鐘
2.事件發(fā)送往服務(wù)器的時間,取決于設(shè)備時鐘
3.事件被服務(wù)器接收的時間,取決于服務(wù)器時鐘
使用3-2去估算1
流處理的三種連接
流流,流表,表表
第十二章
主要圍繞著數(shù)據(jù)變更流構(gòu)建系統(tǒng)的好處(這對于用過阿里云dts的我來說可太熟悉了).
消息錯誤會被丟棄重試,這就導(dǎo)致正好執(zhí)行一次的語義失效了,比如說郵件被發(fā)送兩次這類錯誤,處理的方法就是冪等,給消息事件添加唯一的表示
像是金融類操作重試意味這雙倍金額,我們?nèi)绾蝸砣シ謨纱尾僮魇仟?dú)立的還是重試的,就是為一次支付操作生成唯一標(biāo)識符,一般支付的做法就是,生成支付單來標(biāo)識這次支付的唯一性.就算支付請求因?yàn)榭蛻舳巳蹙W(wǎng)絡(luò)的原因被提交的兩次,相同的支付單號也會使得他們只被執(zhí)行一次.這其實(shí)也是一種冪等,只不過,被唯一標(biāo)識的不是一個實(shí)體,而是一個動作.
這是一種端到端的解決方案即:沖客戶端一路傳遞到數(shù)據(jù)庫的事務(wù)標(biāo)識.
最后就是作者對于數(shù)據(jù)的道德底線,以及作為工程師價值的個人看法,還挺酷的,至此本書的第一遍我看完了,以后找時間二刷.