後端好書閱讀與推薦(續五)

後端好書閱讀與推薦系列文章:
後端好書閱讀與推薦
後端好書閱讀與推薦(續)
後端好書閱讀與推薦(續二)
後端好書閱讀與推薦(續三)
後端好書閱讀與推薦(續四)
後端好書閱讀與推薦(續五)html

Redis設計與實現

Redis設計與實現 (豆瓣): https://book.douban.com/subje...前端

經過前面這本書咱們已經知道redis怎麼用比較好了,如今咱們來看看 Redis 的實現原理。這本書是做者本身看着源碼寫出來的,不得不佩服做者的智慧與毅力。這本書基於redis3.0,此刻redis最新版是4.0.9,咱們看書的時候能夠本身去看看源碼,看看redis有啥變化沒,源碼在此java

亮點:node

  • redis並無用C語言的字符串做爲其基準字符串表示,而是使用了SDS(簡單動態字符串)這一抽象類型,被用於鍵、字符串的表示,還有AOF中的緩衝區、客戶端輸出緩衝區等buffer的表示。 SDS的優點在於:記錄了長度信息不須要遍歷(空間換時間)、有長度因此會先檢查空間是否足夠而不會溢出、記錄了free(未使用空間)長度從而避免頻繁的內存從新分配(實現了空間預分配和惰性釋放)、二進制安全等等
  • redis還定義了鏈表Linkedlist(用於實現List結構、發佈訂閱、慢查詢、監視器等功能)、字典Dict(基於兩個hash表,一個平時用、一個rehash用,主要用於實現數據庫、Hash結構,須要注意漸進式rehash而不是java中Hashmap的一次性rehash,漸進式主要是避免鍵數量太大致使服務器暫時中止服務)、跳躍表SkipList(用於實現SortedSet結構、集羣節點)、整數集合(用於實現Set結構)、壓縮列表(用於實現ListHash結構,主要是面向小整數和短字符串,能夠節省空間)、對象redisObject(redis的五種數據結構就是五種對象,key value都是對象,是對前面全部數據結構的一種封裝,實現類型判斷、編碼、引用計數與對象共享和內存回收、過時刪除等功能)等數據結構來實現特定功能
  • redis服務器是一個redisServer數據結構,包含一個redisDb的鏈表,每個數據庫都是一個數據結構redisDb,中間有一個dict的數據結構保存了這個數據庫全部的鍵值對,叫作鍵空間(key space)。鍵空間會維護命中次數、最後使用時間、過時清除、鍵監視、鍵空間(關注鍵自己)/鍵事件(關注操做自己如del、sadd、set等)通知等事件。此外還有一個clients字段保存了全部客戶端
  • redisDb有一個dict類型的鏈表expire,保存了全部鍵的過時時間。過時鍵有三種刪除策略:定時刪除,設置timer,過時當即刪除,對內存友好,可是浪費CPU時間片,並且大量的timer也不現實;惰性刪除,聽任無論,獲取的時候檢查是否過時,過時再刪除,會浪費必定的內存,可是節省CPU時間;按期刪除,每隔一段時間就檢查過時鍵並刪除,須要好好設計執行時長與頻率。redis實際使用的是後二者
  • 持久化分爲AOFRDB。RDB能夠手動執行也可按期執行(BGSAVE)用內存數據生成壓縮過的二進制RDB文件,SAVE命令會阻塞服務器,而BGSAVE會fork一個子進程來建立RDB文件,因此期間新的數據變化是不能提現到RDB文件中的,此外,RDB文件的載入是服務器啓動自動完成的;AOF不直接記錄數據,而是記錄每個redis命令,分爲append、文件寫入(可能在系統緩衝中)、文件同步sync(強制刷到磁盤)三個步驟,文件同步有三種選項always(寫入文件就刷盤)、everysec(默認)、no(由操做系統決定什麼時候刷盤)
  • redis是一個事件驅動的程序,這種程序通常會有一個相似於while(true)的無限循環,叫作事件循環,每一個循環裏服務器要處理兩種事件:文件事件,完成網絡通訊(基於Reactor模式);時間事件,完成定時、週期操做之類。
  • Sentinel(哨兵)是redis的高可用解決方案,由>=1個Sentinel實例監視任意多的redis主服務器以及所屬的從服務器(從服務器複製主服務器的數據),完成主備切換等功能。實現原理是Sentinel每隔10秒就向全部主服務器發送info命令,獲取各個主服務器及其對應的從服務器的信息,而後也會以相同形式給從服務器發送info命令。另外會以兩秒一次的頻率向全部主從服務器發送一個publish的命令,而後會subscribe這個頻道,這樣就能得到每一個服務器的相關信息了。Sentinel之間只有命令鏈接,沒有頻道鏈接。
  • 在線檢測經過每秒的ping來實現,當超過一個Sentinel的時限down-after-milliseconds還沒得到一個服務器的回覆這個Sentinel就認爲此服務器主觀下線,而後會詢問其餘Sentinel,若是超過quorumSentinel都認爲此服務器主觀下線那麼這些Sentinel就認爲這個服務器就客觀下線了。當一個主服務器下線時,Sentinel們會選舉一個領頭SentinelRaft leader選舉)來對這個服務器羣進行主備切換,具體算法就不說了
  • redis集羣經過槽指派實現,全部數據分配到16284個槽,全部槽都有節點處理時集羣才能對外服務,每一個節點能夠處理多個槽(一個節點能夠是主從服務器羣,提升該節點可用性),當一個節點收到命令發現該槽不在本節點時會向客戶端返回重定向指令,讓其請求對應的節點。從新分槽能夠在線分,由redis-trib實現。
  • redis 支持慢查詢,超過showlog-log-slower-than選項執行時間的命令會被記錄到慢查詢日誌,日誌採用保存最近的,數量由slowlog-max-len決定。

