中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

大廠面試必知必會:圖解分布式事務實現原理

發布時間:2020-07-20 08:08:44 來源:網絡 閱讀:717 作者:Java_老男孩 欄目:編程語言

問題場景

大廠面試必知必會:圖解分布式事務實現原理

大廠面試必知必會:圖解分布式事務實現原理

大廠面試必知必會:圖解分布式事務實現原理大廠面試必知必會:圖解分布式事務實現原理

大廠面試必知必會:圖解分布式事務實現原理

什么是事務?

大廠面試必知必會:圖解分布式事務實現原理

事務是數據庫從一個穩定狀態變遷到另一個穩定狀態的保證,具備 ACID 這 4 個特性:

  • 原子性(Atomicity):一個事務中的所有操作,要么全部完成,要么全部不完成,不會結束在中間某個環節。事務在執行過程中發生錯誤,會被回滾到事務開始前的狀態。

  • 一致性(Consistency):在事務開始之前和事務結束以后,數據庫的完整性限制沒有被破壞。

  • 隔離性(Isolation):兩個事務的執行是互不干擾的,兩個事務時間不會互相影響。

  • 持久性(Durability):在事務完成以后,該事務對數據庫所作的更改便持久地保存在數據庫之中,并且是完全的。

例如應用程序需要更新多條相關數據時就需要進行事務處理。

什么是分布式事務?

當遇到復雜業務調用時,可能會出現跨庫多資源調用(一個事務管理器,多個資源)/多服務調用(多個事務管理器,多個資源),期望全部成功或失敗回滾,這就是分布式事務,用以保證“操作多個隔離資源的數據一致性”。

大廠面試必知必會:圖解分布式事務實現原理

分布式事務與 XA 規范

分布式事務是指會涉及到操作多個數據庫的事務,同樣必須保證 ACID。其就是將對同一庫事務的概念擴大到了對多個庫的事務:對同一庫的 SQL 操作對應了分布式事務中對一個庫的事務。

X/Open XA 定義了分布式事務處理的規范,并由數據庫廠商在驅動層面進行實現。XA 規范的基礎是兩階段提交協議,并定義了分布式事務處理所涉及的角色:

應用程序(AP)
事務管理器(TM)
資源管理器(RM)
通信資源管理器(CRM)

常見的事務管理器( TM )是交易中間件,常見的資源管理器( RM )是數據庫,常見的通信資源管理器( CRM )是消息中間件。

可以這樣認為,事務管理器即事務處理中間件(分布式事務處理系統);資源管理器即各個數據庫。

兩階段提交協議

大廠面試必知必會:圖解分布式事務實現原理

兩階段提交協議(Two-phase commit protocol, 2PC)將一次分布式事務處理劃分為兩個階段:預提交階段(也稱為準備階段或投票階段),提交階段。

1 預提交階段

這是兩階段提交協議的第一個階段,分布式事務處理系統咨詢各個資源管理器是否可以提交本地事務,各個資源管理器會把這個咨詢過程寫入日志,以便進行回滾或提交。

當一個數據庫接收到咨詢后,它會將需要執行的操作寫入日志,禁止其他寫入操作(鎖定資源)。

如果分布式事務中某數據庫預提交失敗或提交失敗,那該數據庫會根據日志進行自身的操作回滾,并解鎖。

2 提交階段

分布式事務處理系統對各個資源管理器下達提交/回滾的指令,使整個分布式事務結束。

當一個數據庫接受到提交/回滾指令時,它將根據第一階段的日志進行提交/回滾處理。

兩階段提交協議可以在數據庫層面通過驅動支持,也可以在應用框架中按照其原理進行設計實現。

兩階段提交協議(Two Phase Commitment Protocol)是分布式事務的基礎協議。

在此協議中,一個事務協調器(TM, transaction manager)協調多個資源管理器(RM, resource manager)的活動;在一階段所有資源管理器(RM)向事務管理器(TM)匯報自身活動狀態,在第二階段事務管理器(TM)根據各資源管理器(RM)匯報的狀態,來決定各RM是執行提交操作還是回滾操作;具體描述如下:

