亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

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

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

Java分布式架構原理是什么

發布時間:2022-01-07 20:16:44 來源:億速云 閱讀:154 作者:iii 欄目:編程語言

這篇文章主要介紹“Java分布式架構原理是什么”的相關知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“Java分布式架構原理是什么”文章能幫助大家解決問題。

1. 分布式術語

1.1. 異常

服務器宕機

內存錯誤、服務器停電等都會導致服務器宕機,此時節點無法正常工作,稱為不可用。

服務器宕機會導致節點失去所有內存信息,因此需要將內存信息保存到持久化介質上。

網絡異常

有一種特殊的網絡異常稱為——網絡分區 ,即集群的所有節點被劃分為多個區域,每個區域內部可以通信,但是區域之間無法通信。

磁盤故障

磁盤故障是一種發生概率很高的異常。

使用冗余機制,將數據存儲到多臺服務器。

1.2. 超時

在分布式系統中,一個請求除了成功和失敗兩種狀態,還存在著超時狀態。

可以將服務器的操作設計為具有 冪等性 ,即執行多次的結果與執行一次的結果相同。如果使用這種方式,當出現超時的時候,可以不斷地重新請求直到成功。

1.3. 衡量指標

性能

常見的性能指標有:吞吐量、響應時間。

其中,吞吐量指系統在某一段時間可以處理的請求總數,通常為每秒的讀操作數或者寫操作數;響應時間指從某個請求發出到接收到返回結果消耗的時間。

這兩個指標往往是矛盾的,追求高吞吐的系統,往往很難做到低響應時間,解釋如下:

  • 在無并發的系統中,吞吐量為響應時間的倒數,例如響應時間為 10 ms,那么吞吐量為 100 req/s,因此高吞吐也就意味著低響應時間。

  • 但是在并發的系統中,由于一個請求在調用 I/O 資源的時候,需要進行等待。服務器端一般使用的是異步等待方式,即等待的請求被阻塞之后不需要一直占用 CPU 資源。這種方式能大大提高 CPU 資源的利用率,例如上面的例子中,單個請求在無并發的系統中響應時間為 10 ms,如果在并發的系統中,那么吞吐量將大于 100 req/s。因此為了追求高吞吐量,通常會提高并發程度。但是并發程度的增加,會導致請求的平均響應時間也增加,因為請求不能馬上被處理,需要和其它請求一起進行并發處理,響應時間自然就會增高。

可用性

可用性指系統在面對各種異常時可以提供正常服務的能力。可以用系統可用時間占總時間的比值來衡量,4 個 9 的可用性表示系統 99.99% 的時間是可用的。

一致性

可以從兩個角度理解一致性:從客戶端的角度,讀寫操作是否滿足某種特性;從服務器的角度,多個數據副本之間是否一致。

可擴展性

指系統通過擴展集群服務器規模來提高性能的能力。理想的分布式系統需要實現“線性可擴展”,即隨著集群規模的增加,系統的整體性能也會線性增加。

2. 數據分布

分布式存儲系統的數據分布在多個節點中,常用的數據分布方式有哈希分布和順序分布。

數據庫的水平切分(Sharding)也是一種分布式存儲方法,下面的數據分布方法同樣適用于 Sharding。

2.1. 哈希分布

哈希分布就是將數據計算哈希值之后,按照哈希值分配到不同的節點上。例如有 N 個節點,數據的主鍵為 key,則將該數據分配的節點序號為:hash(key)%N。

傳統的哈希分布算法存在一個問題:當節點數量變化時,也就是 N 值變化,那么幾乎所有的數據都需要重新分布,將導致大量的數據遷移。

一致性哈希

Distributed Hash Table(DHT):對于哈希空間 [0, 2n-1],將該哈希空間看成一個哈希環,將每個節點都配置到哈希環上。每個數據對象通過哈希取模得到哈希值之后,存放到哈希環中順時針方向第一個大于等于該哈希值的節點上。

一致性哈希的優點是在增加或者刪除節點時只會影響到哈希環中相鄰的節點,例如下圖中新增節點 X,只需要將數據對象 C 重新存放到節點 X 上即可,對于節點 A、B、D 都沒有影響。