本書配合着官方文檔來學習是最佳的,文檔在此中文文檔mysql

MySQL技術內幕

MySQL技術內幕 (豆瓣): https://book.douban.com/subje...linux

經過前面這本書咱們已經知道 mysql 怎麼用比較好了,如今咱們來看看 mysql 的實現原理。nginx

亮點:git

  • mysql採用單進程多線程模式。邏輯上,採用了分層可插拔架構,上層是鏈接池管理模塊,中層是語句解析、緩存、優化模塊,下層是可插拔的存儲引擎如myisam、Innodb(存儲引擎基於表而不是數據庫),下層依賴於操做系統層面的文件系統
  • InnoDB支持事務、行鎖、外鍵,主要面向在線事務處理應用(OLTP),經過MVVC提升併發性,默承認重複讀級別使用 next-key locking避免幻讀,此外還提供插入緩衝、二次寫、自適應hash索引、預讀等高性能與高可用功能;MyISAM不支持事務與行鎖,可是支持全文索引,主要面向OLAP應用;NDB是一個集羣引擎,數據所有在內存因此速度很快,可是鏈接操做不是在引擎層面解決的,效率較低;Memory也是內存存儲的引擎,適合臨時表存儲中間結果使用,默認使用hash索引,只支持表鎖;Archive只支持insert和select,支持壓縮適合存儲歸檔數據;還有太多不經常使用的,就不一一列舉了
  • innodb採用多線程模型,Master Thread負責將緩衝池中的數據異步刷新到磁盤,保證數據一致性,包括髒頁刷新,合併插入緩衝,undo頁回收;IO thread負責寫操做AIO的回調處理;Purge Thread 負責undo log的回收,減輕Master Thread的負擔;Page cleanner Thread 負責髒頁刷新,減輕master thread 負擔
  • mysql經過寫緩衝WAL將隨機寫改爲了順序寫提升了吞吐量,同時保證數據持久性,若是宕機就會用redoundo兩階段的日誌來將數據恢復到數據庫文件中。可是mysql基本頁面通常是16KB,而操做系統基本頁面通常是4KB,若是在寫入到數據庫文件時發生宕機,就可能引發partial write問題,亦即一個mysql頁面只寫入了一部分,這時就要依靠double write:同步緩衝區數據時,不是直接寫入文件,而是寫入內存中的double write buffer再調用fsync寫到共享表空間文件,而後立刻調用fsync同步至數據庫文件,這樣若是發生了partial write,就能夠去共享表空間找到該頁副本並複製到數據庫文件中,而後再進行redo,undo。固然,若是文件系統自己有防範機制就沒必要啓用double write
  • InnodB中頁是管理數據庫的最小磁盤單位,分爲多個部分,其中Fileheader、Pageheader、FileTrailer(檢查完整性)是固定的,記錄一些該頁的信息如checksum、頁所在B+樹層數。userrecords、freespace、pagedirectory(頁相對位置,B+索引只記錄一條數據所在頁,真正查找還需把這一頁加載如內存,靠二分搜索這一條記錄)是實際的行記錄存儲空間,所以大小是動態的。
  • Cardinality能幫助咱們決策是否須要創建索引,能夠經過show index來觀察,通常好比性別這個字段Cardinality就很低,由於可能一個類型female就佔據了全部行的一半,根本不必創建索引,而名字這個字段Cardinality就很高,適合創建索引(固然也得是應用經常按名字檢索,這樣纔有必要創建索引)
  • Innodb1.2.x 開始支持全文檢索,並支持myisam引擎全部功能。全文檢索通常經過倒排索引實現,亦即存儲每個詞彙及其對應文檔,這樣關鍵詞檢索時就能迅速返回相應文檔
  • 事務分爲幾種:扁平事務,全部操做位於同一層次,要麼都提交要麼都回滾(也就是說不支持部分回滾),是應用程序成爲原子操做的基本模塊;帶有保存點的扁平事務,在扁平事務基礎上支持部分回滾,用保存點(volatile,易失的)實現;鏈事務,事務的連接;嵌套事務,頂層事務管理多個子事務;分佈式事務,一般是在分佈式場景下運行的扁平事務
  • 事務的實現主要依靠:程序員

    • redo實現持久性,亦即commit操做必須將專門的redo日誌文件fsync刷新到磁盤才能返回成功,合併多條語句插入優於一句一句插入也是由於減小了日誌刷盤頻率,因爲redolog塊與磁盤扇區塊大小一致,因此無需doublewrite
    • undo實現回滾操做和MVCC,是存在於數據庫內部共享表空間的一個特殊段(undo段)中的邏輯日誌,記錄了事務執行的反效果便於回滾,MVCC的實現是經過若某行記錄已被其餘事物佔用,當前事務能夠經過undo日誌獲得改行以前版本的信息,需注意undolog也會產生redolog,亦即undolog也須要持久性維護;
    • purge最終完成deleteupdate操做,由於Innodb支持MVCC,因此記錄不能在提交時當即處理,purge操做判斷合什麼時候真正清理數據並回收undo page,具體來講,若是一行數據不被真正引用那就可清理deleteupdate數據了;
    • group commit將多個事務的數據一次性調用fsync刷新到磁盤減小刷盤次數;
    • 須要注意的是binlog,用來實現Point-In-Time的恢復以及主從複製的實現,很是相似於redolog,可是二者本質有很大不一樣:redolog產生於下層只針對Innodb引擎產生,是物理格式日誌,記錄針對每一頁的修改,事務過程當中不斷被寫入;binlog產生於中層,針對任何引擎都會產生,是邏輯日誌,記錄針對每條SQL語句,事務提交後一次寫入
  • Mysql經過XA事務來保證分佈式的一致性,同時內部也有XA的使用,如如今數據庫爲了複製通常都是打開binlog的,事務提交時既要寫binlog也要寫redolog,這就會涉及原子性問題,亦即兩個日誌必須同時寫入,經過先作prepare操做,將事務的xid寫入,而後寫入binlog,而後提交存儲引擎並寫入redolog