大廠面試必知必會:圖解分布式事務實現原理

  1. 應用程序向事務管理器(TM)提交請求,發起方分布式事務;

  2. 一階段,事務管理器(TM)聯絡所有資源管理器(RM),通知它們執行準備操作;

  3. 資源管理器(RM)返回準備成功,或者失敗的消息給TM(響應超時算作失敗);

  4. 二階段,如果所有RM均準備成功,TM會通知所有RM執行提交;如果任一RM準備失敗,TM會通知所有RM回滾;

通過事務管理器2階段協調資源管理器,使所有資源管理器的狀態最終都是一致的,要么全部提交,要么全部回滾。

2PC應用之XA

XA是X/Open組織提出的,定義了事務管理器與資源管理器之間通信的接口協議;XA協議由數據庫實現,目前支持XA協議的數據庫有Oracle、MySql、BD2等;

XA定義了一系列的接口:

  • xa_start: 啟動XA事務

  • xa_end: 結束XA事務

  • xa_prepare: 準備階段,XA事務預提交

  • xa_commit:提交XA事務

  • xa_rollback: 回滾XA事務

大廠面試必知必會:圖解分布式事務實現原理

一個數據庫實現XA協議之后,它就可以作為作為一個資源管理器參與到分布式事務中;

在一階段,事務管理器協調所有數據庫執行XA事務(xa_start、用戶SQL、xa_end),并完成XA事務預提交(xa_prepare);

在二階段,如果所有數據庫上XA事務預提交均成功,那么事務管理器協調所有數據庫提交XA事務(xa_commit);如果任一數據庫上XA是我預提交失敗,那么事務管理器會協調所有數據組回滾XA事務(xa_rollback);

分階段提交原理

分布式事物基本理論: 基本遵循CPA理論,采用柔性事物特征,軟狀態或者最終一致性特點保證分布式事物一致性問題。

分布式事務常見解決方案:

  1. 2PC兩段提交協議

  2. 3PC三段提交協議(彌補兩端提交協議缺點)

  3. TCC或者GTS(阿里)

  4. 消息中間件最終一致性

  5. 使用LCN解決分布式事物,理念“LCN并不生產事務,LCN只是本地事務的搬運工”。

兩階段提交(2PC)

兩階段提交又稱2PC,2PC是一個非常經典的強一致、中心化的原子提交協議

這里所說的中心化是指協議中有兩類節點:一個是中心化協調者節點(coordinator)和N個參與者節點(partcipant)。

兩個階段:第一階段:投票階段?和第二階段:提交/執行階段。

舉例?訂單服務A,需要調用?支付服務B?去支付,支付成功則處理購物訂單為待發貨狀態,否則就需要將購物訂單處理為失敗狀態。

那么看2PC階段是如何處理的

1、第一階段:投票階段

大廠面試必知必會:圖解分布式事務實現原理

image

第一階段主要分為3步

1)事務詢問

協調者?向所有的?參與者?發送事務預處理請求,稱之為Prepare,并開始等待各?參與者?的響應。

2)執行本地事務

各個?參與者?節點執行本地事務操作,但在執行完成后并不會真正提交數據庫本地事務,而是先向?協調者?報告說:“我這邊可以處理了/我這邊不能處理”。.

3)各參與者向協調者反饋事務詢問的響應

如果?參與者?成功執行了事務操作,那么就反饋給協調者?Yes?響應,表示事務可以執行,如果沒有?參與者?成功執行事務,那么就反饋給協調者?No?響應,表示事務不可以執行。

第一階段執行完后,會有兩種可能。1、所有都返回Yes. 2、有一個或者多個返回No。

2、第二階段:提交/執行階段(成功流程)

成功條件:所有參與者都返回Yes。

大廠面試必知必會:圖解分布式事務實現原理

第二階段主要分為兩步

1)所有的參與者反饋給協調者的信息都是Yes,那么就會執行事務提交

?協調者?向?所有參與者?節點發出Commit請求.

2)事務提交

?參與者?收到Commit請求之后,就會正式執行本地事務Commit操作,并在完成提交之后釋放整個事務執行期間占用的事務資源。

第二階段:提交/執行階段(異常流程)

異常條件:任何一個?參與者?向?協調者?反饋了?No?響應,或者等待超時之后,協調者尚未收到所有參與者的反饋響應。

大廠面試必知必會:圖解分布式事務實現原理