2.2. 順序分布

哈希分布式破壞了數據的有序性,順序分布則不會。

順序分布的數據劃分為多個連續的部分,按數據的 ID 或者時間分布到不同節點上。例如下圖中,User 表的 ID 范圍為 1 ~ 7000,使用順序分布可以將其劃分成多個子表,對應的主鍵范圍為 1 ~ 1000,1001 ~ 2000,...,6001 ~ 7000。

順序分布的優點是可以充分利用每個節點的空間,而哈希分布很難控制一個節點存儲多少數據。

但是順序分布需要使用一個映射表來存儲數據到節點的映射,這個映射表通常使用單獨的節點來存儲。當數據量非常大時,映射表也隨著變大,那么一個節點就可能無法存放下整個映射表。并且單個節點維護著整個映射表的開銷很大,查找速度也會變慢。為了解決以上問題,引入了一個中間層,也就是 Meta 表,從而分擔映射表的維護工作。

2.3. 負載均衡

衡量負載的因素很多,如 CPU、內存、磁盤等資源使用情況、讀寫請求數等。

分布式系統存儲應當能夠自動負載均衡,當某個節點的負載較高,將它的部分數據遷移到其它節點。

每個集群都有一個總控節點,其它節點為工作節點,由總控節點根據全局負載信息進行整體調度,工作節點定時發送心跳包(Heartbeat)將節點負載相關的信息發送給總控節點。

一個新上線的工作節點,由于其負載較低,如果不加控制,總控節點會將大量數據同時遷移到該節點上,造成該節點一段時間內無法工作。因此負載均衡操作需要平滑進行,新加入的節點需要較長的一段時間來達到比較均衡的狀態。

3. 分布式理論

3.1. CAP

分布式系統不可能同時滿足一致性(C:Consistency)、可用性(A:Availability)和分區容忍性(P:Partition Tolerance),最多只能同時滿足其中兩項。

Java分布式架構原理是什么

一致性

一致性指的是多個數據副本是否能保持一致的特性。

在一致性的條件下,系統在執行數據更新操作之后能夠從一致性狀態轉移到另一個一致性狀態。

對系統的一個數據更新成功之后,如果所有用戶都能夠讀取到最新的值,該系統就被認為具有強一致性。

可用性

可用性指分布式系統在面對各種異常時可以提供正常服務的能力,可以用系統可用時間占總時間的比值來衡量,4 個 9 的可用性表示系統 99.99% 的時間是可用的。

在可用性條件下,系統提供的服務一直處于可用的狀態,對于用戶的每一個操作請求總是能夠在有限的時間內返回結果。

分區容忍性

網絡分區指分布式系統中的節點被劃分為多個區域,每個區域內部可以通信,但是區域之間無法通信。

在分區容忍性條件下,分布式系統在遇到任何網絡分區故障的時候,仍然需要能對外提供一致性和可用性的服務,除非是整個網絡環境都發生了故障。

權衡

在分布式系統中,分區容忍性必不可少,因為需要總是假設網絡是不可靠的。因此,CAP 理論實際在是要在可用性和一致性之間做權衡。

可用性和一致性往往是沖突的,很難都使它們同時滿足。在多個節點之間進行數據同步時,

  • 為了保證一致性(CP),就需要讓所有節點下線成為不可用的狀態,等待同步完成;

  • 為了保證可用性(AP),在同步過程中允許讀取所有節點的數據,但是數據可能不一致。

3.2. BASE

BASE 是基本可用(Basically Available)、軟狀態(Soft State)和最終一致性(Eventually Consistent)三個短語的縮寫。

BASE 理論是對 CAP 中一致性和可用性權衡的結果,它的理論的核心思想是:即使無法做到強一致性,但每個應用都可以根據自身業務特點,采用適當的方式來使系統達到最終一致性。

Java分布式架構原理是什么

基本可用

指分布式系統在出現故障的時候,保證核心可用,允許損失部分可用性。

例如,電商在做促銷時,為了保證購物系統的穩定性,部分消費者可能會被引導到一個降級的頁面。

軟狀態

指允許系統中的數據存在中間狀態,并認為該中間狀態不會影響系統整體可用性,即允許系統不同節點的數據副本之間進行同步的過程存在延時。

