第一章 分布式系統(tǒng)介紹 分布式系統(tǒng)的定義:組件分布在網(wǎng)絡(luò)計(jì)算機(jī)上,組件間僅僅通過(guò)消息傳遞來(lái)通信并協(xié)調(diào)行動(dòng)。 分布式系統(tǒng)的意義:
摩爾定律:當(dāng)價(jià)格不變時(shí),每隔 18 個(gè)月,集成電路上可容納的晶體管數(shù)目會(huì)增加一倍,性能也將提升一倍。 線程與進(jìn)程的執(zhí)行模式 馮諾依曼結(jié)構(gòu):輸入設(shè)備、輸入設(shè)備、運(yùn)算器、控制器、存儲(chǔ)器。 基于共享容器協(xié)同的多線程模式:經(jīng)典如生產(chǎn)者消費(fèi)者問(wèn)題,對(duì)于存儲(chǔ)數(shù)據(jù)的容器或?qū)ο?,有線程安全和不安全之分,對(duì)于不安全的容器或?qū)ο?,一般可以通過(guò)加鎖或者通過(guò) Copy On Write 的方式控制并發(fā)。 通過(guò)事件協(xié)同的多線程模式:避免死鎖 多進(jìn)程模式:
網(wǎng)絡(luò)通信基礎(chǔ)知識(shí) OSI 七層模型與 TCP/IP 模型: Socket 套接字進(jìn)行網(wǎng)絡(luò)通信開(kāi)發(fā)時(shí),用到的三種方式:BIO、NIO 和 AIO BIO:Blocking IO,采用阻塞的方式實(shí)現(xiàn),一個(gè)線程處理一個(gè) Socket,發(fā)生建立連接、讀數(shù)據(jù)、寫(xiě)數(shù)據(jù)的操作時(shí),都可能會(huì)阻塞。 NIO:Nonblocking IO,基于時(shí)間驅(qū)動(dòng)思想,采用 Reactor 模式,可以在一個(gè)線程中處理多個(gè) Socket 套接字 AIO:AsynchronousIO,異步 IO,采用 Proactor 模式,與 NIO 的差別是,AIO 在進(jìn)行讀寫(xiě)操作時(shí),只需要調(diào)用響應(yīng)的 read/write 方法,并且需要傳入 CompletionHandler,在動(dòng)作完成后會(huì)調(diào)用。 如何把應(yīng)用從單機(jī)擴(kuò)展到分布式
方式 1 和 2,透明代理:對(duì)發(fā)起方和處理方都是透明的
缺點(diǎn):
方式 3,采用名稱服務(wù)器直連的方式: 請(qǐng)求發(fā)起方和處理方直接沒(méi)有代理服務(wù)器,而是直接連接。外部多了一個(gè)“名稱服務(wù)”的角色,作用有:
名稱服務(wù)只是起到一個(gè)地址交換的作用,在發(fā)起請(qǐng)求的機(jī)器上,需要根據(jù)從名稱服務(wù)得到的地址進(jìn)行負(fù)載均衡的工作。 優(yōu)點(diǎn)如下:
缺點(diǎn)就是代碼升級(jí)較復(fù)雜 方式 4,采用規(guī)則服務(wù)器控制路由的請(qǐng)求直連調(diào)用 與名稱服務(wù)器不同的是,規(guī)則服務(wù)器并不和請(qǐng)求處理的機(jī)器交互,只負(fù)責(zé)把規(guī)則提供給請(qǐng)求發(fā)起的機(jī)器。 方式 5,Master+Worker 的方式 存在一個(gè) Master 節(jié)點(diǎn)來(lái)管理任務(wù),由 Master 把任務(wù)分配給不同的 Worker 進(jìn)行處理。 運(yùn)算器的變化 通過(guò) DNS 服務(wù)器進(jìn)行調(diào)度和控制 增加負(fù)載均衡設(shè)備,DNS 返回的永遠(yuǎn)是負(fù)載均衡地址 存儲(chǔ)器的變化 同控制器的變化,加代理服務(wù)器、or 名稱服務(wù)器、or 規(guī)則服務(wù)器 分布式系統(tǒng)的難點(diǎn)
第二章 大型網(wǎng)站及其架構(gòu)演進(jìn)過(guò)程 大型網(wǎng)站:訪問(wèn)量(PV)、數(shù)據(jù)量、業(yè)務(wù)復(fù)雜度 單機(jī)負(fù)載告警,數(shù)據(jù)庫(kù)與應(yīng)用分離 應(yīng)用服務(wù)器負(fù)載告警,走向集群
Session 保存會(huì)話狀態(tài),在 Web 服務(wù)器上,各個(gè)會(huì)話獨(dú)立存儲(chǔ),多臺(tái)服務(wù)器不能保證每次請(qǐng)求都落在同一邊的服務(wù)器上。解決方案如下: 1、Session Sticky:負(fù)載均衡根據(jù)會(huì)話標(biāo)識(shí)進(jìn)行轉(zhuǎn)發(fā),讓同樣的 Session 請(qǐng)求每次都發(fā)送到同一個(gè)服務(wù)器端處理 缺點(diǎn):
2、Session Replication:會(huì)話在多態(tài)服務(wù)器上復(fù)制同步 缺點(diǎn):
3、Session 數(shù)據(jù)集中存儲(chǔ) Session 數(shù)據(jù)不再 Web 服務(wù)器上,而是放在另一個(gè)集中存儲(chǔ)的地方。 缺點(diǎn):
4、Cookie Based:把 Session 數(shù)據(jù)放在 Cookie 中 缺點(diǎn):
數(shù)據(jù)讀壓力變大,讀寫(xiě)分離 1、采用數(shù)據(jù)庫(kù)作為讀庫(kù) 缺點(diǎn):
2、搜索引擎其實(shí)是一個(gè)讀庫(kù) 3、加速數(shù)據(jù)讀取的利器——緩存
彌補(bǔ)關(guān)系型數(shù)據(jù)庫(kù)的不足,引入分布式存儲(chǔ)系統(tǒng) 分布式文件系統(tǒng),解決小文件和大文件的存儲(chǔ)問(wèn)題 分布式 key-value 系統(tǒng),提供高性能的半結(jié)構(gòu)化支持 分布式數(shù)據(jù)庫(kù)提供一個(gè)支持大數(shù)據(jù)、高并發(fā)的數(shù)據(jù)庫(kù)系統(tǒng) 讀寫(xiě)分離后,數(shù)據(jù)庫(kù)又遇到瓶頸 盡管讀寫(xiě)分離以及分布式存儲(chǔ)系統(tǒng),能夠降低主庫(kù)的壓力,但是交易、商品、用戶的數(shù)據(jù)都還在一個(gè)數(shù)據(jù)庫(kù)中,壓力還在繼續(xù)增加,我們有數(shù)據(jù)垂直拆分和水平拆分兩種選擇; 1、專庫(kù)專用,數(shù)據(jù)垂直拆分 垂直拆分即把不同的業(yè)務(wù)數(shù)據(jù)分到不同的數(shù)據(jù)庫(kù)中。 問(wèn)題:
2、單表達(dá)到瓶頸,數(shù)據(jù)水平拆分 水平拆分就是把同一個(gè)表的數(shù)據(jù)拆到兩個(gè)數(shù)據(jù)庫(kù)中。 問(wèn)題:
數(shù)據(jù)庫(kù)問(wèn)題解決后,應(yīng)用面對(duì)的新挑戰(zhàn) 拆分應(yīng)用
初識(shí)消息中間件 消息中間件是在分布式系統(tǒng)中完成消息發(fā)送和接收的基礎(chǔ)軟件。兩個(gè)明顯好處:異步、解耦。 第三章 構(gòu)建 Java 中間件 三個(gè)領(lǐng)域的中間件:
構(gòu)建 Java 中間件的基礎(chǔ)知識(shí) JVM 中堆分為三塊:Young/Tenured/Perm,新生代 / 年老代 / 持久代 一般來(lái)說(shuō),新對(duì)象分配在新生代的 Eden 區(qū),也可能直接分配在年老代,在進(jìn)行新生代垃圾回收時(shí),Eden 區(qū)存活的對(duì)象被復(fù)制到空的 Survivor 區(qū),在下次新生代回收時(shí),Eden 區(qū)存活的對(duì)象和這個(gè) Survivor 存活的對(duì)象被復(fù)制到另外那個(gè) Survivor 區(qū),并且清空當(dāng)前 Survivor 區(qū),經(jīng)過(guò)多次新生代垃圾回收,還存活的對(duì)象會(huì)被移動(dòng)到年老代。 線程池
使用線程池的方式是復(fù)用線程的,不用每次都創(chuàng)建線程。而創(chuàng)建線程的開(kāi)銷占比較大。 synchronized synchronized 修飾靜態(tài)方法、對(duì)象方法、代碼塊 ReetrantLock
volatile 可見(jiàn)性指一個(gè)線程修改變量值后,其他線程中能夠看到這個(gè)值。volatile 雖然解決了可見(jiàn)性問(wèn)題,但是不能控制并發(fā) Atomics 原子操作,如 AtomicInteger 內(nèi)部通過(guò) JNI 的方式使用了硬件支持的 CAS 指令 wait、notify 和 notifyAll wait 是等待線程,notify 是喚醒一個(gè)等待線程(并不能指定,隨機(jī)),notifyAll 是喚醒所有的等待線程。 CountDownLatch java.util.concurrent 包中的一個(gè)類,主要提供的機(jī)制是當(dāng)多個(gè)線程都到達(dá)了預(yù)期狀態(tài)或完成預(yù)期工作時(shí)觸發(fā)事件,其他線程可以等待這個(gè)事件來(lái)觸發(fā)自己后續(xù)的工作。 CyclicBarrier 循環(huán)屏障,可以協(xié)同多個(gè)線程,讓多個(gè)線程在這個(gè)屏障前等待,知道所有線程都到達(dá)了這個(gè)屏障時(shí),再一起繼續(xù)執(zhí)行后面的動(dòng)作。 Semaphore Semaphore 是用于管理信號(hào)量的,構(gòu)造時(shí)傳入可供管理的信號(hào)量的數(shù)值。如果信號(hào)量只有一個(gè),就退化到互斥鎖了,如果多于一個(gè),則主要用于控制并發(fā)數(shù)。 Exchanger 用于兩個(gè)線程之間進(jìn)行數(shù)據(jù)交換,線程會(huì)阻塞在 exchange 方法上,知道另外一個(gè)線程也到了同一個(gè) Exchanger 的 exchange 方法時(shí),二者進(jìn)行交換。 Future 和 FutureTask Future 是一個(gè)接口,F(xiàn)utureTask 是一個(gè)具體實(shí)現(xiàn)類
getDataFromRemote2 還是使用率 getDataFromRemote 完成操作,并且用到了線程池:把任務(wù)加入線程池中,把 Future 對(duì)象返回出去。 并發(fā)容器 CopyOnWrite:更改容器時(shí),把容器復(fù)制一份進(jìn)行修改,用于讀多寫(xiě)少 Concurrent:盡量保證讀不加鎖,并且修改時(shí)不影響讀,所以比讀寫(xiě)鎖更高的并發(fā)性能 動(dòng)態(tài)代理 繼承 InvocationHandler 反射 Java 反射機(jī)制是指在運(yùn)行狀態(tài),對(duì)于任意一個(gè)類,都能知道這個(gè)類所有屬性和方法;對(duì)于任意一個(gè)對(duì)象,都能夠調(diào)用它的任意一個(gè)方法和屬性。
網(wǎng)絡(luò)通信的選擇 BIO、NIO、AIO 第三方框架,MINA,Netty 第四章 服務(wù)框架 服務(wù)調(diào)用端的設(shè)計(jì)與實(shí)現(xiàn) 調(diào)用發(fā)起 ==> 尋址路由 ==> 協(xié)議適配和序列化 ==> 網(wǎng)絡(luò)傳輸 ==> 反序列化 協(xié)議解析 ==> 得到結(jié)果返回給調(diào)用方 1、確定服務(wù)框架的使用方式 2、服務(wù)調(diào)用者與服務(wù)提供者之間通信方式的選擇 3、引入基于接口、方法、參數(shù)的路由 4、多機(jī)房場(chǎng)景,避免跨機(jī)房調(diào)用,一是在服務(wù)注冊(cè)中心甄別,二是地址過(guò)濾 5、服務(wù)調(diào)用端的流控處理 6、序列化與反序列化處理,Java 本身的序列化性能問(wèn)題、跨語(yǔ)言問(wèn)題、序列化后語(yǔ)言長(zhǎng)度 7、網(wǎng)絡(luò)通信實(shí)現(xiàn)選擇:BIO、NIO、AIO 8、支持多種異步服務(wù)調(diào)用方式:Oneway,Callback,F(xiàn)uture,可靠異步 服務(wù)提供端的設(shè)計(jì)與實(shí)現(xiàn) 1、如何暴露遠(yuǎn)程服務(wù) 2、服務(wù)端對(duì)請(qǐng)求處理的流程 3、執(zhí)行不同服務(wù)的線程池隔離 4、服務(wù)提供端的流控處理 第五章 數(shù)據(jù)訪問(wèn)層 分布式事務(wù)
多機(jī)自增主鍵問(wèn)題 考慮唯一性和連續(xù)性,UUID 生成方式(IP、MAC、時(shí)間等)連續(xù)性不好 實(shí)現(xiàn)方案 1:把 ID 集中放在一個(gè)地方進(jìn)行管理,對(duì)每個(gè) Id 序列獨(dú)立管理,每臺(tái)機(jī)器使用 Id 時(shí)都從這個(gè) Id 生成器上取。 缺點(diǎn):
實(shí)現(xiàn)方案 2:舍掉 Id 生成器,把相關(guān)的邏輯放到需要生成 Id 的應(yīng)用本身。每個(gè)生成器讀取可用的 Id,然后給應(yīng)用使用,但是數(shù)據(jù)的 Id 并不是嚴(yán)格按照進(jìn)入數(shù)據(jù)庫(kù)順序而增大的。 應(yīng)對(duì)多機(jī)的數(shù)據(jù)查詢 跨庫(kù) Join
外鍵約束 外鍵約束比較難解決,不能完全依賴數(shù)據(jù)庫(kù)本身來(lái)完成之前的功能了。 跨庫(kù)查詢的問(wèn)題及解決 一張邏輯表,對(duì)應(yīng)多個(gè)數(shù)據(jù)庫(kù)的多張數(shù)據(jù)表,在一些場(chǎng)景下比較復(fù)雜,如排序、最大最小求和等函數(shù)處理、求平均值、非排序分頁(yè)、排序后分頁(yè)。 如何對(duì)外提供數(shù)據(jù)訪問(wèn)層的功能 1、為用戶提供專有 API 2、通用的方式,數(shù)據(jù)層 JDBC 3、基于 ORM 或類 ORM 接口的方式 直接基于 JDBC 驅(qū)動(dòng)方式較好 ~ 數(shù)據(jù)層的整體流程 SQL 解析 ==> 規(guī)則處理 ==>SQL 改寫(xiě) ==> 數(shù)據(jù)源選擇 ==>SQL 執(zhí)行 ==> 結(jié)果集返回合并處理 1、SQL 解析階段
2、規(guī)則處理階段
3、為什么要改寫(xiě) SQL 分庫(kù)分表后,同一個(gè)賣家的商品可能會(huì)分在多個(gè)庫(kù)中,查詢就要跨庫(kù)。分布的不同數(shù)據(jù)庫(kù)中的表的結(jié)構(gòu)雖然一樣,但是表的名字、索引名字未必一樣,所以要修改 SQL。 還有需要修改 SQL 的地方,如跨庫(kù)計(jì)算平均值,必須修改 SQL 獲取數(shù)量、總數(shù)后再進(jìn)行計(jì)算。 4、如何選擇數(shù)據(jù)源,讀寫(xiě)分析 5、執(zhí)行 SQL 和結(jié)果處理階段,異常處理和判斷 第六章 消息中間件 JMS,Java Message Service 是 Java EE 中關(guān)于消息的規(guī)范,ActiveMQ 等是對(duì)這個(gè)規(guī)范的實(shí)現(xiàn)。如果是小型系統(tǒng)直接使用 JMS 是一個(gè)經(jīng)濟(jì)的選擇,在大型系統(tǒng)中不適合使用 JMS。 如何解決消息發(fā)送一致性 消息發(fā)送一致性是指產(chǎn)生消息的業(yè)務(wù)動(dòng)作與消息發(fā)送一致,即如果業(yè)務(wù)操作成功了,那么由這個(gè)操作產(chǎn)生的消息一定要發(fā)送出去。 1、發(fā)送消息給消息中間件 2、消息中間件入庫(kù)消息 3、消息中間件返回結(jié)果 4、業(yè)務(wù)操作 5、發(fā)送業(yè)務(wù)操作結(jié)果給消息中間件 6、更改存儲(chǔ)中消息狀態(tài) |
|
來(lái)自: 萬(wàn)皇之皇 > 《IT互聯(lián)》