深刻Linux內核架構

深刻Linux內核架構 (豆瓣): https://book.douban.com/subje...github

這是一本能把linux內核全貌展示給咱們的大部頭,涵蓋了包括進程管理,內存管理、鎖與通訊、設備驅動、文件系統等等。要採起觀其大略,用時細讀的策略,去宏觀的把握linux的設計哲學。

亮點:

  • 操做系統架構主要涉及兩種類型:微內核,最基本的功能由中央內核實現,其餘功能委託給一些進程實現,經過通訊接口與中心內核通訊,這種模型研究活躍可是實用性進展甚微;宏(單)內核,內核的所有代碼打包到一個文件中,內核中每一個函數均可以訪問其餘部分,目前性能強於微內核,linux也是使用這種模式,可是linux模塊化作得很好(能夠動態添加減小功能,內核文件也不會膨脹),也消除了單內核的一個重要弱點
  • linux虛擬地址空間是每一個進程管理自身資源與其餘進程隔離的工具,與物理內存無直接關係(由CPU訪問總線數決定),分爲內核空間(task-size~最高位)和用戶空間(0~task-size),這樣就爲全部進程提供了一個統一的系統視圖,無需計較其餘進程;Intel處理器有4中特權級別,可是linux只使用兩種不一樣的狀態:核心態和用戶態,用戶態進程禁止直接訪問內核空間(這是內核的專用領域)的數據和執行其代碼,用戶態進程只能藉助於系統調用或者中斷來陷入內核態,由內核代爲執行操做。物理內存基本單位是頁框頁幀),虛擬內存基本單位是,二者大小同樣,對應關係由頁表(linux採用4級頁表)決定
  • 建立進程有兩種方式,fork(父子進程只有PID不一樣,使用COW使得fork更高效,亦即子進程只複製頁表,只有父子某一進程要向內存寫入數據時才真正複製物理內存,若只讀則能夠共享而沒必要複製,這樣就延遲甚至消除了了大量的複製,節約了內存和CPU時間)和exec(將一個新程序加載到當前內存中執行,舊的程序內存頁將刷出)。linux使用clone建立線程(或者說輕量級進程),相似於fork,可是能精確檢查哪些資源與父進程共享哪些爲線程獨立建立
  • Linux的進程調度分爲兩大部分:調度策略和上下文切換。非實時進程的調度策略通常考慮公平性,linux全部可運行進程都在一個紅黑樹中排序,vruntime(一次調度間隔的虛擬運行時間實際運行時間*(NICE_0_LOAD/權重nice值))最小的進程位於左下方會被調度器優先考慮,休眠進程被放入等待隊列中,喚醒後會從新被加入紅黑樹。實時進程是指該進程必須在指定的時間內完成好比飛機飛行控制指令,於是通常都有相對非實時進程較高的優先級,不一樣於非實時進程調度
  • 物理內存管理分爲兩個層次:夥伴系統負責物理頁幀的管理,圍繞多頁組成的連續內存塊的拆分與合併,新進的內核引入了反碎片技術(可移動頁與可移動內存區)防止物理內存碎片發生;slab負責處理小塊內存的分配,並提供了用戶層malloc函數族的內核等價物。
  • Linux使用了SystemV(Unix的一個分支)引入的機制來支持用戶進程間通訊(IPC)與同步。主要經過信號量、消息隊列、共享內存三種方式實現。此外,linux還有其餘IPC機制如信號(kill -s)、管道(以虛擬文件系統實現,適用於父子進程單向通訊)及命名管道(適用於無關係的進程間通訊)、socket(更通用,可多主機進程通訊)
  • Linux內核爲了統一文件訪問接口,在用戶進程(或者C標準庫)和文件系統(Ext2/3,XFS,Reiserfs)之間引入抽象層:虛擬文件系統(VFS)。文件系統通常分爲3種:基於磁盤的FS(如Ext2/3),無持久FS(如/proc),網絡文件系統。處理文件時,用戶程序關注一個整型的文件描述符fd(由內核分配,只在一個進程內有效,兩個進程即便有相同的fd也是指向不一樣的文件),而內核關注的是inode,包含了一個文件/目錄的元數據但不含文件名(文件名只是inode的別稱)。軟鏈接採用文件名指向的方式,獨立inode;硬連接採用引用計數,共享inode
  • 無持久FS有:proc標準掛載點是/proc,其信息不能從塊設備讀取,只有在讀取文件內容時才動態生成相關信息,也能夠在不從新編譯內核源碼的狀況下修改內核行爲,與內核通訊,包含網絡信息、內存管理、進程特徵數據、文件系統、設備驅動、電源、終端、系統控制參數;sysfs的標準掛載點是/sys,是一個向用戶空間導出內核對象的文件系統,提供了查看和修改內核數據結構的能力;用於專門目的的小文件系統
  • 應用程序看到的內核是一個執行多種系統功能(內存管理、系統資源請求、訪問外設、進程通訊、讀取文件等)的大的例程集合,標準庫是一箇中間層,用於在不一樣的體系結構和系統間,標準化並簡化內核例程的管理

