分佈式系統原理與應用複習

1 分佈式系統簡介

1.1 分佈式系統定義

產生背景:應用驅動+技術支撐
分佈式系統優點:支持業務固有的分佈性、經濟性、性能提升、可靠性提升
定義:分佈式系統是若干獨立計算機的集合,這些計算機對於用戶來說就像是單個相關係統。硬件角度:各個計算機是自治的,通過網絡互聯;軟件角度:用戶看到一臺邏輯計算機。(互聯、協作、單一視圖)

1.2 分佈式系統目標

(1)使遠程資源可訪問
分佈式系統的最主要目標是使用戶能夠方便地訪問遠程資源,並且以一種受控的方式與其他用戶共享這些資源。
(2)透明性:隱藏進程和資源分佈在多臺計算機上的事實。
透明性的程度和具體應用相關,同時還要考慮性能問題( 副本能提高性能,但保持副本的一致性需要進行更新傳播 )。透明性是要犧牲一些效率來達到的。具體透明性如下:
透明性的說明
(3)開放性
根據一系列準則來提供服務,這些準則描述了所提供服務的語法和語義。分佈式系統中服務通常通過接口來提供 ,而接口一般通過接口定義語言來描述
(4)可擴展性
規模擴展:方便的增加資源和用戶(限制:集中的服務、數據及算法)
地域擴展:用戶和資源相隔距離(限制:通信延遲、不可靠通信)
管理擴展:能跨越多個獨立的管理機構(限制:安全問題、收費問題)
解決擴展性的技術
a.隱藏通信延遲
採用異步通信方式,避免等待響應
採用多線程技術,提高併發
減少通信量,胖客戶端
b.分佈:DNS,WWW分佈式web項目
c.複製技術:擴展通常會導致性能的下降,複製能增加可用性,提高性能,利於負載均衡,但存在一致性問題。-複製也可隱藏通信時間

1.3 常見分佈式系統類型

(1)分佈式計算系統:用於高性能計算任務
①集羣計算系統
底層硬件由類似的工作站或者PC集組成,通過高速局域網緊密相連,每個結點運行相同的操作系統(具有同構性)
②網格計算系統
異構的(硬件、操作系統、網絡等都不盡相同)系統,把不同計算機的資源集中起來,進行協調工作
(2)分佈式信息系統:適用於大型企業或者組織對信息進行管理和事務處理,解決大型企業或組織對大量網絡應用、信息的集成和管理。
①事務處理系統(分佈式數據庫應用)
用戶看到的是一個完整的數據庫,但是數據實際是分佈在多個計算機結點上,事務處理系統能提供有效的存取手段來對數據進行處理。事務處理的特徵是所有操作要麼被完全執行,要麼不執行。
②企業應用集成:將各個應用集成起來,應用之間可以直接交換信息。
(3)分佈式普適系統:移動和嵌入式設備加入到系統中,以便訪問信息
①智能家居系統:把家庭中的設備集成爲單個系統,能夠進行自我配置和
自我管理
②電子健保系統:用於日常監視個人健康程度,在需要的時候與醫生聯繫

2 分佈式系統體系結構

2.1 體系結構樣式

軟件體系結構: 軟件的組件,以及組件之間的相互關係。
要素:組件-模塊單元,具有良好的接口
鏈接器-實現組件間通信的機制
軟件體系結構樣式:如何表示一個軟件體系結構
常見的體系結構樣式 :

  • 分層體系結構:系統由不同層的組件組成,只有相鄰層可以通信 ,請求消息自上 而下,響應消息自下而上
  • 基於對象的體系結構 :每個組件對應一個對象; RMI 通信
  • 以數據爲中心的體系結構:組件間通過一個公用的存儲實現通信
  • 基於事件的體系結構 :通過事件的傳播實現組件間的通信

2.2 系統體系結構

軟件體系結構的具體實例 :集中式體系結構(客戶/服務器模型–CS)、非集中式體系結構(點對點系統—P2P)、混合體繫結構

2.2.1 集中式體系結構

客戶 / 服務器模型
Server :服務器是實現特定服務的進程
Client :是通過往服務器發送請求來請求服務,然後等待服務器回覆的進程
請求 / 答覆模式:Client和Server分別扮演服務請求者和服務提供者。服務器監聽請求,客戶提出請求、接收響應;服務器等待請求,客戶等待響應。
應用分層(邏輯三層):用戶接口層、處理層、數據層
多層體系結構

  • 物理兩層體系結構:
    邏輯上三層部署在物理上的兩層上
    (1)客戶機,只含有實現(部分)用戶接口的程序
    (2)服務器,包含了其餘的部分,即實現處理和數據層的程序

  • 物理三層體系結構:
    服務器有時會擔任客戶機的角色;用戶接口、應用程序服務器、數據庫服務器
    多層是按縱向劃分,也可以按橫向劃分:垂直分佈(不同功能的分佈)、水平分佈(相同功能的複製)
    c/s 適合集中式網絡服務

2.2.2 非集中式體系結構

點對點系統(P2P):網絡上的所有節點都可以“平等”共享其他節點的計算資源,所有網絡節點上的設備都可以建立P2P對話。(既可以是客戶也可以是服務器))
P2P適合分散式服務,如即時通信、點對點文件傳輸、視頻會議等(eg.napster )
結構化的點對點體系結構
邏輯上的結構,方便快速查找,eg. Chord系統-基於Hash運算,CAN上下文可編址網絡-基於虛擬的 d 維笛卡爾座標
非結構化的點對點體系結構
每個節點維護一個鄰節點列表,泛洪查找–>改進:超級對等體(維護索引或充當代理)

2.2.3 混合體繫結構

將集中式和非集中式體系結構組合,eg.BitTorrent 系統,其目錄的存儲是集中的,但文件系統是分散的

2.3 中間件

中間件在應用程序和底層操作系統之間,其目的是要提供分佈式透明性
中間件如何不同應用程序的需求:

  • 針對不同的應用實現多箇中間件版本
  • 按照應用程序的需要來配置、適應中間件系統

攔截器:可中斷正常執行的控制流,插入執行其他代碼

  • 請求級攔截器
  • 消息級攔截器

3 進程

3.1 進程和線程

