java 并發(fā)編程學(xué)習(xí)筆記(九)多線程并發(fā)拓展

      網(wǎng)友投稿 769 2025-04-01

      多線程并發(fā)拓展

      (1)死鎖

      public class DeadLockTest implements Runnable {

      private int flag ;

      private static Object o1=new Object();

      private static Object o2=new Object();

      public DeadLockTest(int flag) {

      this.flag = flag;

      }

      @Override

      public void run() {

      if(flag == 0){

      synchronized (o2){

      try {

      Thread.sleep(500);

      System.out.println("Thread1開(kāi)始");

      } catch (InterruptedException e) {

      e.printStackTrace();

      }

      synchronized (o1){

      System.out.println("Thread1結(jié)束!");

      }

      }

      }

      if(flag ==1){

      synchronized (o1){

      try {

      Thread.sleep(500);

      System.out.println("Thread2開(kāi)始");

      } catch (InterruptedException e) {

      e.printStackTrace();

      }

      synchronized (o2){

      System.out.println("Thread2結(jié)束!");

      }

      }

      }

      }

      public static void main(String[] args){

      new Thread(new DeadLockTest(0)).start();

      new Thread(new DeadLockTest(1)).start();

      }

      }

      死鎖問(wèn)題是多線程特有的問(wèn)題,它可以被認(rèn)為是線程間切換消耗系統(tǒng)性能的一種極端情況。在死鎖時(shí),線程間相互等待資源,而又不釋放自身的資源,導(dǎo)致無(wú)窮無(wú)盡的等待,其結(jié)果是系統(tǒng)任務(wù)永遠(yuǎn)無(wú)法執(zhí)行完成。死鎖問(wèn)題是在多線程開(kāi)發(fā)中應(yīng)該堅(jiān)決避免和杜絕的問(wèn)題。

      一般來(lái)說(shuō),要出現(xiàn)死鎖問(wèn)題需要滿足以下條件:

      1. 互斥條件:一個(gè)資源每次只能被一個(gè)線程使用。

      2. 請(qǐng)求與保持條件:一個(gè)進(jìn)程因請(qǐng)求資源而阻塞時(shí),對(duì)已獲得的資源保持不放。

      3. 不剝奪條件:進(jìn)程已獲得的資源,在未使用完之前,不能強(qiáng)行剝奪。

      4. 循環(huán)等待條件:若干進(jìn)程之間形成一種頭尾相接的循環(huán)等待資源關(guān)系。

      只要破壞死鎖 4 個(gè)必要條件之一中的任何一個(gè),死鎖問(wèn)題就能被解決。

      死鎖解決方案

      死鎖是由四個(gè)必要條件導(dǎo)致的,所以一般來(lái)說(shuō),只要破壞這四個(gè)必要條件中的一個(gè)條件,死鎖情況就應(yīng)該不會(huì)發(fā)生。

      如果想要打破互斥條件,我們需要允許進(jìn)程同時(shí)訪問(wèn)某些資源,這種方法受制于實(shí)際場(chǎng)景,不太容易實(shí)現(xiàn)條件;

      打破不可搶占條件,這樣需要允許進(jìn)程強(qiáng)行從占有者那里奪取某些資源,或者簡(jiǎn)單一點(diǎn)理解,占有資源的進(jìn)程不能再申請(qǐng)占有其他資源,必須釋放手上的資源之后才能發(fā)起申請(qǐng),這個(gè)其實(shí)也很難找到適用場(chǎng)景;

      進(jìn)程在運(yùn)行前申請(qǐng)得到所有的資源,否則該進(jìn)程不能進(jìn)入準(zhǔn)備執(zhí)行狀態(tài)。這個(gè)方法看似有點(diǎn)用處,但是它的缺點(diǎn)是可能導(dǎo)致資源利用率和進(jìn)程并發(fā)性降低;

      避免出現(xiàn)資源申請(qǐng)環(huán)路,即對(duì)資源事先分類編號(hào),按號(hào)分配。這種方式可以有效提高資源的利用率和系統(tǒng)吞吐量,但是增加了系統(tǒng)開(kāi)銷,增大了進(jìn)程對(duì)資源的占用時(shí)間。

      如果我們?cè)谒梨i檢查時(shí)發(fā)現(xiàn)了死鎖情況,那么就要努力消除死鎖,使系統(tǒng)從死鎖狀態(tài)中恢復(fù)過(guò)來(lái)。消除死鎖的幾種方式:

      1. 最簡(jiǎn)單、最常用的方法就是進(jìn)行系統(tǒng)的重新啟動(dòng),不過(guò)這種方法代價(jià)很大,它意味著在這之前所有的進(jìn)程已經(jīng)完成的計(jì)算工作都將付之東流,包括參與死鎖的那些進(jìn)程,以及未參與死鎖的進(jìn)程;

      2. 撤消進(jìn)程,剝奪資源。終止參與死鎖的進(jìn)程,收回它們占有的資源,從而解除死鎖。這時(shí)又分兩種情況:一次性撤消參與死鎖的全部進(jìn)程,剝奪全部資源;或者逐步撤消參與死鎖的進(jìn)程,逐步收回死鎖進(jìn)程占有的資源。一般來(lái)說(shuō),選擇逐步撤消的進(jìn)程時(shí)要按照一定的原則進(jìn)行,目的是撤消那些代價(jià)最小的進(jìn)程,比如按進(jìn)程的優(yōu)先級(jí)確定進(jìn)程的代價(jià);考慮進(jìn)程運(yùn)行時(shí)的代價(jià)和與此進(jìn)程相關(guān)的外部作業(yè)的代價(jià)等因素;

      3. 進(jìn)程回退策略,即讓參與死鎖的進(jìn)程回退到?jīng)]有發(fā)生死鎖前某一點(diǎn)處,并由此點(diǎn)處繼續(xù)執(zhí)行,以求再次執(zhí)行時(shí)不再發(fā)生死鎖。雖然這是個(gè)較理想的辦法,但是操作起來(lái)系統(tǒng)開(kāi)銷極大,要有堆棧這樣的機(jī)構(gòu)記錄進(jìn)程的每一步變化,以便今后的回退,有時(shí)這是無(wú)法做到的。

      其實(shí)即便是商業(yè)產(chǎn)品,依然會(huì)有很多死鎖情況的發(fā)生,例如 MySQL 數(shù)據(jù)庫(kù),它也經(jīng)常容易出現(xiàn)死鎖案例。

      (2)多線程并發(fā)最佳實(shí)踐

      使用本地變量

      使用不可變類

      最小化鎖的作用域范圍s=1/(1-a+a/n)? (a 并行計(jì)算部分所占比例,n 并行處理節(jié)點(diǎn)個(gè)數(shù),S 加速比)

      使用線程池Executor ,而不是直接new Thread執(zhí)行

      寧可使用同步也不要使用線程的wait和notiyf

      使用BlockingQueue 實(shí)現(xiàn)生產(chǎn)-消費(fèi)模式

      使用并發(fā)集合而不是加了鎖的同步集合

      使用Semaphore創(chuàng)建有界的訪問(wèn)

      寧可使用同步代碼塊,也不適用同步的方法

      避免使用靜態(tài)變量

      (3)高并發(fā)處理思路

      擴(kuò)容

      垂直 擴(kuò)容 :(縱向擴(kuò)展)提高系統(tǒng)的 部件能力

      水平擴(kuò)容:(橫向擴(kuò)容):增加更多系統(tǒng)成員來(lái)實(shí)現(xiàn)

      數(shù)據(jù)庫(kù)擴(kuò)容:

      讀操作擴(kuò)展:memcache,redis,cdn等緩存

      寫(xiě)操作擴(kuò)展:Cassandra,Hbase等

      緩存:

      緩存命中率的影響因素: 業(yè)務(wù)場(chǎng)景合業(yè)務(wù)需求,緩存的設(shè)計(jì)(粒度和策略),緩存容量和基礎(chǔ)設(shè)施

      本地緩存:編程實(shí)現(xiàn)(成員變量、局部變量、靜態(tài)變量)Guava Cache

      分布式緩存:? Memcache 、Redis

      高并發(fā)場(chǎng)景下緩存常見(jiàn)問(wèn)題:

      1、緩存一致性問(wèn)題

      當(dāng)數(shù)據(jù)時(shí)效性要求很高時(shí),需要保證緩存中的數(shù)據(jù)與數(shù)據(jù)庫(kù)中的保持一致,而且需要保證緩存節(jié)點(diǎn)和副本中的數(shù)據(jù)也保持一致,不能出現(xiàn)差異現(xiàn)象。這就比較依賴緩存的過(guò)期和更新策略。一般會(huì)在數(shù)據(jù)發(fā)生更改的時(shí),主動(dòng)更新緩存中的數(shù)據(jù)或者移除對(duì)應(yīng)的緩存。

      2、緩存并發(fā)問(wèn)題

      緩存過(guò)期后將嘗試從后端數(shù)據(jù)庫(kù)獲取數(shù)據(jù),這是一個(gè)看似合理的流程。但是,在高并發(fā)場(chǎng)景下,有可能多個(gè)請(qǐng)求并發(fā)的去從數(shù)據(jù)庫(kù)獲取數(shù)據(jù),對(duì)后端數(shù)據(jù)庫(kù)造成極大的沖擊,甚至導(dǎo)致 “雪崩”現(xiàn)象。此外,當(dāng)某個(gè)緩存key在被更新時(shí),同時(shí)也可能被大量請(qǐng)求在獲取,這也會(huì)導(dǎo)致一致性的問(wèn)題。那如何避免類似問(wèn)題呢?我們會(huì)想到類似“鎖”的機(jī)制,在緩存更新或者過(guò)期的情況下,先嘗試獲取到鎖,當(dāng)更新或者從數(shù)據(jù)庫(kù)獲取完成后再釋放鎖,其他的請(qǐng)求只需要犧牲一定的等待時(shí)間,即可直接從緩存中繼續(xù)獲取數(shù)據(jù)。

      3、緩存穿透問(wèn)題

      緩存穿透在有些地方也稱為“擊穿”。很多朋友對(duì)緩存穿透的理解是:由于緩存故障或者緩存過(guò)期導(dǎo)致大量請(qǐng)求穿透到后端數(shù)據(jù)庫(kù)服務(wù)器,從而對(duì)數(shù)據(jù)庫(kù)造成巨大沖擊。

      這其實(shí)是一種誤解。真正的緩存穿透應(yīng)該是這樣的:

      在高并發(fā)場(chǎng)景下,如果某一個(gè)key被高并發(fā)訪問(wèn),沒(méi)有被命中,出于對(duì)容錯(cuò)性考慮,會(huì)嘗試去從后端數(shù)據(jù)庫(kù)中獲取,從而導(dǎo)致了大量請(qǐng)求達(dá)到數(shù)據(jù)庫(kù),而當(dāng)該key對(duì)應(yīng)的數(shù)據(jù)本身就是空的情況下,這就導(dǎo)致數(shù)據(jù)庫(kù)中并發(fā)的去執(zhí)行了很多不必要的查詢操作,從而導(dǎo)致巨大沖擊和壓力。

      可以通過(guò)下面的幾種常用方式來(lái)避免緩存?zhèn)鹘y(tǒng)問(wèn)題:

      緩存空對(duì)象

      對(duì)查詢結(jié)果為空的對(duì)象也進(jìn)行緩存,如果是集合,可以緩存一個(gè)空的集合(非null),如果是緩存單個(gè)對(duì)象,可以通過(guò)字段標(biāo)識(shí)來(lái)區(qū)分。這樣避免請(qǐng)求穿透到后端數(shù)據(jù)庫(kù)。同時(shí),也需要保證緩存數(shù)據(jù)的時(shí)效性。這種方式實(shí)現(xiàn)起來(lái)成本較低,比較適合命中不高,但可能被頻繁更新的數(shù)據(jù)。

      單獨(dú)過(guò)濾處理

      對(duì)所有可能對(duì)應(yīng)數(shù)據(jù)為空的key進(jìn)行統(tǒng)一的存放,并在請(qǐng)求前做攔截,這樣避免請(qǐng)求穿透到后端數(shù)據(jù)庫(kù)。這種方式實(shí)現(xiàn)起來(lái)相對(duì)復(fù)雜,比較適合命中不高,但是更新不頻繁的數(shù)據(jù)。

      3、緩存顛簸問(wèn)題

      緩存的顛簸問(wèn)題,有些地方可能被成為“緩存抖動(dòng)”,可以看做是一種比“雪崩”更輕微的故障,但是也會(huì)在一段時(shí)間內(nèi)對(duì)系統(tǒng)造成沖擊和性能影響。一般是由于緩存節(jié)點(diǎn)故障導(dǎo)致。業(yè)內(nèi)推薦的做法是通過(guò)一致性Hash算法來(lái)解決。

      4、緩存的雪崩現(xiàn)象

      緩存雪崩就是指由于緩存的原因,導(dǎo)致大量請(qǐng)求到達(dá)后端數(shù)據(jù)庫(kù),從而導(dǎo)致數(shù)據(jù)庫(kù)崩潰,整個(gè)系統(tǒng)崩潰,發(fā)生災(zāi)難。導(dǎo)致這種現(xiàn)象的原因有很多種,上面提到的“緩存并發(fā)”,“緩存穿透”,“緩存顛簸”等問(wèn)題,其實(shí)都可能會(huì)導(dǎo)致緩存雪崩現(xiàn)象發(fā)生。這些問(wèn)題也可能會(huì)被惡意攻擊者所利用。還有一種情況,例如某個(gè)時(shí)間點(diǎn)內(nèi),系統(tǒng)預(yù)加載的緩存周期性集中失效了,也可能會(huì)導(dǎo)致雪崩。為了避免這種周期性失效,可以通過(guò)設(shè)置不同的過(guò)期時(shí)間,來(lái)錯(cuò)開(kāi)緩存過(guò)期,從而避免緩存集中失效。

      從應(yīng)用架構(gòu)角度,我們可以通過(guò)限流、降級(jí)、熔斷等手段來(lái)降低影響,也可以通過(guò)多級(jí)緩存來(lái)避免這種災(zāi)難。

      此外,從整個(gè)研發(fā)體系流程的角度,應(yīng)該加強(qiáng)壓力測(cè)試,盡量模擬真實(shí)場(chǎng)景,盡早的暴露問(wèn)題從而防范。

      5、緩存無(wú)底洞現(xiàn)象

      該問(wèn)題由 facebook 的工作人員提出的, facebook 在 2010 年左右,memcached 節(jié)點(diǎn)就已經(jīng)達(dá)3000 個(gè),緩存數(shù)千 G 內(nèi)容。

      他們發(fā)現(xiàn)了一個(gè)問(wèn)題---memcached 連接頻率,效率下降了,于是加 memcached 節(jié)點(diǎn),

      添加了后,發(fā)現(xiàn)因?yàn)檫B接頻率導(dǎo)致的問(wèn)題,仍然存在,并沒(méi)有好轉(zhuǎn),稱之為”無(wú)底洞現(xiàn)象”。

      目前主流的數(shù)據(jù)庫(kù)、緩存、Nosql、搜索中間件等技術(shù)棧中,都支持“分片”技術(shù),來(lái)滿足“高性能、高并發(fā)、高可用、可擴(kuò)展”等要求。有些是在client端通過(guò)Hash取模(或一致性Hash)將值映射到不同的實(shí)例上,有些是在client端通過(guò)范圍取值的方式映射的。當(dāng)然,也有些是在服務(wù)端進(jìn)行的。但是,每一次操作都可能需要和不同節(jié)點(diǎn)進(jìn)行網(wǎng)絡(luò)通信來(lái)完成,實(shí)例節(jié)點(diǎn)越多,則開(kāi)銷會(huì)越大,對(duì)性能影響就越大。

      主要可以從如下幾個(gè)方面避免和優(yōu)化:

      數(shù)據(jù)分布方式

      有些業(yè)務(wù)數(shù)據(jù)可能適合Hash分布,而有些業(yè)務(wù)適合采用范圍分布,這樣能夠從一定程度避免網(wǎng)絡(luò)IO的開(kāi)銷。

      IO優(yōu)化

      可以充分利用連接池,NIO等技術(shù)來(lái)盡可能降低連接開(kāi)銷,增強(qiáng)并發(fā)連接能力。

      數(shù)據(jù)訪問(wèn)方式

      一次性獲取大的數(shù)據(jù)集,會(huì)比分多次去獲取小數(shù)據(jù)集的網(wǎng)絡(luò)IO開(kāi)銷更小。

      當(dāng)然,緩存無(wú)底洞現(xiàn)象并不常見(jiàn)。在絕大多數(shù)的公司里可能根本不會(huì)遇到。

      消息隊(duì)列

      流程A在處理時(shí)沒(méi)有在當(dāng)前線程同步的處理完而是直接發(fā)送了一條消息A1到隊(duì)列里,然后消息隊(duì)列過(guò)了一段時(shí)間(可能是幾毫秒 幾秒 幾分鐘)這個(gè)消息開(kāi)始被處理,消息處理的過(guò)程就相當(dāng)于流程A被處理;當(dāng)然這只是一個(gè)簡(jiǎn)單的模型下面我們套用實(shí)際的場(chǎng)景來(lái)看一下,比如下單成功后發(fā)送短信提醒;如果沒(méi)有消息隊(duì)列我們會(huì)選擇同步調(diào)用發(fā)短信的接口并等待短信發(fā)送成功,正常情況下這么做是沒(méi)有問(wèn)題的但是如果發(fā)短信的時(shí)候短信接口出問(wèn)題了或者說(shuō)調(diào)用超時(shí)了等意外情況,這個(gè)時(shí)候我們就需要設(shè)計(jì)對(duì)應(yīng)的方案來(lái)解決前提是這些方案的設(shè)計(jì)會(huì)比較復(fù)雜;

      但是當(dāng)我們使用消息隊(duì)列以后這個(gè)事情就會(huì)變得非常簡(jiǎn)單,使用消息隊(duì)列以后有如下好處:

      ① 實(shí)現(xiàn)了異步解耦

      ② 設(shè)計(jì)變的更加簡(jiǎn)單了

      ③ 保證了數(shù)據(jù)的最終一致性;

      ④ 提高效率;

      消息隊(duì)列特性:

      1 與業(yè)務(wù)無(wú)關(guān) : 只做消息分發(fā)

      2 FIFO : 先投遞先到達(dá)

      3 容災(zāi) : 節(jié)點(diǎn)的動(dòng)態(tài)增刪和消息的持久化

      4 性能 : 吞吐量提升,系統(tǒng)內(nèi)部通信效率提高

      為什么需要消息隊(duì)列?

      生產(chǎn)和消費(fèi)的速度或穩(wěn)定性等因素不一致;

      消息隊(duì)列的好處

      1 業(yè)務(wù)解耦

      2 最終一致性 : 用記錄和補(bǔ)償?shù)姆绞絹?lái)處理,在做所有的不確定事情之前先記錄然后再去做,它的結(jié)果通常分為三種成功失敗或者不確定(比如說(shuō)超時(shí)等);如果是成功我們就可以清楚掉記錄,如果是失敗或者不確定我們可以通過(guò)定時(shí)任務(wù)將所有事情重新做一遍直到成功為止;

      3 廣播 : 如果沒(méi)有消息隊(duì)列每一個(gè)新的業(yè)務(wù)方介入都需要聯(lián)調(diào)一次接口,使用消息隊(duì)列只需要關(guān)心消息是否送達(dá)到消息隊(duì)列,新接入的接口訂閱相關(guān)的消息自己做處理就可以了;

      4 錯(cuò)峰與流控 : 上下游對(duì)于事情的處理是不同的,比如WEB前端每秒承受上千萬(wàn)的請(qǐng)求都是可以的但是數(shù)據(jù)庫(kù)的處理卻非常有限;迫于成本的壓力我們不能要求數(shù)據(jù)庫(kù)的機(jī)器數(shù)量與前端資源一樣;這樣的問(wèn)題同樣存在于系統(tǒng)與系統(tǒng)之間,比如短信系統(tǒng)的速度卡在網(wǎng)關(guān)上邊它與前端的并發(fā)量不是一個(gè)數(shù)量級(jí)的,用戶玩幾秒種收到短信也是可以的;針對(duì)于這樣的場(chǎng)景如果沒(méi)有消息隊(duì)列也能實(shí)現(xiàn)但是系統(tǒng)的復(fù)雜度非常的高;

      常用的消息隊(duì)列介紹

      java 并發(fā)編程學(xué)習(xí)筆記(九)多線程并發(fā)拓展

      Kafka

      Kafka是Apache下的一個(gè)子項(xiàng)目,是一個(gè)高性能 跨語(yǔ)言 分布式發(fā)布訂閱消息隊(duì)列系統(tǒng);

      1 Kafka的特性

      ① 快速持久化 : 它可以在o1的系統(tǒng)開(kāi)銷下實(shí)現(xiàn)消息的持久化;

      ② 高吞吐 : 在一臺(tái)普通的服務(wù)器上就可以達(dá)到10w/秒的吞吐速率;

      ③ 天生的分布式 : 所有組件天生支持分布式且自動(dòng)實(shí)現(xiàn)負(fù)載均衡;

      2 Kafka基礎(chǔ)定義

      ① Broker : Kafka集群包含一個(gè)或多個(gè)服務(wù)器,這個(gè)服務(wù)器就被稱為Producer;

      ② Topic : 指每條發(fā)布到Kafka的消息都有一個(gè)類別,這個(gè)類別叫做Topic;物理上不同Topic的消息是分開(kāi)存儲(chǔ)的,邏輯上一個(gè)Topic消息雖然保存在一個(gè)或者多Producer上但是用戶只需指定消息的Topic就可以生產(chǎn)或者消費(fèi)數(shù)據(jù)而不用關(guān)心數(shù)據(jù)存在哪里;

      ③ Partition : 是物理上的概念,每個(gè)Topic包含一個(gè)或者多個(gè)Partition;

      ④ Producer : 負(fù)責(zé)發(fā)布消息到Kafka的Broker里邊;

      ⑤ consumer : 消息消費(fèi)者,向Kafka broker讀取消息的客戶端;

      ⑥ Consumer Group : 每個(gè)Consumer屬于一個(gè)特定的Consumer Group(可為每個(gè)Consumer指定group name,若不指定group name則屬于默認(rèn)的group);

      RabbitMQ

      RabbitMQ是流行的開(kāi)源消息隊(duì)列系統(tǒng),用erlang語(yǔ)言開(kāi)發(fā)。RabbitMQ是AMQP(高級(jí)消息隊(duì)列協(xié)議)的標(biāo)準(zhǔn)實(shí)現(xiàn);

      1 RabbitMQ的使用過(guò)程

      (1)客戶端連接到消息隊(duì)列服務(wù)器,打開(kāi)一個(gè)channel。

      (2)客戶端聲明一個(gè)exchange,并設(shè)置相關(guān)屬性。

      (3)客戶端聲明一個(gè)queue,并設(shè)置相關(guān)屬性。

      (4)客戶端使用routing key,在exchange和queue之間建立好綁定關(guān)系。

      (5)客戶端投遞消息到exchange。

      2 RabbitMQ的概念

      Broker:簡(jiǎn)單來(lái)說(shuō)就是消息隊(duì)列服務(wù)器實(shí)體。

      Exchange:消息交換機(jī),它指定消息按什么規(guī)則,路由到哪個(gè)隊(duì)列。

      Queue:消息隊(duì)列載體,每個(gè)消息都會(huì)被投入到一個(gè)或多個(gè)隊(duì)列。

      Binding:綁定,它的作用就是把exchange和queue按照路由規(guī)則綁定起來(lái)。

      Routing Key:路由關(guān)鍵字,exchange根據(jù)這個(gè)關(guān)鍵字進(jìn)行消息投遞。

      vhost:虛擬主機(jī),一個(gè)broker里可以開(kāi)設(shè)多個(gè)vhost,用作不同用戶的權(quán)限分離。

      producer:消息生產(chǎn)者,就是投遞消息的程序。

      consumer:消息消費(fèi)者,就是接受消息的程序。

      channel:消息通道,在客戶端的每個(gè)連接里,可建立多個(gè)channel,每個(gè)channel代表一個(gè)會(huì)話任務(wù)。

      (4)高并發(fā)應(yīng)用拆分

      比如一個(gè)股票系統(tǒng)有用戶信息、開(kāi)戶、股票行情、交易、訂單等,拆分后如下圖所示:

      原則

      業(yè)務(wù)優(yōu)先

      每個(gè)系統(tǒng)都會(huì)有多個(gè)模塊,每個(gè)模塊又有多個(gè)業(yè)務(wù)功能;按照業(yè)務(wù)邊界進(jìn)行切割,再對(duì)模塊進(jìn)行拆分。

      循序漸進(jìn)

      邊拆分邊測(cè)試,保證系統(tǒng)的正常運(yùn)行。

      兼顧技術(shù):重構(gòu)、分層

      不能為了分布式而分布式,拆分過(guò)程不僅是業(yè)務(wù)梳理也是代碼重構(gòu)的過(guò)程,根據(jù)技術(shù)進(jìn)行分層來(lái)分配工作,ui對(duì)用戶體驗(yàn),熟悉C和C++對(duì)服務(wù)器,熟悉數(shù)據(jù)庫(kù)的對(duì)數(shù)據(jù)庫(kù),做到術(shù)業(yè)有專攻,合適的人去做合適的事情。

      可靠測(cè)試

      測(cè)試完畢后,才可進(jìn)行下一步,每一步都要有足夠的測(cè)試才可進(jìn)行下一步,避免小錯(cuò)誤引起蝴蝶效應(yīng)。

      思考

      應(yīng)用之間通信: RPC ( dubbo等)、消息隊(duì)列

      消息隊(duì)列通常用于傳輸數(shù)據(jù)包小但是數(shù)據(jù)量大,對(duì)實(shí)時(shí)性要求低的場(chǎng)景,比如下單后短信通知客戶。而采用RPC要求實(shí)時(shí)性高,這里通常不會(huì)http或者service服務(wù),原因是使用PRC調(diào)用service方法無(wú)感知,在配置好后和本地方法很像。

      應(yīng)用之間數(shù)據(jù)庫(kù)設(shè)計(jì):每個(gè)應(yīng)用都有獨(dú)立的數(shù)據(jù)庫(kù)

      通常情況下,每個(gè)應(yīng)用都有自己獨(dú)立的數(shù)據(jù)庫(kù),如果共同使用的信息,可以考慮放在common中使用。

      避免事務(wù)操作跨應(yīng)用

      分布式事務(wù)是一個(gè)很消耗資源的問(wèn)題,應(yīng)用之間服務(wù)分開(kāi)開(kāi)發(fā),能夠保持相互獨(dú)立。

      框架

      服務(wù)化 Dubbo

      微服務(wù)Spring Cloud

      微服務(wù):獨(dú)立的服務(wù)共同組成一個(gè)系統(tǒng)

      要實(shí)踐微服務(wù)要解決4個(gè)問(wèn)題:

      客戶端如何訪問(wèn)這些服務(wù)

      API Gateway提供統(tǒng)一的服務(wù)入口,對(duì)前臺(tái)透明,同時(shí)可以聚合后臺(tái)的服務(wù),提供安全過(guò)濾流控等api的管理功能

      服務(wù)之間是如何通信的

      異步的話使用消息隊(duì)列,同步調(diào)用使用REST或者是RPC,Rest可以使用springboot,RPC通常使用Dubbo

      同步調(diào)用一致性強(qiáng)但是出現(xiàn)調(diào)用問(wèn)題,REST一般基于http實(shí)現(xiàn),能夠跨客戶端,同時(shí)對(duì)客戶端沒(méi)有更多的要求。

      RPC的傳輸協(xié)議更高效,安全也更加可控。特別是在一個(gè)公司內(nèi)部如果有統(tǒng)一的開(kāi)發(fā)規(guī)范和統(tǒng)一的框架,它的開(kāi)發(fā)效率會(huì)更加明顯。

      而異步消息在分布式系統(tǒng)中有特別廣泛的應(yīng)用,它既能減少調(diào)用服務(wù)之間的耦合,又能成為調(diào)用之間的緩沖,確保消息積壓不會(huì)沖垮被調(diào)用方。

      同時(shí)保證調(diào)用方的用戶的體驗(yàn),繼續(xù)干自己的活。付出的代價(jià)是一致性的減慢,需要接受數(shù)據(jù)的最終一致性

      如何實(shí)現(xiàn)如此多服務(wù)

      在微服務(wù)架構(gòu)中一般每一服務(wù)都會(huì)拷貝進(jìn)行負(fù)載均衡,服務(wù)如何相互感知,如何相互管理,這就是服務(wù)發(fā)現(xiàn)的問(wèn)題了,一般都是進(jìn)行服務(wù)注冊(cè)信息的分布式管理。

      服務(wù)掛了該如何解決,有什么備份方案和應(yīng)急處理機(jī)制

      分布式最大的特性就是網(wǎng)絡(luò)是不可靠的,當(dāng)系統(tǒng)是由一系列的調(diào)用鏈組成的時(shí)候,其中任何一個(gè)出問(wèn)題都不至于影響到整個(gè)鏈路。

      相應(yīng)的手段有:重試機(jī)制、應(yīng)用的限流、熔斷機(jī)制、負(fù)載均衡、系統(tǒng)降級(jí)

      (5) 應(yīng)用限流

      限流就是通過(guò)對(duì)并發(fā)訪問(wèn)/請(qǐng)求進(jìn)行限速或一個(gè)時(shí)間窗口內(nèi)的請(qǐng)求進(jìn)行限速,從而達(dá)到保護(hù)系統(tǒng)的目的。一般系統(tǒng)可以通過(guò)壓測(cè)來(lái)預(yù)估能處理的峰值,一旦達(dá)到設(shè)定的峰值閥值,則可以拒絕服務(wù)(定向錯(cuò)誤頁(yè)或告知資源沒(méi)有了)、排隊(duì)或等待(例如:秒殺、評(píng)論、下單)、降級(jí)(返回默認(rèn)數(shù)據(jù))

      限流不能亂用,否則正常流量會(huì)出現(xiàn)一些奇怪的問(wèn)題,從而導(dǎo)致用戶抱怨。

      假設(shè)有130W到140W的數(shù)據(jù)插入到數(shù)據(jù)庫(kù)中,如果沒(méi)有做限流,數(shù)據(jù)庫(kù)的主庫(kù)會(huì)突然接收到130w的插入操作

      首先是網(wǎng)絡(luò)上的開(kāi)銷,很可能直接把帶寬占滿,導(dǎo)致其他請(qǐng)求無(wú)法正常傳輸和處理,其次會(huì)是數(shù)據(jù)庫(kù)的負(fù)載突然增高,導(dǎo)致無(wú)法處理某些數(shù)據(jù)庫(kù)的操作,也有可能數(shù)據(jù)庫(kù)沒(méi)有足夠的連接導(dǎo)致某些數(shù)據(jù)庫(kù)插入查詢失??;

      還有一點(diǎn)就是現(xiàn)在數(shù)據(jù)庫(kù)都做了主從設(shè)計(jì),主數(shù)據(jù)庫(kù)的數(shù)據(jù)還要同步給從庫(kù),這時(shí)瞬間插入了大量的數(shù)據(jù),會(huì)帶來(lái)從庫(kù)和主庫(kù)的延遲特別大,這時(shí)從庫(kù)查詢不準(zhǔn)確的概率也會(huì)跟著提升。

      如果我們放慢插入數(shù)據(jù)庫(kù)的速度,這時(shí)插入數(shù)據(jù)庫(kù)主庫(kù)的速率會(huì)很正常,同步到從庫(kù)也很正常。網(wǎng)絡(luò)消耗也可以接收不會(huì)影響其他服務(wù)。

      1.計(jì)數(shù)器法

      有時(shí)我們還會(huì)使用計(jì)數(shù)器來(lái)進(jìn)行限流,主要用來(lái)限制一定時(shí)間內(nèi)的總并發(fā)數(shù),比如數(shù)據(jù)庫(kù)連接池、線程池、秒殺的并發(fā)數(shù);計(jì)數(shù)器限流只要一定時(shí)間內(nèi)的總請(qǐng)求數(shù)超過(guò)設(shè)定的閥值則進(jìn)行限流,是一種簡(jiǎn)單粗暴的總數(shù)量限流,而不是平均速率限流。

      這個(gè)方法有一個(gè)致命問(wèn)題:臨界問(wèn)題——當(dāng)遇到惡意請(qǐng)求,在0:59時(shí),瞬間請(qǐng)求100次,并且在1:00請(qǐng)求100次,那么這個(gè)用戶在1秒內(nèi)請(qǐng)求了200次,用戶可以在重置節(jié)點(diǎn)突發(fā)請(qǐng)求,而瞬間超過(guò)我們?cè)O(shè)置的速率限制,用戶可能通過(guò)算法漏洞擊垮我們的應(yīng)用。

      2.滑動(dòng)窗口算法

      在上圖中,整個(gè)紅色矩形框是一個(gè)時(shí)間窗口,在我們的例子中,一個(gè)時(shí)間窗口就是1分鐘,然后我們將時(shí)間窗口進(jìn)行劃分,如上圖我們把滑動(dòng)窗口

      劃分為6格,所以每一格代表10秒,每超過(guò)10秒,我們的時(shí)間窗口就會(huì)向右滑動(dòng)一格,每一格都有自己獨(dú)立的計(jì)數(shù)器,例如:一個(gè)請(qǐng)求在0:35到達(dá),

      那么0:30到0:39的計(jì)數(shù)器會(huì)+1,那么滑動(dòng)窗口是怎么解決臨界點(diǎn)的問(wèn)題呢?如上圖,0:59到達(dá)的100個(gè)請(qǐng)求會(huì)在灰色區(qū)域格子中,而1:00到達(dá)的請(qǐng)求

      會(huì)在紅色格子中,窗口會(huì)向右滑動(dòng)一格,那么此時(shí)間窗口內(nèi)的總請(qǐng)求數(shù)共200個(gè),超過(guò)了限定的100,所以此時(shí)能夠檢測(cè)出來(lái)觸發(fā)了限流。

      回頭看看計(jì)數(shù)器算法,會(huì)發(fā)現(xiàn),其實(shí)計(jì)數(shù)器算法就是窗口滑動(dòng)算法,只不過(guò)計(jì)數(shù)器算法沒(méi)有對(duì)時(shí)間窗口進(jìn)行劃分,所以是一格。

      由此可見(jiàn),當(dāng)滑動(dòng)窗口的格子劃分越多,限流的統(tǒng)計(jì)就會(huì)越精確。

      3.漏銅算法

      這個(gè)算法很簡(jiǎn)單。首先,我們有一個(gè)固定容量的桶,有水進(jìn)來(lái),也有水出去。對(duì)于流進(jìn)來(lái)的水,我們無(wú)法預(yù)計(jì)共有多少水流進(jìn)來(lái),也無(wú)法預(yù)計(jì)流水速度,但

      對(duì)于流出去的水來(lái)說(shuō),這個(gè)桶可以固定水流的速率,而且當(dāng)桶滿的時(shí)候,多余的水會(huì)溢出來(lái)。

      4.令牌桶算法

      從上圖中可以看出,令牌算法有點(diǎn)復(fù)雜,桶里存放著令牌token。桶一開(kāi)始是空的,token以固定的速率r往桶里面填充,直到達(dá)到桶的容量,多余的token會(huì)

      被丟棄。每當(dāng)一個(gè)請(qǐng)求過(guò)來(lái)時(shí),就會(huì)嘗試著移除一個(gè)token,如果沒(méi)有token,請(qǐng)求無(wú)法通過(guò)。

      (6)服務(wù)降級(jí)與服務(wù)熔斷

      服務(wù)降級(jí):

      服務(wù)壓力劇增的時(shí)候根據(jù)當(dāng)前的業(yè)務(wù)情況及流量對(duì)一些服務(wù)和頁(yè)面有策略的降級(jí),以此環(huán)節(jié)服務(wù)器的壓力,以保證核心任務(wù)的進(jìn)行。

      同時(shí)保證部分甚至大部分任務(wù)客戶能得到正確的相應(yīng)。也就是當(dāng)前的請(qǐng)求處理不了了或者出錯(cuò)了,給一個(gè)默認(rèn)的返回。

      服務(wù)熔斷:

      在股票市場(chǎng),熔斷這個(gè)詞大家都不陌生,是指當(dāng)股指波幅達(dá)到某個(gè)點(diǎn)后,交易所為控制風(fēng)險(xiǎn)采取的暫停交易措施。相應(yīng)的,服務(wù)熔斷一般是指軟件系統(tǒng)中,由于某些原因使得服務(wù)出現(xiàn)了過(guò)載現(xiàn)象,為防止造成整個(gè)系統(tǒng)故障,從而采用的一種保護(hù)措施,所以很多地方把熔斷亦稱為過(guò)載保護(hù)。

      降級(jí)分類

      降級(jí)按照是否自動(dòng)化可分為:自動(dòng)開(kāi)關(guān)降級(jí)和人工開(kāi)關(guān)降級(jí)。

      降級(jí)按照功能可分為:讀服務(wù)降級(jí)、寫(xiě)服務(wù)降級(jí)。

      降級(jí)按照處于的系統(tǒng)層次可分為:多級(jí)降級(jí)。

      自動(dòng)降級(jí)分類

      (1)、超時(shí)降級(jí):主要配置好超時(shí)時(shí)間和超時(shí)重試次數(shù)和機(jī)制,并使用異步機(jī)制探測(cè)回復(fù)情況

      (2)、失敗次數(shù)降級(jí):主要是一些不穩(wěn)定的api,當(dāng)失敗調(diào)用次數(shù)達(dá)到一定閥值自動(dòng)降級(jí),同樣要使用異步機(jī)制探測(cè)回復(fù)情況

      (3)、故障降級(jí):比如要調(diào)用的遠(yuǎn)程服務(wù)掛掉了(網(wǎng)絡(luò)故障、DNS故障、http服務(wù)返回錯(cuò)誤的狀態(tài)碼、rpc服務(wù)拋出異常),則可以直接降級(jí)。降級(jí)后的處理方案有:默認(rèn)值(比如庫(kù)存服務(wù)掛了,返回默認(rèn)現(xiàn)貨)、兜底數(shù)據(jù)(比如廣告掛了,返回提前準(zhǔn)備好的一些靜態(tài)頁(yè)面)、緩存(之前暫存的一些緩存數(shù)據(jù))

      (4)、限流降級(jí)

      當(dāng)我們?nèi)ッ霘⒒蛘邠屬?gòu)一些限購(gòu)商品時(shí),此時(shí)可能會(huì)因?yàn)樵L問(wèn)量太大而導(dǎo)致系統(tǒng)崩潰,此時(shí)開(kāi)發(fā)者會(huì)使用限流來(lái)進(jìn)行限制訪問(wèn)量,當(dāng)達(dá)到限流閥值,后續(xù)請(qǐng)求會(huì)被降級(jí);降級(jí)后的處理方案可以是:排隊(duì)頁(yè)面(將用戶導(dǎo)流到排隊(duì)頁(yè)面等一會(huì)重試)、無(wú)貨(直接告知用戶沒(méi)貨了)、錯(cuò)誤頁(yè)(如活動(dòng)太火爆了,稍后重試)。

      服務(wù)熔斷和服務(wù)降級(jí)比較:

      兩者其實(shí)從有些角度看是有一定的類似性的:

      目的很一致,都是從可用性可靠性著想,為防止系統(tǒng)的整體緩慢甚至崩潰,采用的技術(shù)手段;

      最終表現(xiàn)類似,對(duì)于兩者來(lái)說(shuō),最終讓用戶體驗(yàn)到的是某些功能暫時(shí)不可達(dá)或不可用;

      粒度一般都是服務(wù)級(jí)別,當(dāng)然,業(yè)界也有不少更細(xì)粒度的做法,比如做到數(shù)據(jù)持久層(允許查詢,不允許增刪改);

      自治性要求很高,熔斷模式一般都是服務(wù)基于策略的自動(dòng)觸發(fā),降級(jí)雖說(shuō)可人工干預(yù),但在微服務(wù)架構(gòu)下,完全靠人顯然不可能,開(kāi)關(guān)預(yù)置、配置中心都是必要手段;

      而兩者的區(qū)別也是明顯的:

      觸發(fā)原因不太一樣,服務(wù)熔斷一般是某個(gè)服務(wù)(下游服務(wù))故障引起,而服務(wù)降級(jí)一般是從整體負(fù)荷考慮;

      管理目標(biāo)的層次不太一樣,熔斷其實(shí)是一個(gè)框架級(jí)的處理,每個(gè)微服務(wù)都需要(無(wú)層級(jí)之分),而降級(jí)一般需要對(duì)業(yè)務(wù)有層級(jí)之分(比如降級(jí)一般是從最外圍服務(wù)開(kāi)始)

      實(shí)現(xiàn)方式不太一樣

      服務(wù)降級(jí)要考慮的問(wèn)題:

      1.核心和非核心服務(wù)

      2.是否支持降級(jí),降級(jí)策略

      3.業(yè)務(wù)放通的場(chǎng)景,策略

      Hystrix,該庫(kù)旨在通過(guò)控制那些訪問(wèn)遠(yuǎn)程系統(tǒng)、服務(wù)和第三方庫(kù)的節(jié)點(diǎn),從而對(duì)延遲和故障提供更強(qiáng)大的容錯(cuò)能力。Hystrix具備擁有回退機(jī)制和斷路器功能的線程和信號(hào)隔離,請(qǐng)求緩存和請(qǐng)求打包(request collapsing,即自動(dòng)批處理,譯者注),以及監(jiān)控和配置等功能。

      (7)數(shù)據(jù)庫(kù)分庫(kù)分表

      數(shù)據(jù)庫(kù)的瓶頸

      單個(gè)庫(kù)數(shù)據(jù)量太大;考慮多個(gè)庫(kù)解決問(wèn)題。

      單個(gè)數(shù)據(jù)庫(kù)服務(wù)器壓力過(guò)大、讀寫(xiě)瓶頸;考慮多個(gè)庫(kù)、讀寫(xiě)分離解決問(wèn)題。

      單個(gè)表數(shù)據(jù)量過(guò)大;考慮分表解決問(wèn)題。

      數(shù)據(jù)庫(kù)切庫(kù)與分庫(kù)

      對(duì)數(shù)據(jù)庫(kù)的操作中讀多寫(xiě)少,且讀操作占用系統(tǒng)資源多,耗時(shí)長(zhǎng),適用多個(gè)分庫(kù)進(jìn)行負(fù)載均衡。詳情查看: 自定義注解完成數(shù)據(jù)庫(kù)切庫(kù)

      切庫(kù)的基礎(chǔ)及實(shí)際應(yīng)用中,隨著業(yè)務(wù)增加,并發(fā)增加,需做到讀寫(xiě)分離;

      自定義注解完成數(shù)據(jù)庫(kù)切庫(kù)-代碼實(shí)現(xiàn);另一種方式是在業(yè)務(wù)中直接定義兩個(gè)數(shù)據(jù)庫(kù)鏈接:主庫(kù)連接和從庫(kù)連接;更新數(shù)據(jù)時(shí),讀取主庫(kù)連接,

      支持多數(shù)據(jù)源:指一個(gè)項(xiàng)目里,同時(shí)可以訪問(wèn)多個(gè)不同的數(shù)據(jù)庫(kù)。

      原理:?jiǎn)蝹€(gè)數(shù)據(jù)源在配置時(shí)會(huì)綁定一套mybatis配置,多個(gè)數(shù)據(jù)源時(shí),不同的數(shù)據(jù)源綁定不同的mybatis配置就可以了,簡(jiǎn)單的思路就是讓不同的數(shù)據(jù)源掃描不同的包,讓不同的包下的mapper對(duì)應(yīng)連接不同的數(shù)據(jù)源去處理邏輯。

      數(shù)據(jù)庫(kù)分表

      分表的類型

      橫向(水平)分表(Horizontal Partitioning)

      這種形式分區(qū)是對(duì)表的行進(jìn)行分割,通過(guò)這樣的方式不同分組里面的物理列分割的數(shù)據(jù)集得以組合,從而進(jìn)行個(gè)體分割(單分區(qū))或集體分割(1個(gè)或多個(gè)分區(qū))。所有在表中定義的列在每個(gè)數(shù)據(jù)集中都能找到,所以表的特性依然得以保持。

      縱向(垂直)分表(Vertical Partitioning)

      這種分割方式一般來(lái)說(shuō)是通過(guò)對(duì)表的垂直劃分來(lái)減少目標(biāo)表的寬度,使某些特定的列被劃分到特定的分區(qū),每個(gè)分區(qū)都包含了其中的列所對(duì)應(yīng)的行。

      在數(shù)據(jù)庫(kù)供應(yīng)商開(kāi)始在他們的數(shù)據(jù)庫(kù)引擎中建立分區(qū)(主要是水平分區(qū))時(shí),DBA和建模者必須設(shè)計(jì)好表的物理分區(qū)結(jié)構(gòu),不要保存冗余的數(shù)據(jù)(不同表中同時(shí)都包含父表中的數(shù)據(jù))或相互聯(lián)結(jié)成一個(gè)邏輯父對(duì)象(通常是視圖)。這種做法會(huì)使水平分區(qū)的大部分功能失效,有時(shí)候也會(huì)對(duì)垂直分區(qū)產(chǎn)生影響。

      分表的好處

      性能的提升(Increased performance)- 在掃描操作中,如果MySQL的優(yōu)化器知道哪個(gè)分區(qū)中才包含特定查詢中需要的數(shù)據(jù),它就能直接去掃描那些分區(qū)的數(shù)據(jù),而不用浪費(fèi)很多時(shí)間掃描不需要的地方了。需要舉個(gè)例子?好啊,百萬(wàn)行的表劃分為10個(gè)分區(qū),每個(gè)分區(qū)就包含十萬(wàn)行數(shù)據(jù),那么查詢分區(qū)需要的時(shí)間僅僅是全表掃描的十分之一了,很明顯的對(duì)比。同時(shí)對(duì)十萬(wàn)行的表建立索引的速度也會(huì)比百萬(wàn)行的快得多得多。如果你能把這些分區(qū)建立在不同的磁盤上,這時(shí)候的I/O讀寫(xiě)速度就“不堪設(shè)想”;

      對(duì)數(shù)據(jù)管理的簡(jiǎn)化(Simplified data management)- 分區(qū)技術(shù)可以讓DBA對(duì)數(shù)據(jù)的管理能力提升。通過(guò)優(yōu)良的分區(qū),DBA可以簡(jiǎn)化特定數(shù)據(jù)操作的執(zhí)行方式。例如:DBA在對(duì)某些分區(qū)的內(nèi)容進(jìn)行刪除的同時(shí)能保證余下的分區(qū)的數(shù)據(jù)完整性(這是跟對(duì)表的數(shù)據(jù)刪除這種大動(dòng)作做比較的)。

      (8)高可用的一些手段

      任務(wù)調(diào)度系統(tǒng)分布式:elastic-job組件 + zookeeper;

      主備切換:Apache curator + zookeeper分布式鎖;

      監(jiān)控報(bào)警機(jī)制。詳情參看: https://www.imooc.com/article/20891?業(yè)務(wù)相關(guān)監(jiān)控報(bào)警系統(tǒng)

      Java 任務(wù)調(diào)度 多線程

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。

      上一篇:制造業(yè)生產(chǎn)車間管理系統(tǒng)圖(制造業(yè)生產(chǎn)車間管理系統(tǒng)圖片)
      下一篇:云表格下載(云表格在線登錄)
      相關(guān)文章
      亚洲成AV人在线观看网址| 亚洲中文字幕无码av| 另类专区另类专区亚洲| 亚洲AV无码之国产精品| 亚洲欧洲无码AV不卡在线| youjizz亚洲| 亚洲一区电影在线观看| 亚洲伊人久久大香线蕉啊| 亚洲国产av美女网站| 亚洲最大的视频网站| 亚洲一级免费毛片| 亚洲a级片在线观看| 亚洲中文字幕无码一去台湾| 77777亚洲午夜久久多喷| 在线观看亚洲AV日韩AV| 亚洲日本VA中文字幕久久道具| 亚洲人成色在线观看| 亚洲av永久无码精品秋霞电影秋| 豆国产96在线|亚洲| 亚洲成a人片在线播放| 亚洲色偷偷狠狠综合网| 超清首页国产亚洲丝袜| 国产亚洲成av人片在线观看| 香蕉蕉亚亚洲aav综合| 97亚洲熟妇自偷自拍另类图片| 亚洲视频小说图片| 亚洲人成人77777在线播放| 国产精品亚洲综合五月天| 亚洲欧美日韩久久精品| 色欲色欲天天天www亚洲伊| 亚洲av中文无码| 国产日产亚洲系列| 久久久久亚洲av无码尤物| 亚洲美女aⅴ久久久91| 亚洲娇小性色xxxx| 亚洲AV无码AV吞精久久| 国产亚洲精品免费视频播放| 国产aⅴ无码专区亚洲av| 久久亚洲日韩精品一区二区三区| 亚洲色偷偷偷网站色偷一区| 国产91在线|亚洲|