最終一致性

最終一致性強調的是系統中所有的數據副本,在經過一段時間的同步后,最終能達到一致的狀態。

ACID 要求強一致性,通常運用在傳統的數據庫系統上。而 BASE 要求最終一致性,通過犧牲強一致性來達到可用性,通常運用在大型分布式系統中。

在實際的分布式場景中,不同業務單元和組件對一致性的要求是不同的,因此 ACID 和 BASE 往往會結合在一起使用。

4. 分布式事務問題

4.1. 兩階段提交(2PC)

兩階段提交(Two-phase Commit,2PC)

主要用于實現分布式事務,分布式事務指的是事務操作跨越多個節點,并且要求滿足事務的 ACID 特性。

通過引入協調者(Coordinator)來調度參與者的行為,并最終決定這些參與者是否要真正執行事務。

運行過程

準備階段

協調者詢問參與者事務是否執行成功,參與者發回事務執行結果。

Java分布式架構原理是什么

提交階段

如果事務在每個參與者上都執行成功,事務協調者發送通知讓參與者提交事務;否則,協調者發送通知讓參與者回滾事務。

Java分布式架構原理是什么

需要注意的是,在準備階段,參與者執行了事務,但是還未提交。只有在提交階段接收到協調者發來的通知后,才進行提交或者回滾。

問題

同步阻塞

所有事務參與者在等待其它參與者響應的時候都處于同步阻塞狀態,無法進行其它操作。

單點問題

協調者在 2PC 中起到非常大的作用,發生故障將會造成很大影響,特別是在階段二發生故障,所有參與者會一直等待狀態,無法完成其它操作。

數據不一致

在階段二,如果協調者只發送了部分 Commit 消息,此時網絡發生異常,那么只有部分參與者接收到 Commit 消息,也就是說只有部分參與者提交了事務,使得系統數據不一致。

太過保守

任意一個節點失敗就會導致整個事務失敗,沒有完善的容錯機制。

2PC 優缺點

優點:盡量保證了數據的強一致,適合對數據強一致要求很高的關鍵領域。(其實也不能 100%保證強一致) 缺點:實現復雜,犧牲了可用性,對性能影響較大,不適合高并發高性能場景。

4.2. 補償事務(TCC)

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

  1. Try 階段主要是對業務系統做檢測及資源預留。

  2. Confirm 階段主要是對業務系統做確認提交,Try 階段執行成功并開始執行 Confirm 階段時,默認 Confirm 階段是不會出錯的。即:只要 Try 成功,Confirm 一定成功。

  3. Cancel 階段主要是在業務執行錯誤,需要回滾的狀態下執行的業務取消,預留資源釋放。

舉個例子,假設 Bob 要向 Smith 轉賬,思路大概是:

  1. 首先在 Try 階段,要先調用遠程接口把 Smith 和 Bob 的錢給凍結起來。

  2. 在 Confirm 階段,執行遠程調用的轉賬的操作,轉賬成功進行解凍。

  3. 如果第 2 步執行成功,那么轉賬成功,如果第二步執行失敗,則調用遠程凍結接口對應的解凍方法 (Cancel)。

TCC 優缺點
  • 優點:跟 2PC 比起來,實現以及流程相對簡單了一些,但數據的一致性比 2PC 也要差一些。

  • 缺點:缺點還是比較明顯的,在 2,3 步中都有可能失敗。TCC 屬于應用層的一種補償方式,所以需要程序員在實現的時候多寫很多補償的代碼,在一些場景中,一些業務流程可能用 TCC 不太好定義及處理。

4.3. 本地消息表(異步確保)

本地消息表與業務數據表處于同一個數據庫中,這樣就能利用本地事務來保證在對這兩個表的操作滿足事務特性。

  1. 在分布式事務操作的一方完成寫業務數據的操作之后向本地消息表發送一個消息,本地事務能保證這個消息一定會被寫入本地消息表中。

  2. 之后將本地消息表中的消息轉發到 Kafka 等消息隊列(MQ)中,如果轉發成功則將消息從本地消息表中刪除,否則繼續重新轉發。

  3. 在分布式事務操作的另一方從消息隊列中讀取一個消息,并執行消息中的操作。