進程----- 程序的一次執行過程;資源分配的最小單位;
線程-----CPU分配的單位;程序執行的最小單位,資源調度的最小單位
爲什麼引入線程的: 提高併發程度, 適合多核, 通信代價小
(1)不必使進程因等待某事件而阻塞,提高了進程的執行效率;
(2)多處理/多核上可使線程並行執行;
(3)IPC需要內核干預,上下文切換代價高,線程可通過數據共享實現;
(4)軟件工程的需要,有些應用程序需要一組相互協作的任務完成。
線程的實現以線程包的形式提供,分爲:

  • user-level線程庫;上下文切換代價小,但容易造成整個進程的阻塞。
  • kernel-level線程庫;不會導致進程的阻塞,但上下文切換代價高。
    爲此採用混合方式,通過 LWP 進行線程管理(結合kernel-level lightweight processes和user-level threads)。
    多核處理器的三種實現方案 : 1) 共享緩存方案 ; 2) 共享 IO 接口方案 ; 3) 共享數據包方案 ;
    多線程之間的合作方式:(a)派遣者 / 工作者模式 (b) 團隊模式 © 管道模式
    在分佈式系統中,線程可用於開發高效率的客戶端和服務器.

3. 2虛擬化

定義:將一臺計算機虛擬爲多臺邏輯上的計算機
原因:

  • 高層軟件跟不上底層硬件的更新
  • 可移植和靈活性

虛擬機體系結構
計算機系統提供了不同層次的接口以實現不同的虛擬化技術,如下圖
在這裏插入圖片描述
①由機器指令組成的硬件和軟件之間的接口

  • 任何程序都能調(General instructions)
  • 只有特權程序才能調用(Privileged instructions)
    ②由操作系統提供的系統調用(System calls)組成的接口
    ③由庫函數組成的接口(Library functions),通常形成了應用程序編程接口(API)

虛擬化可採用兩種方式
①進程虛擬機-Runtime System,提供一套抽象指令集來執行程序,如 JVM,在操作系統和應用層之間
②虛擬機監視器VMM-系統屏蔽硬件同時提供機器指令接口,可以有多個不同的操作系統獨立併發地運行在同一平臺,如VMWare,硬件和操作系統之間

3.3 c/s模型

client:

  • 提供用戶接口
  • 和服務器進行交互
  • 執行部分處理工作(ATM 機,機頂盒,條碼閱讀器等)
  • 提供分佈式透明性(Client-side solution)

server:
(1)工作方式
等待來自客戶的請求,隨後處理該請求,返回處理結果,並等待下一個客戶請求。
(2)組織結構
迭代服務器(Iterative server):自己處理請求,並將響應返回給發出請求的客戶。
併發服務器(Concurrent server):自己不處理請求,將請求傳遞給某個獨立線程或者其他進程來處理,自己立即返回並等待下一個輸入的請求。
(3)端口訪問
客戶如何訪問服務器?服務器在端口監聽客戶的請求。
客戶如何知道服務器的端口?爲已知的服務分配特定端口,如Http是80端口,FTP是21端口;動態分配
客戶端到服務器的綁定:

  • 使用daemon(守護程序,查找end-point table)
  • 使用superserver(create server)

(4)中斷服務

  • 退出客戶應用程序
  • 利用帶外數據:帶外數據是服務器在處理客戶發送的其他所有數據之前必須處理的數據。

(5)狀態

  • 狀態無關服務器(Stateless server):服務器不保存其客戶的狀態信息,也不把自身的狀態變化告知任何客戶(例如:Web服務器)
  • 狀態相關服務器(Stateful server):服務器端保存每次通信的信息(例如:文件服務器)