異常流程第二階段也分為兩步

1)發送回滾請求

?協調者?向所有參與者節點發出?RoollBack?請求.

2)事務回滾

?參與者?接收到RoollBack請求后,會回滾本地事務。

2PC缺點

通過上面的演示,很容易想到2pc所帶來的缺陷

1)性能問題

無論是在第一階段的過程中,還是在第二階段,所有的參與者資源和協調者資源都是被鎖住的,只有當所有節點準備完畢,事務?協調者?才會通知進行全局提交,

參與者?進行本地事務提交后才會釋放資源。這樣的過程會比較漫長,對性能影響比較大。

2)單節點故障

由于協調者的重要性,一旦?協調者?發生故障。參與者?會一直阻塞下去。尤其在第二階段,協調者?發生故障,那么所有的?參與者?還都處于

鎖定事務資源的狀態中,而無法繼續完成事務操作。(雖然協調者掛掉,可以重新選舉一個協調者,但是無法解決因為協調者宕機導致的參與者處于阻塞狀態的問題)

2PC出現單點問題的三種情況

(1)協調者正常,參與者宕機

由于?協調者?無法收集到所有?參與者?的反饋,會陷入阻塞情況。

?解決方案:引入超時機制,如果協調者在超過指定的時間還沒有收到參與者的反饋,事務就失敗,向所有節點發送終止事務請求。

(2)協調者宕機,參與者正常

無論處于哪個階段,由于協調者宕機,無法發送提交請求,所有處于執行了操作但是未提交狀態的參與者都會陷入阻塞情況.

?解決方案:引入協調者備份,同時協調者需記錄操作日志.當檢測到協調者宕機一段時間后,協調者備份取代協調者,并讀取操作日志,向所有參與者詢問狀態。

(3)協調者和參與者都宕機

  1. 發生在第一階段:因為第一階段,所有參與者都沒有真正執行commit,所以只需重新在剩余的參與者中重新選出一個協調者,新的協調者在重新執行第一階段和第二階段就可以了。

2)發生在第二階段 并且 掛了的參與者在掛掉之前沒有收到協調者的指令。也就是上面的第4步掛了,這是可能協調者還沒有發送第4步就掛了。這種情形下,新的協調者重新執行第一階段和第二階段操作。

3)發生在第二階段 并且 有部分參與者已經執行完commit操作。就好比這里訂單服務A和支付服務B都收到協調者?發送的commit信息,開始真正執行本地事務commit,但突發情況,Acommit成功,B確掛了。這個時候目前來講數據是不一致的。雖然這個時候可以再通過手段讓他和協調者通信,再想辦法把數據搞成一致的,但是,這段時間內他的數據狀態已經是不一致的了!2PC 無法解決這個問題。

三階段提交(3PC)

大廠面試必知必會:圖解分布式事務實現原理

三階段提交協議(3PC)主要是為了解決兩階段提交協議的阻塞問題,2pc存在的問題是當協作者崩潰時,參與者不能做出最后的選擇。因此參與者可能在協作者恢復之前保持阻塞。

三階段提交(Three-phase commit),是二階段提交(2PC)的改進版本。

與兩階段提交不同的是,三階段提交有兩個改動點。

1、 引入超時機制。同時在協調者和參與者中都引入超時機制。
2、在第一階段和第二階段中插入一個準備階段。保證了在最后提交階段之前各參與節點的狀態是一致的。

也就是說,除了引入超時機制之外,3PC把2PC的準備階段再次一分為二,這樣三階段提交就有

CanCommitPreCommitDoCommit

三個階段。

1、CanCommit階段

之前2PC的一階段是本地事務執行結束后,最后不Commit,等其它服務都執行結束并返回Yes,由協調者發生commit才真正執行commit。而這里的CanCommit指的是?嘗試獲取數據庫鎖?如果可以,就返回Yes。

大廠面試必知必會:圖解分布式事務實現原理

這階段主要分為2步

事務詢問?協調者?向?參與者?發送CanCommit請求。詢問是否可以執行事務提交操作。然后開始等待?參與者?的響應。
響應反饋?參與者?接到CanCommit請求之后,正常情況下,如果其自身認為可以順利執行事務,則返回Yes響應,并進入預備狀態。否則反饋No