Java分布式架構原理是什么

這種方案遵循 BASE 理論,采用的是最終一致性。

本地消息表利用了本地事務來實現分布式事務,并且使用了消息隊列來保證最終一致性。

本地消息表優缺點
  • 優點:一種非常經典的實現,避免了分布式事務,實現了最終一致性。

  • 缺點:消息表會耦合到業務系統中,如果沒有封裝好的解決方案,會有很多雜活需要處理。

4.4. MQ 事務消息

有一些第三方的 MQ 是支持事務消息的,比如 RocketMQ,他們支持事務消息的方式也是類似于采用的二階段提交。但是市面上一些主流的 MQ 都是不支持事務消息的,比如 RabbitMQ 和 Kafka 都不支持。

以阿里的 RocketMQ 中間件為例,其思路大致為:

  1. Prepared 消息,會拿到消息的地址。

  2. 執行本地事務。

  3. 通過第一階段拿到的地址去訪問消息,并修改狀態。

也就是說在業務方法內要想消息隊列提交兩次請求,一次發送消息和一次確認消息。如果確認消息發送失敗了 RocketMQ 會定期掃描消息集群中的事務消息,這時候發現了 Prepared 消息,它會向消息發送者確認,所以生產方需要實現一個 check 接口,RocketMQ 會根據發送端設置的策略來決定是回滾還是繼續發送確認消息。這樣就保證了消息發送與本地事務同時成功或同時失敗。

MQ 事務消息優缺點
  • 優點:實現了最終一致性,不需要依賴本地數據庫事務。

  • 缺點:實現難度大,主流 MQ 不支持。

5. 共識性問題

5.1. Paxos

用于達成共識性問題,即對多個節點產生的值,該算法能保證只選出唯一一個值。

主要有三類節點:

  • 提議者(Proposer):提議一個值;

  • 接受者(Acceptor):對每個提議進行投票;

  • 告知者(Learner):被告知投票的結果,不參與投票過程。

算法需要滿足 safety 和 liveness 兩方面的約束要求(實際上這兩個基礎屬性是大部分分布式算法都該考慮的):

  • safety:保證決議結果是對的,無歧義的,不會出現錯誤情況。

    • 決議(value)只有在被 proposers 提出的 proposal 才能被最終批準;

    • 在一次執行實例中,只批準(chosen)一個最終決議,意味著多數接受(accept)的結果能成為決議;

  • liveness:保證決議過程能在有限時間內完成。

    • 決議總會產生,并且 learners 能獲得被批準(chosen)的決議。

基本過程包括 proposer 提出提案,先爭取大多數 acceptor 的支持,超過一半支持時,則發送結案結果給所有人進行確認。一個潛在的問題是 proposer 在此過程中出現故障,可以通過超時機制來解決。極為湊巧的情況下,每次新的一輪提案的 proposer 都恰好故障,系統則永遠無法達成一致(概率很小)。

Paxos 能保證在超過 $1/2$ 的正常節點存在時,系統能達成共識。

單個提案者+多接收者

如果系統中限定只有某個特定節點是提案者,那么一致性肯定能達成(只有一個方案,要么達成,要么失敗)。提案者只要收到了來自多數接收者的投票,即可認為通過,因為系統中不存在其他的提案。

但一旦提案者故障,則系統無法工作。

多個提案者+單個接收者

限定某個節點作為接收者。這種情況下,共識也很容易達成,接收者收到多個提案,選第一個提案作為決議,拒絕掉后續的提案即可。

缺陷也是容易發生單點故障,包括接收者故障或首個提案者節點故障。

以上兩種情形其實類似主從模式,雖然不那么可靠,但因為原理簡單而被廣泛采用。

當提案者和接收者都推廣到多個的情形,會出現一些挑戰。

多個提案者+多個接收者

既然限定單提案者或單接收者都會出現故障,那么就得允許出現多個提案者和多個接收者。問題一下子變得復雜了。

一種情況是同一時間片段(如一個提案周期)內只有一個提案者,這時可以退化到單提案者的情形。需要設計一種機制來保障提案者的正確產生,例如按照時間、序列、或者大家猜拳(出一個數字來比較)之類。考慮到分布式系統要處理的工作量很大,這個過程要盡量高效,滿足這一條件的機制非常難設計。