(6) 服務器集羣
一組經網絡相連的機器,每臺機器運行一 個或多個服務器,實現分佈式計算 ,邏輯上分三層
1 、存儲器、交換機,分配客戶請求給服務器
2 、存儲器、應用或計算服務器,提供計算或相應處理
3 、存儲器、文件或數據庫服務器,完成數據處理服務
不同服務運行在不同的機器上,交換機需要區分不同的請求,轉發到合適的服務器,可能導致負載不均(代碼遷移, 負載均衡算法
分佈式透明性(單點訪問, TCP handoff)

3.4 代碼遷移(migration)

爲什麼要進行代碼遷移

  • 性能提升:從負載重的機器遷移到負載輕的機器;把客戶端的部分遷移到服務器;把服務器的部分代碼遷移到客戶端
  • 靈活性 客戶綁定到服務器時,可以動態下載代碼

代碼遷移模型:
一個進程包括:代碼段,資源段,執行段(包括當前進程的狀態)
移動的強弱:

  • 弱可移動性,只傳輸代碼及相關初始化數據 ,要求目標機器能執行代碼,遷移後的代碼 總是從預先定義的位置開始執行
  • 強可移動性,移動代碼和執行段,可以先停止運行中的程序,然後遷移,在目標機器上從停止的地方繼續執行

移動的方向:

  • 發送者啓動遷移:代碼當前駐留在哪臺機器上或者正在哪臺機 器上執行,就由該機器來啓動遷移。如向計算服務器上載程序
  • 接收者啓動遷移:代碼遷移的主動權掌握在目標機器手中。 如Java 小程序

資源和進程的綁定方式

  • By identifier----like URL(強綁定方式 )
  • By value–like standard libraries: C等(較弱綁定方式 )
  • By type------like monitors, printers (弱綁定方式 )

資源對機器的綁定方式

  • Unattached resources不同機器間可移動
  • Fastened resources移動複製代價高
  • Fixed resources不能移動

資源的遷移方式:建立全局引用GR,移動MV,複製CP,進程與本地資源重新綁定RB

4 進程間通信

4.1 Layered Protocols

  • 物理層:負責對電平信號(位)的傳輸 ;
  • 數據鏈路層:幀校驗和糾錯 ;
  • 網絡層:路由 ( 面向連接 X.25 , 面向非連接的IP);
  • 傳輸層:消息的無損傳送,並保持進入時的次序(TCP/UDP)
  • 會話層:提供對話控制、對正在會話的對話者進行跟蹤 以及同步功能
  • 表示層:消息表示(爲了實現各機器內部表示方式不同 的數據傳遞) ;
  • 應用層:公共事務遵循的一個雜項協議的集合 .
    Client-Server TCP:T/TCP-省略了連接開始的三次握手 ,縮短了連接結束時TIME_WAIT狀態持續時間。更快、更高效和更可靠

4.2 中間件協議

中間件是一種應用程序,許多應用層的協議可以由它完成
中間件的通信類型
Persistent持久通信-存儲起來 ;Transient瞬時通信
Asynchronous異步通信; Synchronous同步通信-阻塞
6 種不同語義的通信方式
1.持久異步通信-郵箱
2.持久同步
3.瞬時異步
4.Receipt-based 瞬時同步
5.Delivery-based 瞬時同步
6.Response-based 瞬時同步

4.3 RPC遠程過程調用

允許程序去調用位於其它機器上的過程。消息的傳送與 I/O操作對於程序員不可見
如何供分佈式透明性: 實現客戶存根stub和服務器存根stub,接口與過程實現分離。
執行一個RPC共10步
異構系統傳參數
值(大小端模式)
指針:指針只在使用該指針的進程所在的 地址空間內纔有意義
建立 RPC 協議:規定-消息的格式;數據的表示標準及對複雜數據操作步驟;消息的交換方式-TCP/IP協議
生成 Client/Server Stub:通過對 IDL 描述的接口編譯產生
原始RPC 的缺點: 必須消息傳遞;隱含同步方式
改進: asynchronous RPC
DCE軟件
DCE RPC 的目標
使遠程過程可訪問 ;
透明性:隱藏通信細節和底層硬件差異
開放性:採用統一的協議
RPC 特性

  • 隱藏通信細節,提供了分佈式透明性
  • RPC 是瞬時同步通信
    RMI :遠程方法調用

4.4 面向消息的通信

面向消息的瞬時通信
1.套接字:是一種通信端點,包含 IP 地址和 port ,在一對端口之間可以進行消息傳遞。只支持簡單的 send 和 receive 原語,利用協議棧 (TCP/IP) 進行網絡通信,不適合專用協議。瞬時同步
2.MPI:適合進程間標準消息傳遞的並行程序設計平臺;最佳的可移植性
MPI 假定通信在一個已知進程組中, 每個組有 ID ,組內每個進程也有一個局部ID,(組 ID ,進 程 ID )對就可以唯一的確定消息來源或者目的地。
支持四種瞬時通信語義 (3,4,5,6)
支持一組消息傳遞原語
基於消息傳遞的並行程序執行模式:

  • SPMD 模式:單程序多數據流,初始複製多份程序代碼並獨立執行
  • MPMD 模式:多程序多數據流,初始啓動多個可執行代碼,

面向消息的持久通信
消息隊列系統

  • 面向消息的中間件(MOM)
  • 提供消息的中介存儲能力
  • 應用程序可以通過向指定隊列插入消息來實現通信。只保證送達,不保證送達的時間。
  • 需要給出目的消息隊列的名字(系統內唯一)
    消息如何送達
    隊列-網絡地址映射表
    消息如何解析
    message broker ,格式轉換
    實例: IBM MQSeries
  • 所有隊列由隊列管理器管理
  • 一對隊列管理器通過消息通道相連
    每個消息通道都有且只有一個與其對應的發送隊列, 通道兩端的 MCA 都啓動時,消息沿通道傳輸
  • 消息通道提供單向可靠連接
  • 消息通道兩端各自有一個消息通道代理MCA
  • 應用程序接口和隊列管理器可使用 RPC 通信
    消息如何傳遞
    消息中應包含有目標地址(接收消息的隊列管理器,目標隊列名字)
    指明本地發送隊列
    ( 發送隊列,目標隊列管理器 ) 表
    別名表:別名可以適應隊列管理器的變化

4.5 Data Stream

時間敏感的信息交換。如連續媒體播放傳送等。
數據流數據單元的序列,可以應用於離散或連續的媒體。如 TCP/IP 連接的面向字節的離散數據流,和麪向播放音頻文件的連續數據流;連續數據流關鍵是採用同步傳輸模式
傳輸模式

  • 異步傳輸模式:數據項逐個傳輸,無時間限制。
  • 同步傳輸模式:端到端最大延遲
  • 等時傳輸模式:須按時傳輸,端到端延遲有上限和下限約束
    簡單流;複雜流,各子流之間是時間敏感的
    確保 QoS服務質量
    時間敏感的需求
  • 數據傳輸所需要的比特率;
  • 創建會話的最大延時;
  • 端到端的最大延時;
  • 最大延時抖動;
  • 最大往返延時;
    QoS控制方法
  • 資源預留:帶寬,緩衝區, CPU 資源
  • 緩存(消除延時抖動)
  • 糾錯
  • 交錯傳輸
  • 隊列控制
    流同步
    連續流保持同步,同步建立在流的數據單元層次上 ,只要保證兩個流的數據單元同步;在發送方同步

5 命名系統

5.1 名稱、標識符、訪問點、地址

命名服務將名字和計算機中的一個對象(可以是遠程)相關聯,通過名字可以方便地找到對應的對象

  • 一個名字標識一個對象,它們之間的聯結叫做綁定
  • 實體訪問點:特殊的實體,是訪問實體的接口
    (1)可以有多個訪問點
    (2)實體可以改變訪問點
    (3)訪問點可賦給另一個實體
  • 地址:實體訪問點的名字,指向實體的一個訪問點
  • 位置獨立性:實體的名字與他的地址無關
  • 真正的標識符是具有以下屬性的名字
    (1)一個標識符最多引用一個實體
    (2)每個實體最多由一個標識符引用
    (3)一個標識符始終引用同一個實體
  • 地址(機器可讀的名字)和標識符(用戶友好的名字)
    命名與實體定位
    在這裏插入圖片描述

5.2 無層次命名

(1)廣播、轉發指針
廣播:將包含實體所用標識符的消息廣播到每個結點,擁有該標識符的結點返回相應的地址
網絡規模變大時,廣播很低效;網絡帶寬被請求數據包浪費;很多主機接收到它無法回答的請求,可轉換成多播,只有符合條件的一組主機纔會接收到請求。
實體遷移如何定位:轉發指針,每個轉發指針都以 (客戶存根、服務器存根)對的形式實現,當實體移動時在原位置留下指針(客戶存根),指向新位置(安裝對應服務器存根)。
優點:很簡便,一旦找到實體之後,客戶就可以順着轉發指針形成的鏈來查找實體的當前地址。
缺點:如果不採取特殊措施,鏈會很長,以致定位開銷很大;鏈很脆弱,易斷開。
重定向轉發指針: 存儲shortcut
鏈斷開怎麼辦: 讓創建對象的機器始終保留對象當前位置的引用
(2)基於宿主位置
持續跟蹤實體的當前位置,可以使用特殊的技術來預防網絡故障或進程失效。缺點:宿主需始終存在,使用了固定的宿主位置,地域擴展性差;解決方法:在傳統的命名服務中註冊宿主位置,客戶查找宿主位置
(3)分佈式散列表 Chord系統(從0開始標號)
node被組織成邏輯環,被賦予隨機的m位標識符,entity被賦予一個特定的m位鍵值,含有鍵值K的實體位於含有最小標識符ID且ID≥K的節點上,每個結點n只知道其後繼節點successor(n) (實際存在的).
finger table:指狀表,提高效率,結點知道successor(n + 2^( i-1)),i=1…m(實際存在的)
基於指狀表的查找:查找 k ,結點 p 將請求轉發給指狀表中索引比 k 小的最大節點 (ppt29習題)
(結點的加入與離開,需要更新指狀表)
(4)分層方法
在這裏插入圖片描述
最底層的域稱爲葉域
每個域 D 都有關聯的目錄結點 dir(D) ,目錄結點會跟蹤域中的實體
根目錄結點包含全部實體位置記錄
客戶如何定位一個實體:從最小的域開始,自底向上查找,找到記錄後,自頂向下定位(到葉域)
通過緩存引用來提高定位效率
根節點要存儲所有實體的位置記錄和指向低層目錄結點的指針,處理查找和更新請求,會成爲瓶頸。可將根結點分成多個子結點,在定位服務覆蓋網上均勻的放置子結點

5.3 結構化命名

名稱空間
在這裏插入圖片描述
如果路徑名中的第一個結點是命名圖的根,那麼該路徑稱爲絕對路徑名,否則,稱爲相對路徑名。
硬鏈接 vs 軟鏈接
Mount兩種方法

  • 將外部空間安裝到分佈式系統需要-訪問協議,服務器,被安裝點
  • 增加新的 Root 結點
    名稱空間邏輯上可分爲三層
    全局層:良好的可用性 ,變化少,客戶可緩存信息提高性能
    行政層:類似全局層
    管理層:要求性能很好,經常更新 ,通常不採用客戶端緩存
    zone:一個名字服務器管轄的區域
    名稱解析
    (1)迭代名稱解析
    在這裏插入圖片描述
    (2)遞歸名稱解析
    在這裏插入圖片描述
    優點:更有效的緩存結果、通信開銷較小
    例子:DNS,主機名的書寫方法:葉節點名. 三級域名. 二級域名. 頂級域名

5.4基於屬性的命名

在分佈式系統中,最常用的一種是用(值,屬性)來描述實體,通常稱爲基於屬性命名。基於屬性的命名系統又稱爲目錄服務。類似數據庫查詢

6 同步

6.1時鐘同步

  • 物理時鐘:實際測量的時間(例如:平均太陽日、原子時鐘)
    物理時鐘校準:UTC接收器;Cristian算法: s 在 時 刻 t 傳回給p,來回時間Tround=min+Δ1+Δ2+min ,用t+Tround/2來估計當前時間,時間服務器是被動的;Berkeley UNIX 中時間服務器主動定期地詢問每臺機器的時間,計算出平均值並告訴所有的機器進行調整。
  • 邏輯時鐘:對於某一類算法,重要的是內部各時鐘的一致
  • Lamport 邏輯時鐘
    用因果關係來描述進程事件發生的順序
    (1)事件定序關係HB:對於事件e1、e2
    ①如果存在進程p,p包含e1、e2, 且e1在e2前發生,則 e1–> e2
    ②如果存在消息m,e1爲Send(m),e2爲Receive(m),則e1–> e2
    ③如果e1–> e2&e2–>e3,則e1–>e3
    ④如果e1–>e2,e2–>e1均不成立,則e1和e2可以併發:e1||e2
    (2)一種邏輯時鐘的定義:設每個進程p有一個邏輯時鐘計數Tp,則:
    ①在進程p的一個事件發生前,執行Tp=Tp+1
    ②當進程p發送消息m時,在m上攜帶時鐘值:(m, Tp)
    ③當進程q接收消息(m, Tp)時,取Tq=max{Tq,Tp}
    (3)邏輯時鐘排序與HB的關係
    ①如果p–>q,則Tp<Tq
    ②如果Tp<Tq,則p–>q不一定成立:可能有p||q
    4)邏輯時鐘與事件全排序
    用序對(Tp,pa)來進行定序。其中Tp爲時間的邏輯時鐘值,pa爲進程p的優先級,稱之爲時間戳。邏輯時鐘值相同時,優先級高者優先。
    如果事件 a 、b 存在因果關係, a 爲 因, b 爲果,那麼 C(a)<C(b) ,但反過來,知道 C(a)<C(b) 並不能知道 a 、 b 事件的關係。標量時鐘無法識別時鐘的推進是局部事件引起 , 還是包文交換引起的。因此引入向量時鐘