2、PreCommit階段

在階段一中,如果所有的參與者都返回Yes的話,那么就會進入PreCommit階段進行事務預提交。這里的PreCommit階段?跟上面的第一階段是差不多的,只不過這里?協調者和參與者都引入了超時機制?(2PC中只有協調者可以超時,參與者沒有超時機制)。

3、DoCommit階段

這里跟2pc的階段二是差不多的。

總結

相比較2PC而言,3PC對于協調者(Coordinator)和參與者(Partcipant)都設置了超時時間,而2PC只有協調者才擁有超時機制。這解決了一個什么問題呢?

這個優化點,主要是避免了參與者在長時間無法與協調者節點通訊(協調者掛掉了)的情況下,無法釋放資源的問題,因為參與者自身擁有超時機制會在超時后,

自動進行本地commit從而進行釋放資源。而這種機制也側面降低了整個事務的阻塞時間和范圍。

另外,通過CanCommit、PreCommit、DoCommit三個階段的設計,相較于2PC而言,多設置了一個緩沖階段保證了在最后提交階段之前各參與節點的狀態是一致的。

以上就是3PC相對于2PC的一個提高(相對緩解了2PC中的前兩個問題),但是3PC依然沒有完全解決數據不一致的問題。

2PC / 3PC / XA

大廠面試必知必會:圖解分布式事務實現原理

TCC ( Try、Confirm、Cancel ) 原理

概念

TCC三個操作描述:

Try: 檢測、預留資源;
Confirm: 業務系統執行提交;默認Confirm階段是不會出錯的,只要TRY成功,CONFIRM一定成功;
Cancel: 業務取消,預留資源釋放;

大廠面試必知必會:圖解分布式事務實現原理

TCC又稱補償事務。其核心思想是:"針對每個操作都要注冊一個與其對應的確認和補償(撤銷操作)"。它分為三個操作:

1、Try階段:主要是對業務系統做檢測及資源預留。
2、Confirm階段:確認執行業務操作。
3、Cancel階段:取消執行業務操作。

TCC對應?Try、Confirm、Cancel?三種操作可以理解成關系型數據庫事務的三種操作:DML、Commit、Rollback。

在一個跨應用的業務操作中

Try:Try操作是先把多個應用中的業務資源預留和鎖定住,為后續的確認打下基礎,類似的,DML操作要鎖定數據庫記錄行,持有數據庫資源。

Confirm:Confirm操作是在Try操作中涉及的所有應用均成功之后進行確認,使用預留的業務資源,和Commit類似;

Cancel:Cancel則是當Try操作中涉及的所有應用沒有全部成功,需要將已成功的應用進行取消(即Rollback回滾)。其中Confirm和Cancel操作是一對反向業務操作。

TCC的具體原理圖如(盜圖):

大廠面試必知必會:圖解分布式事務實現原理

從圖中我們可以明顯看到Confirm和Cancel操作是一對反向業務操作?即要try返回成功執行Confirm,要么try返回失敗執行Cancel操作。

分布式事務協調者:分布式事務協調者管理控制整個業務活動,包括記錄維護TCC全局事務的事務狀態和每個從業務服務的子事務狀態,并在業務活動提交時確認所有的TCC型

操作的confirm操作,在業務活動取消時調用所有TCC型操作的cancel操作。

舉例

例子:A服務轉30塊錢、B服務轉50塊錢,一起到C服務上。

Try:嘗試執行業務。完成所有業務檢查(一致性):檢查A、B、C的帳戶狀態是否正常,帳戶A的余額是否不少于30元,帳戶B的余額是否不少于50元。預留必須業務資源

(準隔離性):帳戶A的凍結金額增加30元,帳戶B的凍結金額增加50元,這樣就保證不會出現其他并發進程扣減了這兩個帳戶的余額而導致在后續的真正轉帳操作過程中,

帳戶A和B的可用余額不夠的情況。

Confirm:確認執行業務。真正執行業務:如果Try階段帳戶A、B、C狀態正常,且帳戶A、B余額夠用,則執行帳戶A給賬戶C轉賬30元、帳戶B給賬戶C轉賬50元的轉帳

操作。?這時已經不需要做任何業務檢查,Try階段已經完成了業務檢查。只使用Try階段預留的業務資源:只需要使用Try階段帳戶A和帳戶B凍結的金額即可。