另一種情況是允許同一時間片段內可以出現多個提案者。那同一個節點可能收到多份提案,怎么對他們進行區分呢?這個時候采用只接受第一個提案而拒絕后續提案的方法也不適用。很自然的,提案需要帶上不同的序號。節點需要根據提案序號來判斷接受哪個。比如接受其中序號較大(往往意味著是接受新提出的,因為舊提案者故障概率更大)的提案。

如何為提案分配序號呢?一種可能方案是每個節點的提案數字區間彼此隔離開,互相不沖突。為了滿足遞增的需求可以配合用時間戳作為前綴字段。

此外,提案者即便收到了多數接收者的投票,也不敢說就一定通過。因為在此過程中系統可能還有其它的提案。

5.2. Raft

Raft 算法是 Paxos 算法的一種簡化實現。

包括三種角色:leader、candidate 和 follower,其基本過程為:

  • Leader 選舉 - 每個 candidate 隨機經過一定時間都會提出選舉方案,最近階段中得票最多者被選為 leader;

  • 同步 log - leader 會找到系統中 log 最新的記錄,并強制所有的 follower 來刷新到這個記錄;

注:此處 log 并非是指日志消息,而是各種事件的發生記錄。

單個 Candidate 的競選

有三種節點:Follower、Candidate 和 Leader。Leader 會周期性的發送心跳包給 Follower。每個 Follower 都設置了一個隨機的競選超時時間,一般為 150ms~300ms,如果在這個時間內沒有收到 Leader 的心跳包,就會變成 Candidate,進入競選階段。

  • 下圖表示一個分布式系統的最初階段,此時只有 Follower,沒有 Leader。Follower A 等待一個隨機的競選超時時間之后,沒收到 Leader 發來的心跳包,因此進入競選階段。

Java分布式架構原理是什么

  • 此時 A 發送投票請求給其它所有節點。

Java分布式架構原理是什么

  • 其它節點會對請求進行回復,如果超過一半的節點回復了,那么該 Candidate 就會變成 Leader。

Java分布式架構原理是什么

  • 之后 Leader 會周期性地發送心跳包給 Follower,Follower 接收到心跳包,會重新開始計時。

Java分布式架構原理是什么

多個 Candidate 競選
  • 如果有多個 Follower 成為 Candidate,并且所獲得票數相同,那么就需要重新開始投票,例如下圖中 Candidate B 和 Candidate D 都獲得兩票,因此需要重新開始投票。

Java分布式架構原理是什么

  • 當重新開始投票時,由于每個節點設置的隨機競選超時時間不同,因此能下一次再次出現多個 Candidate 并獲得同樣票數的概率很低。

Java分布式架構原理是什么

同步日志
  • 來自客戶端的修改都會被傳入 Leader。注意該修改還未被提交,只是寫入日志中。

Java分布式架構原理是什么

  • Leader 會把修改復制到所有 Follower。

Java分布式架構原理是什么

  • Leader 會等待大多數的 Follower 也進行了修改,然后才將修改提交。

Java分布式架構原理是什么

  • 此時 Leader 會通知的所有 Follower 讓它們也提交修改,此時所有節點的值達成一致。

Java分布式架構原理是什么

6. 分布式緩存問題

6.1. 緩存雪崩

緩存雪崩是指:在高并發場景下,由于原有緩存失效,新緩存未到期間(例如:我們設置緩存時采用了相同的過期時間,在同一時刻出現大面積的緩存過期),所有原本應該訪問緩存的請求都去查詢數據庫了,而對數據庫 CPU 和內存造成巨大壓力,嚴重的會造成數據庫宕機。從而形成一系列連鎖反應,造成整個系統崩潰。

解決方案:

  • 用加鎖或者隊列的方式保證來保證不會有大量的線程對數據庫一次性進行讀寫,從而避免失效時大量的并發請求落到底層存儲系統上。

  • 還有一個簡單的方案,就是將緩存失效時間分散開,不要所有緩存時間長度都設置成 5 分鐘或者 10 分鐘;比如我們可以在原有的失效時間基礎上增加一個隨機值,比如 1-5 分鐘隨機,這樣每一個緩存的過期時間的重復率就會降低,就很難引發集體失效的事件。