同窗們,堪稱整個現代互聯網軟件基石的Linux內核源碼就在這裏,有沒有勇氣去瞅瞅?
還有這本書更精簡,推薦給不想看太多源碼和細節的同窗: Linux內核設計與實現(原書第3版)

Kafka權威指南

Kafka權威指南 (豆瓣): https://book.douban.com/subje...

Kafka是一個高吞吐量的分佈式(支持分區partition、多副本replica、使用zookeeper協調)消息系統,目前普遍用來進行實時大數據處理如:hadoop批處理、storm/Spark流式處理引擎,web日誌、消息隊列等等,因此做爲一個後端開發者,頗有必要了解一下。我想的是把kafka做爲消息隊列的表明進行學習,未來若是要用ActiveMQ、RabbitMQ、ZeroMQ、RocketMQ等或者要本身要開發一個MQ均可以觸類旁通或者進行借鑑。

亮點:

  • Kafka是一個流平臺,容許發佈和訂閱數據流,能夠看作傳統的MQ,可是有不少不一樣點:支持多生產者,多消費者,另外多個消費者還能夠組成羣組,共享一個消息流而且特定消息整個羣組只消費一次;以集羣方式運行,可伸縮,還有MirrorMaker支持不統集羣之間的複製;數據能夠持久化,相似於數據庫,保證消息必定送達;流式處理使得你能夠用不多的代碼就能動態的處理派生流和數據集。也能夠看作實時版的Hadoop(大數據中,Hadoop主要應用於批處理與數據分析,Kafka因爲低延遲更適合業務應用,可以在業務事件發生時及時做出響應,爲業務運營提供支撐,好比商品瀏覽數據轉換爲商品推薦)。也能夠看作ETL,可是並不是簡單移動數據而是面向實時數據流。這三個方面是Kafka的主要特性
  • 生產者產生一個ProducerRecord對象,包含Topicvalue,還可能有key或者partition,對象序列化後發送到分區器上,若是有partition則不操做,若無則根據key來指定partition(partition的設計目的是取消消息大小限制和提升並行度)。選好partition後發往對應的topic和partition的記錄批次,這一批記錄等待一次性的發往對應的broker(因此批的大小影響延遲和吞吐量),整個過程有失敗自動重試功能,超過必定次數返回客戶端異常。生產者經過設置ack=n,能夠保證一個ProducerRecord有n個副本(一個Partition的全部副本中有一個Leader負責與客戶端交互,其他副本做爲Follower從Leader複製數據,提供容錯性)被寫入成功纔會收到成功的ack消息。整個topic的順序沒法保證,1個分區的順序能夠經過設置retries>0(重試次數),和max.in.flight.requests.per.connection=1(1次只發1條消息避免後到的消息先成功)來保證,不過會嚴重影響生產者性能,若非嚴格順序要求不建議使用
  • 一個消費者group老是能得到一個topic的所有消息無論還有沒有其餘group訂閱該topic,group內經過添加消費者來伸縮讀取能力和處理能力,每一個消費者只處理一部分數據,並且消費者數量不要超過partition數量,否則多餘的會閒置浪費。group內全部消費者向羣組協調器發送心跳保持活躍,添加和刪除消費者時的再均衡(分配分區與消費者對應關係)也是由羣組協調器完成
  • Kafka使用ZooKeeper維護集羣成員信息,全部broker都對應/brokers/ids的臨時節點並訂閱其變動事件,在broker加入或退出時獲得消息;集羣中有一個控制器對應/controller臨時節點(全部broker均可以嘗試建立節點成功則成爲Controller,失敗則知道Controller已經存在,全部broker都會監聽這個節點的變動,經過遞增的controller epoch來忽略舊控制器消息避免腦裂),除了完成broker功能以外還負責partition副本的leader選舉;持續獲得來自leader最新消息的副本叫作同步的副本,當leader失效時,只有同步的副本纔可能被選爲新的leader;不一樣partition的副本和leader都均勻的分佈在全部broker之間避免熱點問題,副本儘可能放在不一樣機架提升容錯性
  • kafka處理常見幾種請求:元數據請求,能夠發送給任意broker,包含客戶端感興趣的主題列表,返回主題包含的分區、副本及其leader;生產請求,ack能夠爲0,1,all三個值;讀取請求,零拷貝返回客戶端指定的消息(省掉了用戶緩衝區,直接從磁盤到內核),要注意的是,leader只有把數據安全複製到副本中才能給客戶端返回這個數據;其餘請求,如偏移量(再也不保存在ZooKeeper中)
  • 由於大文件的查找和刪除都很費時易錯,因此每一個partition都分紅了許多segment,一個segment包含1GB或者1周的數據(較小爲準),正在寫入數據的叫作活躍片斷,永遠不會被刪除。每一個分區還有一個索引提高查詢效率
  • 可靠性和速度(簡便性)一般是負相關的,Kafka在這二者之間是能夠高度配置的,適應從跟蹤用戶點擊支付操做的不一樣可靠性級別要求。kafka的可靠性機制包括:分區消息順序性、多副本確認實現容錯性、只要還有一個副本是活躍的已提交消息就不會丟失、消費者只能消費已提交數據。這些基本機制加上一些配置參數(unclean.leader.election.enable、min.insync.replicas、生產者ack)的權衡就能構建不一樣級別的可靠系統,可靠級別能夠是針對broker或者topic。總而言之、可靠性不只是kafka單方面的事情,須要整個系統配合如系統架構、生產者消費者的使用方式與配置、topic和broker配置等等
  • 跨集羣的複製在kafka中叫作mirror功能,應用場景:將不一樣區域的集羣數據複製到中心集羣便於分析數據、冗餘實現災備、雲遷移。跨數據中心通訊有高延遲、有限帶寬、高成本等特色,常見架構有:Hub-Spoke架構(一中央多本地集羣)、雙活架構(兩個集羣都對外服務,就近原則)、主備架構(主集羣服務、備集羣只在主不可用時對外服務)
  • 事件流是無邊界的(持續增加)、有序的、可重播的、不可變的記錄。流式處理就是實時的處理一個或多個事件流,是一種編程範式就像請求響應式批處理式,可是延遲吞吐量都位於二者之間。