Cancel:取消執行業務釋放Try階段預留的業務資源:如果Try階段部分成功,比如帳戶A的余額夠用,且凍結相應金額成功,帳戶B的余額不夠而凍結失敗,則需要

對帳戶A做Cancel操作,將帳戶A被凍結的金額解凍掉。

TCC和2PC比較

2PC是資源層面的分布式事務,強一致性,在兩階段提交的整個過程中,一直會持有資源的鎖。

XA事務中的兩階段提交內部過程是對開發者屏蔽的,事務管理器在兩階段提交過程中,從prepare到commit/rollback過程中,資源實際上一直都是被加鎖的。

如果有其他人需要更新這兩條記錄,那么就必須等待鎖釋放。

TCC是業務層面的分布式事務,最終一致性,不會一直持有資源的鎖。

我的理解就是當執行try接口的時候,已經把所需的資源給預扣了,比如上面舉例的A服務已經預扣30元,B服務已經預扣50元,它是由try接口實現,這樣就保證不會

出現其他并發進程扣減了這兩個帳戶的余額而導致在后續的真正轉帳操作過程中,帳戶A和B的可用余額不夠的情況,同時保證不會一直鎖住整個資源。(核心點應該就在這)

TCC中的兩階段提交并沒有對開發者完全屏蔽,也就是說從代碼層面,開發者是可以感受到兩階段提交的存在。

1、try過程的本地事務,是保證資源預留的業務邏輯的正確性。

2、confirm/cancel執行的本地事務邏輯確認/取消預留資源,以保證最終一致性,也就是所謂的補償型事務

由于是多個獨立的本地事務,因此不會對資源一直加鎖。

TCC 實質上是應用層的2PC ,好比把 XA 兩階段提交那種在數據資源層做的事務管理工作提到了數據應用層。

2PC是資源層面的分布式事務,是強一致性,在兩階段提交的整個過程中,一直會持有資源的鎖

TCC是業務層面的分布式事務,最終一致性,不會一直持有資源的鎖

TCC相比較于2PC來講性能會好很多,但是因為同時需要改造try、confirm、canel3個接口,開發成本高。

注意:還有一點需要注意的是Confirm和Cancel操作可能被重復調用,故要求Confirm和Cancel兩個接口必須是冪等。

RocketMQ 分布式事務原理

一、舉個分布式事務場景

列子:假設?A?給?B?轉?100塊錢,同時它們不是同一個服務上。

目標:就是?A?減100塊錢,B?加100塊錢。

實際情況可能有四種:

1)就是A賬戶減100 (成功),B賬戶加100 (成功)2)就是A賬戶減100(失敗),B賬戶加100 (失敗)3)就是A賬戶減100(成功),B賬戶加100 (失敗)4)就是A賬戶減100 (失敗),B賬戶加100 (成功)

這里?第1和第2?種情況是能夠保證事務的一致性的,但是?第3和第4?是無法保證事務的一致性的。

柔性事務

單數據庫事務完全遵循ACID規范,屬于剛性事務,分布式事務要完全遵循ACID規范比較困難, 分布式事務屬于柔性事務,滿足BASE理論;

BASE描述:BA(Basic Availability 基本業務可用性)、S(Soft state 柔性狀態)、E(Eventual consistency 最終一致性);

柔性事務對ACID的支持:

1、原子性:嚴格遵循;

2、一致性:事務完成后的一致性嚴格遵循,事務中的一致性可適當放寬;

3、隔離性:并行事務間不可影響;事務中間結果可見性允許安全放寬;

4、持久性:嚴格遵循

為了可用性、性能的需要,柔性事務降低了一致性(C)與隔離性(I) 的要求,即“基本可用,最終一致”.

那我們來看下RocketMQ是如何來保證事務的一致性的。

RocketMQ 實現分布式事務原理

RocketMQ雖然之前也支持分布式事務,但并沒有開源,等到RocketMQ 4.3才正式開源。

1、基礎概念

最終一致性

RocketMQ是一種最終一致性的分布式事務,就是說它保證的是消息最終一致性,而不是像2PC、3PC、TCC那樣強一致分布式事務,至于為什么說它是最終一致性事務下面會詳細說明。