緩存失效時產生的雪崩效應,將所有請求全部放在數據庫上,這樣很容易就達到數據庫的瓶頸,導致服務無法正常提供。盡量避免這種場景的發生。

6.2. 緩存穿透

緩存穿透是指:用戶查詢的數據,在數據庫沒有,自然在緩存中也不會有。這樣就導致用戶查詢的時候,在緩存中找不到,每次都要去數據庫再查詢一遍,然后返回空(相當于進行了兩次無用的查詢)。這樣請求就繞過緩存直接查數據庫,這也是經常提的緩存命中率問題。

當在流量較大時,出現這樣的情況,一直請求 DB,很容易導致服務掛掉。

解決方案:

  1. 在封裝的緩存 SET 和 GET 部分增加個步驟,如果查詢一個 KEY 不存在,就以這個 KEY 為前綴設定一個標識 KEY;以后再查詢該 KEY 的時候,先查詢標識 KEY,如果標識 KEY 存在,就返回一個協定好的非 false 或者 NULL 值,然后 APP 做相應的處理,這樣緩存層就不會被穿透。當然這個驗證 KEY 的失效時間不能太長。

  2. 如果一個查詢返回的數據為空(不管是數據不存在,還是系統故障),我們仍然把這個空結果進行緩存,但它的過期時間會很短,一般只有幾分鐘。

  3. 采用布隆過濾器,將所有可能存在的數據哈希到一個足夠大的 bitmap 中,一個一定不存在的數據會被這個 bitmap 攔截掉,從而避免了對底層存儲系統的查詢壓力。

6.3. 緩存預熱

緩存預熱這個應該是一個比較常見的概念,相信很多小伙伴都應該可以很容易的理解,緩存預熱就是系統上線后,將相關的緩存數據直接加載到緩存系統。這樣就可以避免在用戶請求的時候,先查詢數據庫,然后再將數據緩存的問題!用戶直接查詢事先被預熱的緩存數據!

解決方案:

  1. 直接寫個緩存刷新頁面,上線時手工操作下;

  2. 數據量不大,可以在項目啟動的時候自動進行加載;

  3. 定時刷新緩存;

6.4. 緩存更新

除了緩存服務器自帶的緩存失效策略之外(Redis 默認的有 6 中策略可供選擇),我們還可以根據具體的業務需求進行自定義的緩存淘汰,常見的策略有兩種:

  1. 定時去清理過期的緩存;

  2. 當有用戶請求過來時,再判斷這個請求所用到的緩存是否過期,過期的話就去底層系統得到新數據并更新緩存。

兩者各有優劣,第一種的缺點是維護大量緩存的 key 是比較麻煩的,第二種的缺點就是每次用戶請求過來都要判斷緩存失效,邏輯相對比較復雜!具體用哪種方案,大家可以根據自己的應用場景來權衡。

6.5. 緩存降級

當訪問量劇增、服務出現問題(如響應時間慢或不響應)或非核心服務影響到核心流程的性能時,仍然需要保證服務還是可用的,即使是有損服務。系統可以根據一些關鍵數據進行自動降級,也可以配置開關實現人工降級。

降級的最終目的是保證核心服務可用,即使是有損的。而且有些服務是無法降級的(如加入購物車、結算)。

關于“Java分布式架構原理是什么”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識,可以關注億速云行業資訊頻道,小編每天都會為大家更新不同的知識點。

向AI問一下細節

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

AI

曲沃县| 双峰县| 珠海市| 麻城市| 汉源县| 海安县| 凯里市| 体育| 平度市| 临城县| 郎溪县| 雷波县| 秦安县| 保定市| 长乐市| 德兴市| 万安县| 新宁县| 大渡口区| 壤塘县| 安龙县| 稻城县| 潼南县| 华安县| 太和县| 秦皇岛市| 原平市| 边坝县| 青川县| 巢湖市| 曲松县| 博罗县| 肃北| 从江县| 新化县| 博野县| 来凤县| 新乐市| 望城县| 千阳县| 蓬溪县|