6.2 向量時鐘

用向量時鐘捕獲因果關係 。
事件 a 的向量時鐘 VC(a) ,對於某一事件 b ,有 VC(a)<VC(b) ,則 a 在因果關係上先於 b
每個進程Pi和一個時間向量VCi[1,2,…,n]相關聯,其中:
(1)向量元素VCi[i]描述進程Pi自身的邏輯時鐘進展情況.
(2)向量元素VCi[j]表示進程Pi所知道的關於進程Pj的邏輯時鐘進展情況.
(3)向量VCi[1,2,…,n]組成進程Pi對於邏輯全局時間的局部視圖.
進程Pi向量時鐘修改規則如下:
(1)發生一個事件之前,Pi更新VCi[i]:
VCi[i]:= VCi[i] + d (d>0);
(2)每個報文帶有發送時的向量時鐘,當收到一個帶時間戳的報文(m, VCj,j)時,Pi更新VCi:
VCi[k]:=max(VCi[k], VCj[k]) 1<= k <=n;
VCi[i]:=VCi[i] + d (d>0);
使用向量邏輯時鐘方法確定的各事件的邏輯時間 ,知道時間前進的原因
因果有序多播
使用向量時鐘,確保所有先於某個消息的所有消息被接收後才傳送這個消息。時鐘只在接收和發送消息時更新,消息正確遞交的條件:
在這裏插入圖片描述

6.3 分佈式互斥算法