Half Message(半消息)

是指暫不能被Consumer消費的消息。Producer 已經把消息成功發送到了 Broker 端,但此消息被標記為暫不能投遞狀態,處于該種狀態下的消息稱為半消息。需要 Producer

對消息的二次確認后,Consumer才能去消費它。

消息回查

由于網絡閃段,生產者應用重啟等原因。導致 Producer 端一直沒有對?Half Message(半消息)?進行?二次確認。這是Brock服務器會定時掃描長期處于半消息的消息,會

主動詢問 Producer端 該消息的最終狀態(Commit或者Rollback),該消息即為?消息回查。

2、分布式事務交互流程

理解這張阿里官方的圖,就能理解RocketMQ分布式事務的原理了。

大廠面試必知必會:圖解分布式事務實現原理

我們來說明下上面這張圖

1、A服務先發送個Half Message給Brock端,消息中攜帶 B服務 即將要+100元的信息。
2、當A服務知道Half Message發送成功后,那么開始第3步執行本地事務。
3、執行本地事務(會有三種情況1、執行成功。2、執行失敗。3、網絡等原因導致沒有響應)
4.1)、如果本地事務成功,那么Product像Brock服務器發送Commit,這樣B服務就可以消費該message。4.2)、如果本地事務失敗,那么Product像Brock服務器發送Rollback,那么就會直接刪除上面這條半消息。4.3)、如果因為網絡等原因遲遲沒有返回失敗還是成功,那么會執行RocketMQ的回調接口,來進行事務的回查。

從上面流程可以得知?只有A服務本地事務執行成功 ,B服務才能消費該message

然后我們再來思考幾個問題?

為什么要先發送Half Message(半消息)

我覺得主要有兩點

1)可以先確認 Brock服務器是否正常 ,如果半消息都發送失敗了 那說明Brock掛了。
2)可以通過半消息來回查事務,如果半消息發送成功后一直沒有被二次確認,那么就會回查事務狀態。

什么情況會回查

也會有兩種情況

1)執行本地事務的時候,由于突然網絡等原因一直沒有返回執行事務的結果(commit或者rollback)導致最終返回UNKNOW,那么就會回查。
2) 本地事務執行成功后,返回Commit進行消息二次確認的時候的服務掛了,在重啟服務那么這個時候在brock端   它還是個Half Message(半消息),這也會回查。

特別注意: 如果回查,那么一定要先查看當前事務的執行情況,再看是否需要重新執行本地事務。

想象下如果出現第二種情況而引起的回查,如果不先查看當前事務的執行情況,而是直接執行事務,那么就相當于成功執行了兩個本地事務。

為什么說MQ是最終一致性事務

通過上面這幅圖,我們可以看出,在上面舉例事務不一致的兩種情況中,永遠不會發生

A賬戶減100 (失敗),B賬戶加100 (成功)

因為:如果A服務本地事務都失敗了,那B服務永遠不會執行任何操作,因為消息壓根就不會傳到B服務。

那么?A賬戶減100 (成功),B賬戶加100 (失敗)?會不會可能存在的。

答案是會的

因為A服務只負責當我消息執行成功了,保證消息能夠送達到B,至于B服務接到消息后最終執行結果A并不管。

那B服務失敗怎么辦?

如果B最終執行失敗,幾乎可以斷定就是代碼有問題所以才引起的異常,因為消費端RocketMQ有重試機制,如果不是代碼問題一般重試幾次就能成功。

如果是代碼的原因引起多次重試失敗后,也沒有關系,將該異常記錄下來,由人工處理,人工兜底處理后,就可以讓事務達到最終的一致性。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

双流县| 望城县| 唐山市| 澄城县| 永年县| 大埔县| 安福县| 奈曼旗| 庆城县| 义马市| 星座| 东莞市| 永济市| 忻城县| 崇礼县| 枣庄市| 洛隆县| 长乐市| 鄢陵县| 许昌市| 巴青县| 黄大仙区| 吉安市| 永兴县| 白银市| 达拉特旗| 唐河县| 新密市| 泰来县| 宁城县| 普兰店市| 金坛市| 肥西县| 玉田县| 修文县| 荔浦县| 绥化市| 石泉县| 高安市| 中西区| 廉江市|