看完這本書基本就能把kafka的使用方法和基本原理搞清楚了,可是翻譯有時候有點點問題,我以爲普通的段落能夠翻譯,可是專用名詞如segmentpartition等仍是直接保留比較好,省得有歧義,固然總體上來來講配合官網文檔讀起來仍是沒問題的。
要想深刻的話源碼在

NoSQL精粹

NoSQL精粹 (豆瓣): https://book.douban.com/subje...

本書先分析了傳統關係數據庫的不足而後引入NoSQL,講到了鍵值、文檔、列族、圖等多種數據庫並分析了其優點劣勢,可讓咱們對NoSQL有一個全面的瞭解,爲咱們進一步NoSQL的探索之路開一個好頭。

亮點:

  • NoSQL泛指最近誕生非關係型數據庫如Cassandra、MongoDB、Neo4j等,他們主張無模式(schemaless)的數據。傳統關係數據庫有可持久化模型標準便於共享和集成事務支持等優勢,NoSQL有無模式便於程序對象與數據庫之間的映射適應集羣等優勢。因此NoSQL和傳統關係數據庫各有所長,發展過程當中也在互相借鑑優勢,誰也不能取代誰,未來都會在各自的領域中發光發熱
  • 關係模型把數據分割成簡單的行,一般一個對象可能須要多行數據經過外鍵鏈接在一塊兒來表示(若是按照嚴格的關係數據庫範式);聚合是領域驅動設計的術語,把一組相關聯的對象視爲一個總體單元來操做,這個單元就叫作聚合(aggregate)。聚合的邊界劃分沒有標準答案,取決於你以後準備怎樣操做數據。由於以聚合爲單位複製和分片比較天然因此集羣中操做數據庫仍是聚合更簡單。若數據操做大多在同一聚合內執行則應使用面向聚合的數據庫(鍵值、文檔、列族數據庫),若交互須要多種不一樣的格式則最好選聚合無知式aggregate-ignorant)數據庫(關係數據庫、圖數據庫),若待處理數據中有大量的關係最好就選關係數據庫,可是若是關係複雜、並行交錯最好選圖數據庫(插入費時、查詢比複雜的join快得多)
  • 寬泛的說數據分佈有兩條正交的路徑:複製,一份數據拷貝到多個節點,有主從式(主節點瓶頸問題)和對等式(一致性問題)兩種形式;分片,將不一樣的數據存放到不一樣的節點。這裏注意不要和另外一個概念混淆:數據庫水平(一個表的不一樣行數據置於不一樣節點)、垂直(一個表的不一樣列置於不一樣節點或者拆爲多個表)拆分。實際分佈式系統中通常都是複製和分片結合的(如上面提到的kafka)
  • 版本戳能夠檢測衝突用來實現CAS,能夠用計數器、GUID、Hash、時間戳等方式實現也能夠組合實現,分佈式系統中,能夠採用「由版本戳構成的數組」來檢測不一樣節點是否發生了「相互衝突的更新操做」
  • 鍵值數據庫最簡單,只能按鍵檢索,適用於會話信息、用戶配置信息、購物車等;文檔數據庫呈樹狀結構能夠看作支持值檢索的鍵值數據庫,適用於CMS及博客、電子商務等;列族數據庫將數據存在列族中,列族裏的行則把許多列數據與本行的行鍵聯繫起來,列族一般把須要一併訪問的相關數據分紅組,提升訪問效率,適用於事件記錄、博客、計數器等;圖數據庫把具備屬性的實體(節點)按關係(邊)聯繫起來,適用於互聯網數據如社交網絡、安排運輸線、推薦引擎等
  • Neal Ford 2006年造出了多語言編程(polyglot programming):應該以多種語言混合編寫同一應用程序,以各自語言的優點來解決其中不一樣的問題,同理數據庫也能夠遵循相似的原則混合持久化(polyglot persistence),好比購物車能夠用鍵值數據庫存儲,可是訂單要用關係型數據庫。因此除非是編程語言狂熱愛好者,咱們大部分人都不該該去爭論什麼語言好,什麼數據庫好,不要想着一把刷子走遍世界,而應該普遍瞭解,解決問題的時候選擇合適的工具,必要的時候也要本身改工具甚至造工具