當一個進程使用某個共享資源時,其他進程進程不允許對這個資源操作。
臨界區:對共享資源進行操作的程序段
1.集中式算法
每一個資源有一個協調者進程管理,保證了互斥,無飢餓問題,單個協作者會成爲性能瓶頸。
①每完成一次臨界區操作,要發Request、Reply、Release三個消息
②當協調者進程故障,需安排新進程代替:選一個進程,通知其它進程,建立相應隊列,恢復工作
2、非集中式
將單個協作者變爲多個協作者,採用投票的方式,某個進程要訪問資源,需要從m>n/2個協作者中獲得多數投票
通信量:3mk個消息
優點:當某個協作者崩潰時,能快速恢復
缺點:重置將使協作者忘記之前的授權許可。且當多個進程要訪問同一資源,可能出現都得不到足夠投票,發生飢餓或死鎖
3、分佈式
①Lamport算法
基本思想:要想獲得某一資源的使用權,必須徵得所有結點的同意;衝突時,按“定序”進行處理
主要數據結構:每個進程擁有一個全局請求隊列
算法思路:
(1)進程p進入臨界區時,向系統中所有進程發送Request(Tp, p),並將此請求放入自己的請求隊列
(2)當進程q接到此消息,將其放入自己的請求隊列,並返回一個帶有時間戳的Reply(Tq):[Tq>=Tp+1];
(3)當Request(Tp, p)按“定序”規則排在p的隊列首位時,p進入臨界區,否則p等待
(4)當p退出臨界區時,從自己的隊列中去掉Request(Tp, p),並向其它進程發出Release
(5)當q接到Release後,將相應的Request(Tp, p)從自己的隊列中刪除。然後看自己是否正在等待此臨界區:
a)如果是,則轉3;
b)如果不是,不做任何進一步的工作。
Lamport算法討論:
(1)每完成一次臨界區操作,要發Request、Reply、Release消息各n-1個(3(n-1))
(2)時間戳及全排序保證不死鎖
②Lamport算法的改進
改進思路:
(1)Request消息:p必須讓系統中的其它n-1個進程知道它的需求,這n-1個消息時必須的
(2)Reply消息:
a.如果進程q未在臨界區內,且現在也不打算進入臨界區,則同意p的進入請求,向p發Reply
b.如果進程q在臨界區內,則不向p發Reply,並將此Request掛入請求隊列
c.如果進程q正打算進入臨界區,則看Tp<Tq是否成立:
i. 成立,同意p的進入請求,向p發Reply; ii. 不成立,則將此Request掛入相應隊列,此時不發Reply
(3)按照發Reply消息的原則,當未發Reply的進程使用完臨界區後,再向原來發Request的進程發送Release消息
發送的Reply和Release消息的總數爲n-1。只用2(n-1)條消 息就可以完成一次對臨界區的操作
改進算法討論:
(1)實現互斥,沒有飢餓和死鎖,需要2(n-1)個消息,不存在單個故障點
(2)多個故障點
(3)新來者問題——參與此活動的進程都需要知道彼此的名字,當一進程新參與時,要完成相應的工作
(4)故障問題——某參與者故障時,會使算法失效,這可用監測方法解決
(5)改進算法最適用於進程數目較少且成員不發生變化的情況
4、令牌傳遞算法
① 基於環結構的令牌傳遞算法
單向環(令牌右傳):沒有進程要進入臨界區時,令牌繞環高速傳遞。單向環—被動等待
雙向環—請求驅動 ( 請求右傳 , 令牌左傳 )
②基於非環結構的令牌傳遞算法
全局n維令牌向量VT=(vt1,vt2,…vtn), vti 爲對應的進程已獲得服務的Request 次數
每個進程維持一個請求隊列
令牌不用一直傳送,只在被申請時才向申請者發送;令牌丟失問題;隊列維護和令牌向量的協調工作。
在這裏插入圖片描述

6.4 選舉算法

如果協調者發生故障,需選擇另一個副本代替其運行,這種選舉過程稱選舉算法。選舉算法總是找擁有最大號碼的進程
1、欺負算法:高優先級進程做協調者
2、基於環結構的算法 (單向右傳,建立活躍表 ):構造一個包含自身進程號的選舉消息發給它的下一個有效後繼者,並將自己的進程號加入到消息表。消息繞環一週,在活躍表中選最高者爲協調者。
3、無線環境中的選舉算法:生成樹

7 複製和一致性

7.1 複製的原因

  • 可靠性(防止單點失效)
  • 性能(擴展性)
    將數據的副本放置在處理它們的進程附近以減少訪問時間,解決可伸縮性問題

7.2 以數據爲中心的一致性模型

