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