本書的一個問題就是有點舊了,2013年第一版,這5年來NoSQL發展很快,已經被普遍用於企業級的系統之中了,尤爲是Redis和MongoDB,因此有需求就大膽的用吧。

大型網站技術架構

大型網站技術架構 (豆瓣): https://book.douban.com/subje...

把事情作大是咱們許多人的追求,這本書就可讓咱們瞭解一下一個大型網站的架構應該要注意些什麼,不管是摸得着的tech仍是比較摸不着的leadership,都值得借鑑。固然,書很薄,大多隻能泛泛而談,要想真正掌握,每一部分咱們都得本身單獨深挖,因此本書能夠看作一個大目錄,爲接下來的學習指引方向。

亮點:

  • 講述了一個單機網站發展到大型分佈式網站的完整歷程,處於業務快速發展期間的公司能夠借鑑,提早作好規劃
  • 架構設計時要注意:不要盲目追隨大公司而是要考慮本身業務;要結合網站實際使用新技術,不要盲目追求新奇酷炫;不要想着用技術解決一切問題,業務模式等也須要考慮;
  • 模式:每個模式描述了一個在咱們周圍不斷重複的問題以及該問題解決方案的核心,這樣你就能1次又1次的使用該方案而沒必要重複勞動。模式的關鍵在於可重複性,包括問題和方案的可重複性。
  • 大型網站有一些常見的架構模式:分層,如應用層、服務層、數據層;分割,如購物、論壇、搜索、廣告;分佈式,包括服務、靜態資源、數據庫、計算、鎖、文件、配置信息等;集羣,相同業務經過集羣負載均衡提升服務能力;緩存,如CDN、反向代理、本地緩存、分佈式緩存;異步,事務關係越少就越能獨立發展,異步也是解耦的一種協做方式;冗餘,冷備、熱備、災備等;自動化,包括髮布、測試、部署、報警、失效轉移、恢復、降級、分配資源等,自動化能提升效率並減少人爲出錯機率;安全,手機驗證碼、圖像驗證碼、轉義、風控等。全部模式都是在性能(響應時間、qps等)、可用性(冗餘)、伸縮性(機器的增減)、擴展性(業務的增減)、安全性(惡意訪問、竊取、攻擊)這幾個維度之間進行平衡
  • 性能針對不一樣羣體須要不一樣的定義(針對用戶的響應時間,針對系統的吞吐量、併發量等)來衡量,也須要測試(壓測等),同時要從架構的多個層面(前端、應用層、存儲層)來進行優化
  • 可用性通常用幾個9來形容(4個9就是99.99%,一年小於53分鐘不可用),實現高可用架構的主要手段是數據和服務的冗餘備份和失效轉移。應用層(文庫、貼吧、知道)和服務層(帳戶服務、session服務)由於通常無狀態因此很容易擴展(負載均衡),新節點上下線都很容易,可是服務層須要注意好分級管理、超時設置、異步調用、服務降級、冪等設計等。數據層(數據庫、文件、緩存)爲了保證數據不丟失須要複製並均勻分佈在集羣中
  • 集羣處理能力若是能和服務器數量正相關,那麼網站就具備伸縮性架構,若是能成線性關係那更是高伸縮性,主要分爲不一樣服務物理拆分和單一服務集羣伸縮(類比於數據庫垂直拆分和水平拆分)。應用集羣伸縮性通常經過負載均衡實現如http重定向、DNS輪詢、反向代理、IP負載均衡、數據鏈路層負載均衡等;緩存集羣伸縮性僅靠負載均衡是不夠的,還須要一致性hash、虛擬槽分區等方法使得緩存在節點發生變化時不會集體失效;存儲集羣伸縮性對持久性和可用性要求更高,可是這裏做者沒怎麼講具體作法
  • 擴展性是在對現有系統影響最小的狀況下持續提高或增長服務的能力,表如今系統基礎設施穩定,應用之間耦合較少等,是系統架構層面的開閉原則體現。主要有:分佈式消息隊列解耦生產者與消費者、分佈式服務打造可複用的業務平臺、利用開放平臺打造生態圈實現開放雙贏等方式
  • 安全性通常主要注意XSS、注入、CSRF等攻擊,主要手段有:用戶輸入轉義、表單token、驗證碼、加密、過濾、風控等
  • 領導的真諦就是尋找一個值得共同奮鬥的目標,營造一個讓你們都能最大限度發揮自我價值的氛圍;發掘人的優秀比發掘優秀的人更有意義