一致性模型實質上是進程和數據存儲之間的一個約定。即,如果進程同意遵守某些規則,那麼數據存儲將正常運行。正常情況下,一個進程在一個數據項上執行讀操作時,它期待該操作返回的是該數據在其最後一次寫操作之後的結果
持續一致性模型

  • 範圍:數值偏差(未收到其他副本的更新數,權重-已提交值與因未收到其他副本更新產生的最大差分)、副本之間新舊程度的偏差,順序偏差(副本的暫時更新操作)
    一致性單元(conit):受控的數據集
    一致性單元粒度:
    粗粒度:任一個更新操作都導致更新傳播
    細粒度:當一個數據更新時,另一個數據無需更新
    在這裏插入圖片描述在這裏插入圖片描述
    一致性分類
  • 嚴格一致性:寫操作在任一時刻對所有進程都是可見的,一旦存儲器中的值改變,後讀出的都是新更改值。 反之,無論後面的寫操作有多快,前面的讀操作仍應是原來的值。(不現實)
  • 順序一致性:任何有效的交錯都是可以接受的行爲,但所有進程必須看到相同的訪問操作次序。每個進程的操作都是符合程序內部的順序。
    在這裏插入圖片描述
  • 線性一致性:滿足順序一至性約束,同時滿足時間戳的順序
  • 因果一致性:所有進程必須以相同的順序看到具有因果關係的寫操作
    在這裏插入圖片描述
  • FIFO一致性:一個進程的寫操作被其它進程以相同的順序接收到,但不同進程的寫操作在不同進程看來次序可以是不同的
  • 弱一致性:同步變量S僅有一個相關操作,即同步操作,該操作同步數據存儲的所有副本。弱一致性模型要求滿足以下幾點:
    ①對同步變量的訪問是順序一致性的(即所有進程都以相同的順序看到同步變量執行的所有操作)
    ②在所有先前的寫操作完成之前,不能訪問同步變量(即要求在所有副本上完成所有的寫操作)
    ③在先前所有同步變量的訪問完成前,不能訪問(讀或寫)數據(即保證所得到的數據是最新的)
    對一組操作的一致性約束, 不是單獨的讀或寫。以簇的形式訪問共享變量時,模型很有用。
    在這裏插入圖片描述
  • 釋放一致性:弱一致性存在的問題,即當訪問同步變量時,存儲器並不知道這是因爲進程已完成對共享變量的寫操作還是要開始讀共享變量。若能夠區分進入還是離開臨界區的話,應用起來會更有效。因此,引入釋放一致性,需要提供兩種操作:
    獲取(acquire)—— 訪問用於通知存儲器系統臨界區已就緒。
    釋放 (release)——訪問表明臨界區剛退出。
    遵守以下規定:
    ①在訪問共享變量前,進程所有先前的獲取訪問都必須成功地完成;
    ②在允許釋放訪問前,進程先前的所有讀寫操作都必須結束;
    ③獲取訪問和釋放訪問必須是FIFO一致的。
  • 入口一致性:不用在整個共享數據上,而是每個共享數據都有一個關聯的同步變量;使得多個包含不同共享數據的臨界區可以同時執行,從而增加系統的並行度,付出的代價是多個同步變量的額外開銷和複雜性。
    標準:
    ①只有某一進程的保護共享變量全部被更新以後,該進程才允許執行同步變量的獲取訪問;
    ②在一進程以互斥模式訪問該進程的同步變量之前,不允許其它進程持有此同步變量 ;
    ③在結束互斥模式下對一個同步變量的訪問後,任意其它進程必須與該變量的擁有者覈查,才能試圖以非互斥模式訪問該同步變量。
    一致性模型總結
    在這裏插入圖片描述

7.3 以客戶爲中心的一致性模型

保證一個客戶對數據存儲的訪問是一致的、不考慮不同客戶之間的併發訪問
1、最終一致性:如果很長時間不發生更新操作,則所有的副本將逐漸變爲一致的
2、假設:
①每個數據項X有一個擁有者,只有擁有者可以修改X
②客戶的讀寫操作在本地副本上進行
③更新最終將傳播給其他副本上
3、記號
①Xi[t]:表示t時刻本地副本Li中數據項x的版本
②WS(Xi[t]):產生Xi[t]的所有寫操作的集合
③WS(Xi[t1];Xj[t2]):WS(Xi[t1])中的寫操作在t2時刻在副本Lj上執行
4、一致性模型
單個進程在兩個不同副本上執行操作

  • 單調讀一致性:如果一個進程讀取數據項X的值,那麼該進程對X執行的任何後續讀操作將總是得到第一次讀取的那個值或更新的值(讀之前,寫都要傳過來)
    在這裏插入圖片描述

  • 單調寫一致性:一個進程對數據項X執行的寫操作必須在該進程對X執行任何後續寫操作之前完成(寫之前,寫都要傳過來)

  • 讀寫一致性:一個進程對數據項X執行一次寫操作的結果總是會被該進程對X執行的後續讀操作看見(read your write)

  • 寫讀一致性: 同一進程對數據項X 執行的讀操作之後的寫操作,保證發生在於 X 讀取值相同或比其更新的值上(write follow read)

7.4 複製管理

1、副本服務器的放置問題:從N個位置中選出K個最優位置
基於距離的方法
最優:使得服務器與其客戶之間的平均距離最小
距離:延遲、帶寬等指標來衡量
基於單元的方法
劃分成多個單元
選擇 K 個密度最大的單元放置副本服務器
2、副本類型
永久副本:構成分佈式數據存儲的初始集合;靜態的,固定的;數量較少
服務器發起的副本:提高性能。當負載突然發生變化時,減少服務器負擔,減少客戶的通信開銷
動態複製算法:服務器Q上的F資源的-訪問計數cnt,刪除計數del,複製計數rep,判斷是否刪除、遷移或複製到其他服務器
cnt(Q ,F ) < del(Q ,F )-remove;del(Q ,F ) < cnt( P,F ) < rep(Q ,F )-migrate;cnt(Q ,F ) > rep(Q ,F ) -replicate
客戶啓動的副本,也稱爲客戶高速緩存。用於改善數據的訪問時間,適用於大部分操作是讀操作時
高速緩存的放置:放置在客戶所在的機器、放在客戶所在地局域網上的某個共享的機器上、在廣域網的某些特定點放置高速緩存服務器。
3、更新的傳播
(1)只傳播更新的通知
數據量少,佔用很少網絡帶寬,適用於讀/寫比較低時
(2)傳送更新數據
數據量多,佔用較多網絡帶寬,適用於讀/寫比較高時
(3)傳送更新操作
佔用較少帶寬,但是要求副本有較高處理能力
4、推協議和拉協議
(1)推協議
①不需要其他副本請求,更新就傳播給副本
②通常用於永久性副本和服務器啓動的副本
③適用於讀寫比非常高的情況
④保持較高的一致性
(2)拉協議
①由客戶請求服務器發送更新
②通常用於客戶高速緩存
③適用於讀寫比比較低的情況
④當cache沒有命中時,響應時間較長

7.5 一致性協議

1、基於主備份的協議
①每個數據項都有一個主備份,由主備份負責管理在數據項x上的寫操作
②實現了順序一致性
③分爲遠程寫協議和本地寫協議

  • 遠程寫協議
    所有操作都轉發給單個固定的遠程服務器
    所有寫操作轉發給單個固定的遠程服務器,讀操作在本地副本執行
  • 本地寫協議
    ①主副本在要執行寫操作的進程之間遷移

2、複製寫協議:寫操作可以在多個副本上執行
(1)主動複製協議
每個副本有一個相關聯的進程,將所有更新操作發給各個副本關聯的進程執行相應的更新操作
問題:更新順序問題,實現順序一致性
①全序多播:Lamport時間戳
②中心協調器(定序器):給每個操作分配一個唯一的序列號,轉發給各個副本
(2)基於多數表決的複製寫協議:多個副本同時執行寫操作
基本算法
設有N個副本
設置讀團體Nr,寫團體Nw
要求:①Nr+Nw>N ②Nw>N/2(①防止讀寫操作衝突②防止讀讀操作衝突)