讀完發現本書幾乎全程「黑友商」,有的甚至好幾遍(* ̄︶ ̄),有點不純粹啊。

深刻理解 Java 內存模型

這本書是infoq上的系列博客造成的一本很薄的書,對於瞭解JMM仍是頗有用的。
深刻理解Java內存模型(二)——重排序: http://www.infoq.com/cn/artic...

亮點:

  • 重排序的目的是提升性能,分爲三種:編譯器、處理器指令級並行技術、內存系統的重排序。JMM屬於語言級別的內存模型,經過禁止特定類型的編譯器重排序(直接可控)和處理器重排序(經過內存屏障實現)來在不一樣的平臺對爲程序員提供一致的內存模型
  • 內存屏障有四種:StoreLoad的排列 ,其中StoreLoad Barriers是一個全能型的屏障,同時具備其餘三個屏障的效果,它確保store數據對其餘處理器的load可見
  • 處理器內存是硬件級別的內存模型,JMM是一個語言級別的內存模型,順序一致性內存是一個理論參考模型,性能依次下降,可編程性依次上升。因此JMM主要關注易編程性和性能,在二者之間求得平衡

深刻分佈式緩存:從原理到實踐

深刻分佈式緩存:從原理到實踐 (豆瓣): https://book.douban.com/subje...