3、實現以客戶爲中心的一致性
每個寫操作 W 都被分配一個全局唯一的標 識符 。對於每個客戶,跟蹤兩個操作集。 讀操作集是由客戶所執行的讀操作相關的寫操作組成的 。寫操作集由客戶執行的寫操作的標識符組成。
單調讀:執行讀操作時,服務器獲得客戶的讀操作集,確保寫操作已在本地執行或轉發,執行讀操作,與讀操作相關的寫操作以及新的寫操作加入客戶的讀操作集
單調寫:執行寫操作時 ,服務器獲得客戶的寫操作集 ,寫操作按正確順序執行, 執行寫操作,將新的寫操作加入寫操作集
讀寫一致性:客戶執行讀操作之前,確保寫操作集的所有操作已經執行,執行讀操作,將寫操作加入讀操作集
寫讀一致性:在寫操作之前,先根據客戶的讀操作集裏的寫操作來更新服務器,執行寫操作,將寫操作和讀操作集中的寫操作加入寫操作集

8 容錯性

8.1 基本概念

1、概念
缺陷(Defect):系統中存在的某種破壞正常運行能力的問題、錯誤,或者隱藏的功能缺陷。
故障(Fault):是造成錯誤的原因。
失效(Failure):系統不能兌現它的承諾。
關係:缺陷 ->故障-> 失效
分佈式系統容許部分失效,並可以從部分失效中自動恢復,不會嚴重影響系統整體性能
2、容錯與系統可靠性相關。可靠性包括:
(1)可用性:系統準備好可以立即使用
(2)可靠性:給定的環境和時間區間連續提供期望服務的能力
(3)安全性:系統臨時失效不發生災難性事故
(4)可維護性:恢復失效系統的難易
3、故障類型
(1)暫時故障:只發生一次,然後就消失了,即時重複操作也不會發生。如果傳輸超時重發。
(2)間歇故障:錯誤出現後,消失不見,然後再次發生,如此反覆。連接器接觸不良。
(3)持久故障:直到故障組件被修復之前持續存在的故障。芯片燃燒。
4、處理機故障分類
(1)失敗緘默(Fail_silent)故障
失效的處理機只是停止運行,對接下來的輸入不作反應也不產生進一步的輸出。
(2)拜占庭(Byzantine)故障(隨意性故障)
出錯的處理機繼續運行,產生錯誤的結果,並可能和其它出錯的處理機一起“惡意”的工作,給人一種工作正常的假象。
在這裏插入圖片描述
5、冗餘
通過冗餘來容錯,隱藏故障的發生。處理失效的關鍵技術
(1)信息冗餘:增加額外數據位以使出錯的數據完全恢復。例如,海明碼可用於附加在傳輸數據上,以使數據能從傳輸線的噪音中恢復。
(2)時間冗餘:動作執行後,必要時可再次執行。例如:原子事務處理,若一個事務處理失敗,它可無負作用地再被執行(對於暫時性和間斷性錯誤特別有用)。
(3)物理冗餘:使用額外部件或進程。物理冗餘可以在硬件上也可以在軟件上。例如,使用冗餘的處理機,冗餘的進程等。

8.2進程恢復

1、進程容錯
冗餘:進程組
當有消息發送到進程組時,組中的所有成員都接收該消息。
2、平等組與等級組
(1)平等組
平等組是對稱的,所有決定共同做出沒有單獨失敗點
做出決定比較複雜,需要表決,開銷和延遲
(2)等級組
組中有一個協調者,協調者做決定,存在單獨失敗點
3、進程組的管理方式
(1)使用組服務器
(2)分佈式管理,採用可靠多播
正常退出,向所有成員發送再見消息;發生故障時,組成員退出:
(1)fail-stop類型:發送Goodbye信息
(2)fail-silent類型:需其他成員發現
消息同步:
(1)加入組時:立刻收到所有消息
(2)退出組時:不在收到任何消息
4、故障掩蓋和複製進程
通過複製進程並將他們組織在一個組中。用一個容錯的進程組來取代一個脆弱的進程。
如何複製進程?
(1)基於主進程的協議:採用等級組方式,一個主進程協調所有寫操作
(2)複製的寫協議:組成平等組,可採用多數表決(團體)方式
5、進程需要複製的程度
取決於想要達到的容錯量,k容錯——可在k個部件出故障時仍正常工作。

  • fail_silent型:k+1個冗餘部件可滿足k容錯的要求。
  • Byzantine型:至少需2k+1個處理機才能達到k容錯。最壞情況下,k個失效處理機偶然(或甚至有意)產生同樣的應答。則剩下的k+1個未出錯的也將產生相同的應答,因此客戶或表決器只要相信大多數的應答就可得到正確的結果。

6、分佈式協同一致算法的目標是使所有無故 障進程對待某些問題的意見達到一致,並在有限的步 驟內進行處理達成一致,需要考慮:消息傳遞是否可靠;進程會崩潰嗎;系統是同步還是異步
可取得一致的三種情況:
(1)處理機同步方式、通信延時有限
處理機可用超時檢測機制,確定其他失敗進程
(2)消息有序,廣播式傳輸
每個處理機原子式廣播一個初始值,其他處理按照次序接收,能夠同意誰是第一個發送的。
(3)處理機同步,消息有序
7、拜占庭協定問題
在這裏插入圖片描述
結論:如果要想容忍m個判國者,必須保證總的將軍的個數大於3m,即無故障進程需要超過總數的 2/3,才能達成協定

8.3 可靠的組間通信

1、可靠的點到點通信
通過使用可靠的傳輸協議來掩蓋某些故障。(TCP建立點到點的可靠通信)
(1)遺漏性故障:通過TCP確認和重傳可以掩蓋
(2)崩潰性故障:TCP無法掩蓋,通常會拋出一個異常信號,通知客戶進程
2、可靠的RPC通信
RPC系統中發生的5種失敗形式:
(1)客戶不能定位服務器;(讓錯誤拋出一個異常)
(2)客戶到服務器的請求信息丟失;(返回應答或確認之前定時器超時,那麼就重新發送消息)
(3)服務器在收到請求之後崩潰;(區分執行操作前崩潰和執行操作後崩潰)
區分這兩種情況的3種方法,但是都不大行,吸引人的方法應該具有恰好一次的語義
①在服務器重啓之前等待並再次嘗試操作。(至少一次語義)
②立刻放棄並報告失敗。(最多一次語義)
③什麼都不保證。
(4)從服務器到客戶的響應消息丟失;(每個請求編號,防止重複執行)
(5)客戶在發送請求之後崩潰;
①日誌文件,保存崩潰前的操作;②再生,把時間分爲順序編號的時期。
3、可靠的組間通信(多播服務):確保消息被傳送到進程組中的所有成員。
區分不同情況:
(1)有故障進程時,保證所有正常組成員都接收到消息
(2)無故障進程時,保證消息被所有當前組成員接收(假設沒有進程加入或離開組)
簡單可靠多播策略:不支持有很多接收方,因爲每個接收方都要返回消息,產生反饋擁塞
解決:接收方只在消息丟失時才返回一個反饋,減少反饋的規模,但不能保證永遠不會發生反饋擁塞(如果所有接收方都沒有接收到消息);發送方不得不將所有消息保留在歷史緩存區中
無層次反饋抑制:支持可擴展,僅當發現收到的信息丟失時纔回應,隨機延時迴應,抑制其他進程同時迴應
分層次的反饋控制:本地協作者把消息轉發給他的孩子然後再處理重發請求
原子多播:確保消息要麼發送給所有成員,要麼一個也不發送
虛同步:只保證應用程序看到的結果是同步的
區分消息接收消息遞交
分佈式系統中的同步形式:

  1. 同步系統----時間上一致;
  2. 鬆弛同步----時間上延遲, 順序一致;
  3. 虛同步—順序不保證。
    組視圖:在發送一個消息時,屬於該組的所有進程的名單;
    視圖變更:當有進程加入或退出組時。
    虛同步組播不保證接收者收到報文的順序,只保證在發送報文 m的進程失效的時候, G中的其它進程要麼都收到報文m, 要麼 都忽略報文m
    ④多播排序的四種方法:
    (1)不排序的多播:是一種虛擬同步多播,不保證接收到的消息的遞交次序是相同的
    (2)FIFO順序的多播:從同一發送者進程接收到消息的遞交次序和其發送次序一致
    (3)按因果關係排序多播:具有因果關係的消息的遞交次序與發送次序一致,無論消息是不是同一個發送者發送的。可以使用時間戳向量實現。
    (4)全序多播:對所有組員的消息遞交次序相同的。原子多播就是提供全序遞交的虛擬同步可靠多播。
    虛擬同步可靠多播總結
    在這裏插入圖片描述
    ⑤如何實現虛擬同步
    保證發送到視圖G的所有消息在G發生改變之前被傳送到G中的所有正常進程。解決:可以讓G中的每個進程在確認G中的所有進程接收到m之前保留m。如果G中的所有進程都接收到m,那麼m就被稱爲是穩定的,穩定的消息只允許傳送一次。不穩定的消息在G改變時,需廣播出去,接收反饋,變成穩定消息。
    在這裏插入圖片描述

8.4分佈式提交

1、兩階段提交協議可以實現分佈式環境下的事務特性,但是可能導致事務阻塞。
(1)協作者先向所有的參與者發送一個Vote-request消息
(2)參與者收到消息後,根據自己的情況返回同意提交Vote-Commit或拒絕Vote-Abort消息
(3)協作者收集來自參與者的所有投票。如果都同意則協調者向所有參與者發送Global-Commit消息。如果有一個參與者返回拒絕,則協作者決定取消並多播一個Global-Abort消息
(4)每個參與者都等待協作者最後發來的消息,根據消息執行相應的操作,提交或取消事務。
2、事務阻塞
(1)參與者可能在INIT狀態阻塞
超時沒有收到投票請求消息,參與者在本地終止事務
(2)協作者可能在WAIT狀態阻塞
超時沒有收到所有參與者的表決,協調者做出中止表決決定,並向所有參與者發消息
(3)參與者可能在READY狀態阻塞(不好解決)
參與者不能簡單做出中止事務的決定
3、參與者 P 處於 Ready 狀態,與另一個參與者 Q 通信後,可能採取的動作
在這裏插入圖片描述
4、三階段提交協議:在有故障時,避免進程阻塞,
協作者多發【準備提交消息】
實現比較複雜,通信次數也比較多,實際應用不多。

8.5 恢復

1、錯誤恢復的兩種形式:回退恢復和前向恢復
(1)回退恢復:主要問題是要將系統從當前的錯誤狀態回到先前的正確狀態。必須定時記錄系統的狀態,即設置一個檢查點。
Checkpointing 設置(包括存儲)和更新
1 存儲:
(1) 每一個Checkpointing被組播到每一個備份模塊.
(2) 每一個Checkpointing被存儲在它的本地穩定存儲
2 更新:
當進程正確地從一箇舊Checkpointing運行到一個新的 Checkpointing時,舊的Checkpointing要被新的Checkpointing 更新.
用2個庫實現原子更新
設A, B兩個庫存放Checkpointing,A庫更新完後,再更新B庫。在每一個庫更新前後都要寫入一個時間戳。
TA1、TA2分別表示A庫更新前後的時間戳;
TB1、TB2分別表示B庫更新前後的時間戳;
TA1、TA2、TB1和TB2初始值相同(假設爲0)。
更新過程:
①TA1=TA1+1;②A庫更新;③TA2=TA2+1;
④TB1=TB1+1;⑤B庫更新;⑥TB1=TB2+1;
4種可能情況:
if TA1=TA2=TB1=TB2 then 正常;
if TA1>TA2=TB1=TB2 then copy B to A; /*A更新中失效
if TA1=TA2>TB1=TB2 then copy A to B; /*A更新結束,B更新前失效
if TA1=TA2=TB1>TB2 then copy A to B; /*B更新中失效
checkpointing設置問題
設置不恰當導致:報文丟失(有發無收),孤兒報文(有收無發),全局檢查點狀態是強一致的指沒有上述兩種類型的報文
兩種設置方式
Independent -各進程週期性地、獨立地保存自己的運行狀態,不相互協商(狀態不一致),但是在恢復時需要相互協商。可能產生多米諾效應
Coordinated -建立 Checkpointing 時協商,使其滿足一致性狀態,恢復時不需要協商,Sync-and-Stop ( SNS )算法
(2)前向恢復:在這種情況下,當系統進入錯誤狀態時,嘗試從可以繼續執行的某點開始把系統帶入一個正確的新狀態。前向錯誤恢復機制的關鍵:必須預先知道會發生什麼

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章