緩存在現在的互聯網中已經幾乎是標配了,分佈式緩存更是大型網站不可或缺的,本書就讓咱們從原理開源實現業務實踐一塊兒打包瞭解了。

亮點:

  • 計算機世界中,不管是硬件仍是軟件,不管是單機仍是分佈式,緩存都被用於解決響應緩慢的問題,是提高性能的關鍵技術。其核心就是空間換時間,解耦高速部件與低速部件。緩存因爲不一樣硬件的訪問速度和價格不一樣而進行分級,每一級存儲對應熱度級別的數據,分層逐級減小流量的衝擊,保護用戶體驗與系統可用性。分佈式環境下要關注其命中、更新、失效、一致性等
  • 緩存是無所不在的,從架構的角度看能夠分爲三塊:客戶端緩存 在客戶端減小網絡請求,如頁面緩存(文件化)、瀏覽器經過HTTP協議實現的緩存(etag,304 not-modified)、APP緩存(sqlite)等;網絡緩存 位於客戶端與服務端之間,代理部分客戶端請求給服務端減負,如web代理緩存(nginx)、邊緣緩存(CDN);服務端緩存 是緩存的重點和難點,如數據庫緩存(query_cache)、平臺級緩存(大而全的Ehcache、極簡的Guava )、應用級緩存(redis)
  • 書中澄清了許多分佈式方面的概念和理論,如集羣是一組互相獨立的計算機經過網絡鏈接構成一個組實現同一個功能,對客戶端表現爲一個獨立服務器,能夠增長可用性與伸縮性,而分佈式系統就是許多不一樣功能的集羣構成的一個實現特定業務的系統;冪等性是指調用1次和N次結果同樣,這個在分佈式系統中很重要是由於網絡抖動等因素經常致使重發;分佈式系統的本質是一堆廉價的硬件攢在一塊兒得到更好的吞吐量和性能以及可用性,有幾個問題廣泛關心:活性檢測(週期心跳、累計失效檢測)、高可用(主備、雙主、集羣)、容錯處理(冷熱切換、冗餘、備份)、重試機制(失敗重試、事務補償)、負載均衡(多機分擔請求),也有幾個實踐很重要:全局ID(數據庫自增id如flicker、UUID、snowflake、預生成置於緩存中)、哈希取模分配一致性哈希(單調性、分散性)、路由表數據拆分
  • 書中在JSR規範下帶領咱們實現了一個緩存框架CSCache,架構由上到下是客戶端、緩存提供層、緩存管理層、緩存存儲層(基本存儲,LRU存儲,Weak存儲),設計思路值得借鑑
  • redis有瓶頸:單機數據量限制、單線程吞吐量限制(尤爲是大塊數據讀取延遲明顯)、單點故障等,目前已有的解決方案有:水平拆分如Proxy和Twemproxy、自帶主從複製(含斷點續傳)、sentinel監控自動故障轉移(使用raft相似算法選主)、redis3.0後出來的去中心化(採用Gossip協議在節點之間達成一致)的cluster提供了完整的sharding、replication、failover等解決方案
  • 本書覆蓋了廣告、社交、電商等多種業務的緩存模式,能開開眼界,未來可能還真用得上,尤爲是社交和電商這兩塊講得很細緻,幾乎能夠做爲一精簡而完整的解決方案了
相關文章
相關標籤/搜索