日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

为什么 Kafka 如此之快?

發(fā)布時間:2025/3/21 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 为什么 Kafka 如此之快? 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

【CSDN編者按】:Kafka的設計者和維護者設計了一個非常優(yōu)秀的、以性能為主的方案。不論是將工作量交個客戶端,還是代理的日志式架構(gòu),甚至是批處理、壓縮、零復制I/O和流式并行,Kafka幾乎打敗了所有面向消息的中間件,不論是商業(yè)的還是開源的。

作者 | Emil Koutanov

譯者 | 彎月

出品 | CSDN(ID:CSDNnews)

以下為譯文:

最近幾年,軟件體系結(jié)構(gòu)領域發(fā)生了巨大的變化。單體應用,乃至共享一個通用數(shù)據(jù)存儲的多個服務的概念已從軟件從業(yè)者的世界消失了。微服務、事件驅(qū)動的體系結(jié)構(gòu)以及CQRS成了構(gòu)建以業(yè)務為中心的現(xiàn)代化應用程序的主要工具。而在這之上,則是物聯(lián)網(wǎng)、移動設備、可穿戴設備等設備連接的激增,系統(tǒng)必須實時處理的事件數(shù)量的壓力也增大了。

首先,我們必須承認“快速”這個詞涉及的方面很廣泛,很復雜,而且比較模糊。延遲、吞吐量和抖動等都是人們衡量“快速”的決定性指標。快速本身也要考慮上下文關系,各個行業(yè)和應用程序領域都有特定的規(guī)范和期望值。快慢的判斷很大程度上取決于相應的參照系。

Apache Kafka針對吞吐量進行了優(yōu)化,但犧牲了延遲和抖動,同時保留了其他所需的品質(zhì),比如持久性、嚴格的記錄順序以及“至少一次”的交付語義。當有人說“Kafka很快”,并假設它們具備一定的能力時,你可以認為他們指的是Kafka在短時間內(nèi)安全地積累和分發(fā)大量記錄的能力。

究其歷史,Kafka的誕生是因為LinkedIn的需求,因為他們需要有效地移動大量的消息,每小時的數(shù)據(jù)總量達數(shù)TB。一條消息的傳播延遲倒是次要的。畢竟,LinkedIn不是從事高頻交易的金融機構(gòu),也不是有明確截止期限的工業(yè)控制系統(tǒng)。我們可以利用Kafka實現(xiàn)近乎實時(又名軟實時)的系統(tǒng)。?

注意:有些人可能對實時這個術語不太熟悉,“實時”并不意味著“快速”,它的意思是“可預測”。具體而言,實時意味著完成動作所需花費的時間有硬性上線,即截止期限。如果系統(tǒng)整體每次都無法滿足截止期限,則不能稱其為實時系統(tǒng)。能夠在一定概率公差范圍內(nèi)完成操作的系統(tǒng)稱為“近乎實時”。單從吞吐量看來,一般實時系統(tǒng)都比近乎實時或非實時系統(tǒng)慢。

為了提高速度,Kafka做了兩方面的努力,下面我們來分別討論。第一個關系到客戶端與代理之間的低效;第二個源于流處理的機會并行性。

代理的性能

日志結(jié)構(gòu)的持久性

Kafka利用分段式追加日志,將大部分讀寫都限制為順序I / O,這種方式在各種存儲介質(zhì)上的讀寫速度都非常快。人們普遍認為磁盤的讀寫速度很慢,但實際上存儲介質(zhì)(尤其是旋轉(zhuǎn)介質(zhì))的性能很大程度上取決于訪問模式。常見的7,200 RPM SATA磁盤上的隨機I / O的性能要比順序I / O慢3~4個數(shù)量級。此外,現(xiàn)代操作系統(tǒng)提供了預讀和延遲寫入技術,可以預先取出大塊的數(shù)據(jù),并將較小的邏輯寫入組合成較大的物理寫入。因此,即使在閃存和其他形式的固態(tài)非易失性介質(zhì)中,隨機I/O和順序I/O的差異仍然很明顯,盡管與旋轉(zhuǎn)介質(zhì)相比,這種差異性已經(jīng)很小了。

記錄批處理

在大多數(shù)媒體類型上,順序I / O的速度非常快,可與網(wǎng)絡I / O的峰值性能相媲美。在實踐中,這意味著精心設計的日志結(jié)構(gòu)持久層能夠跟上網(wǎng)絡流量的速度。實際上,Kafka的瓶頸通常不在于磁盤,而是網(wǎng)絡。因此,除了操作系統(tǒng)提供的低級批處理外,Kafka客戶和代理還會將讀寫的多個記錄打包成批次,然后再通過網(wǎng)絡發(fā)送。記錄的批處理通過使用更大的數(shù)據(jù)包,以及提高帶寬效率來分攤網(wǎng)絡往返的開銷。

批量壓縮

啟用壓縮后,批處理的影響將更為明顯,因為隨著數(shù)據(jù)量的增加,壓縮會更加有效。尤其是當使用基于文本的格式(如JSON)時,壓縮的效果會非常明顯,壓縮率通常會到5~7倍之間。此外,記錄的批處理大部分是在客戶端完成的,它將負載轉(zhuǎn)移到客戶端上,不僅可以減輕網(wǎng)絡帶寬的壓力,而且對代理的磁盤I / O利用率也有積極的影響。

廉價的消費者

傳統(tǒng)的MQ風格的代理程序會在消費消息的時候刪除消息(會導致隨機I / O的性能下降),Kafka與之不同,它不會在使用過后刪除消息,它會按照每個消費者組單獨跟蹤偏移量。偏移量的進度本身發(fā)布在Kafka的內(nèi)部主題__consumer_offsets上。同樣,由于這是一個僅追加的操作,所以速度非常快。在后臺,這個主題的內(nèi)容將進一步減少(使用Kafka的壓縮功能),僅保留消費者組的最新已知偏移量。

我們來比較一下該模型與更傳統(tǒng)的消息代理(這些代理通常都會提供多種不同的消息分發(fā)拓撲)。一方面是消息隊列(一種持久的傳輸,用于點對點消息傳遞,沒有點對多點的功能。)另一方面,pub-sub主題允許點對多點消息傳遞,但犧牲了持久性。在傳統(tǒng)的MQ中實現(xiàn)持久的點對多點消息傳遞模型需要為每個有狀態(tài)的消費者維護一個專用的消息隊列。這會放大讀寫量。一方面,發(fā)布者不得不寫入多個隊列。或者,扇出中繼可能會從一個隊列中消費記錄,并寫入幾個其他隊列,但這只是把讀寫放大的點推遲了而已。另一方面,多個消費者會在代理上產(chǎn)生負載,這些負載既包含順序I / O的讀寫,也包含隨機I / O的讀寫。

只要Kafka中的消費者不更改日志文件(僅允許生產(chǎn)者或內(nèi)部Kafka進程更改日志文件),它們就很“廉價”。這意味著大量的消費者可以同時讀取同一主題,而不會占用過多的集群。雖然添加消費者還是需要付出一些代價,但是大多都是順序讀取,加上極少量的順序?qū)懭搿R虼?#xff0c;多個消費者生態(tài)系統(tǒng)共享一個主題是很正常的。

未刷新的緩沖寫入

Kafka高性能的另一個根本原因(也是值得進一步探討的原因)在于,在確認寫入之前,Kafka在寫入磁盤時實際上并不會調(diào)用fsync。ACK唯一的要求就是記錄已被寫入I / O緩沖區(qū)。這一點鮮為人知,但至關重要,正是因為這一點,Kafka的操作就像是一個內(nèi)存隊列一樣,因為Kafka的目標就是由磁盤支持的內(nèi)存隊列(規(guī)模由緩沖區(qū)/頁面緩存的大小決定)。

另一方面,這種寫入的形式是不安全的,因為即使看似記錄已被確認,副本出問題也可能導致數(shù)據(jù)丟失。換句話說,與關系數(shù)據(jù)庫不同,僅承認寫入并不意味著持久性。保證Kafka持久的原因在于它運行了多個同步副本。即使其中一個出現(xiàn)問題,其他副本也將繼續(xù)運行,當然前提是其他副本沒有受影響(有時,某個常見的上游故障可能會導致多個副本同時出問題)。因此,無fsync的I / O非阻塞方法與冗余的同步副本的結(jié)合保證了Kafka的高吞吐量、持久性和可用性。

客戶端優(yōu)化

大多數(shù)數(shù)據(jù)庫、隊列以及其他形式的持久性中間件的設計理念中,都有一個全能的服務器(或服務器集群),加上多個瘦客戶端,兩者之間通過常見的通信協(xié)議通信。通常我們認為,客戶端的實現(xiàn)難度遠低于服務器端。因此,服務器承擔了大部分負載,而客戶端僅充當應用程序代碼和服務器之間的接口。

Kafka的客戶端設計采用了不同的方法。在記錄到達服務器之前,客戶端需要執(zhí)行大量操作,包括將記錄暫存到收集器中,對記錄的鍵進行哈希處理以獲得正確的分區(qū)索引,對記錄進行校驗以及對批次進行壓縮。客戶端掌握了集群的元數(shù)據(jù),并會定期刷新這些元數(shù)據(jù),以了解代理拓撲的變化。因此,客戶端可以決定底層的轉(zhuǎn)發(fā),生產(chǎn)者客戶端不會將記錄盲目地發(fā)給集群,并依賴集群將記錄轉(zhuǎn)發(fā)到合適的代理節(jié)點,而是直接將寫入轉(zhuǎn)發(fā)給分區(qū)的主服務器。同樣,消費者客戶在選擇記錄源時也可以做一些智能處理,例如在發(fā)送讀取查詢時,選擇地理位置更接近的副本。(此功能是Kafka的新功能,自2.4.0版開始提供。)

零復制

最常見的低效處理來自緩沖區(qū)之間的字節(jié)數(shù)據(jù)復制。Kafka的生產(chǎn)者、代理和消費者之間共享了同樣的二進制消息格式,因此數(shù)據(jù)塊即使經(jīng)過壓縮,在端與端之間流動時也無需進行任何修改。盡管消除通信雙方的結(jié)構(gòu)差異是很重要的一步,但它本身并不能避免數(shù)據(jù)復制。

為了在Linux和UNIX系統(tǒng)上解決了此問題,Kafka使用了Java的NIO框架,特別是java.nio.channels.FileChannel的方法transferTo()。我們可以通過這種方法,將字節(jié)從源通道傳輸?shù)浇邮掌魍ǖ?#xff0c;而無需將應用程序作為傳輸中介。為了說明NIO的不同之處,我們可以考慮一下傳統(tǒng)的方法:將源通道讀取到字節(jié)緩沖區(qū)中,然后作為兩個單獨的操作寫入到接收器通道中:

  • File.read(fileDesc, buf, len);
  • Socket.send(socket,?buf,?len);
  • 流程圖大致如下:

    盡管看起來很簡單,但是在內(nèi)部,復制操作需要在用戶模式和內(nèi)核模式之間進行4次上下文切換,而在操作完成之前數(shù)據(jù)將被復制4次。下圖概述了每個步驟的上下文切換。

    詳細來說:

    • 首先,read()需要將上下文從用戶模式切換到內(nèi)核模式。讀取文件,然后通過DMA引擎(直接內(nèi)存訪問)將文件內(nèi)容復制到內(nèi)核地址空間的緩沖區(qū)中。這與上述代碼中使用的緩沖區(qū)不同。

    • 在read()返回之前,將內(nèi)核緩沖區(qū)復制到用戶空間緩沖區(qū)。此時,我們的應用程序可以讀取文件的內(nèi)容。

    • 后續(xù)的send()需要切換回內(nèi)核模式,將用戶空間緩沖區(qū)復制到內(nèi)核地址空間,這次復制到與目標套接字關聯(lián)的另一個緩沖區(qū)。在背后,由DMA引擎接管,將數(shù)據(jù)從內(nèi)核緩沖區(qū)異步復制到協(xié)議棧。send()無需等待此操作即可返回。

    • send()調(diào)用返回,切換到用戶空間上下文。

    盡管這種模式存在切換效率低下和額外復制的問題,但在許多情況下,中間內(nèi)核緩沖區(qū)實際上可以提高性能。它可以充當預讀緩存和異步預取塊,因此可以預先運行來自應用程序的請求。但是,當請求的數(shù)據(jù)量明顯大于內(nèi)核緩沖區(qū)的大小時,內(nèi)核緩沖區(qū)就會成為性能瓶頸。它不是直接復制數(shù)據(jù),而是迫使系統(tǒng)在用戶和內(nèi)核模式之間來回切換,直到所有數(shù)據(jù)傳輸完為止。

    相比之下,單個操作可以采用零復制的方法。上述示例中的代碼可以改寫成一行:

    fileDesc.transferTo(offset, len, socket);

    如下是零復制的方法:

    在這個模型中,上下文切換的次數(shù)減少到了一次。具體來說,就是transferTo()方法指示塊設備通過DMA引擎將數(shù)據(jù)讀取到緩沖區(qū)中。然后,將該緩沖區(qū)復制到另一個內(nèi)核緩沖區(qū),供套接字使用。最后,套接字緩沖區(qū)通過DMA復制到NIC緩沖區(qū)。

    最終結(jié)果,我們的副本數(shù)目從4個減少到了3個,而其中只有一個副本需要CPU。我們還將上下文切換的次數(shù)從4個減少到了2個。

    這是一個巨大的提升,但還不是真正的查詢零復制。在運行Linux內(nèi)核2.4及更高版本,并且網(wǎng)卡支持gather操作的情況下,就可以實現(xiàn)查詢零復制,作為進一步的優(yōu)化來實現(xiàn)。如下所示。?

    根據(jù)前面的示例,調(diào)用transferTo()時,設備會通過DMA引擎將數(shù)據(jù)讀入內(nèi)核讀取緩沖區(qū)。但是,使用gather 操作時,讀取緩沖區(qū)和套接字緩沖區(qū)之間不需要復制數(shù)據(jù)。NIC會得到一個指向讀取緩沖區(qū)的指針以及偏移量和長度,然后可以通過DMA直接讀取。在任何時候,CPU都不需要復制緩沖區(qū)。

    傳統(tǒng)方式與零復制方式(文件大小范圍從幾兆字節(jié)到千兆字節(jié))的比較結(jié)果表明。零復制的性能提高了2~3倍。但更令人驚訝的是,Kafka僅使用了普通的JVM就實現(xiàn)了該功能,沒有用到任何原生庫或JNI代碼。

    避免垃圾收集

    大量使用通道、原生緩沖區(qū)和頁面緩存還有另一個好處:減少了垃圾收集器(garbage collector,GC)的負載。例如,在擁有32GB內(nèi)存的計算機上運行Kafka,就有28~30GB的頁面緩存可用,這完全超出了GC的范圍。吞吐量的差異很小(在幾個百分點左右),因為經(jīng)過正確地微調(diào)后,GC的吞吐量可以達到很高,尤其是在處理短期對象時。真正的收益在于抖動的減少:避免使用GC,代理可以減少可能會影響到客戶端的暫停,延長記錄端到端傳播的延遲。

    平心而論,對于Kafka來說,與最初的設想時相比,如今避免使用GC已不再是一個問題。Shenandoah和ZGC等現(xiàn)代GC可以擴展到數(shù)TB,并且其最壞情況下的暫停時間是可調(diào)節(jié)的,最低可以調(diào)節(jié)到幾毫秒。如今,對于基于JVM的應用程序來說,使用大型基于堆的緩存的效果遠勝于不采用堆的設計。

    流并行

    日志結(jié)構(gòu)I / O的效率是影響性能的關鍵方面,主要影響在于寫入。Kafka對主題結(jié)構(gòu)以及消費者生態(tài)系統(tǒng)中并行性的處理是其讀取性能的基礎。這種組合產(chǎn)生了很高的端到端消息傳遞吞吐量。并發(fā)根植于它的分區(qū)方案與用戶組的操作中,它實際上是Kafka的負載平衡機制:在組內(nèi)的各個用戶實例之間均勻地分配分區(qū)配額。比較一下傳統(tǒng)的MQ:在同等的RabbitMQ設置中,多個并發(fā)消費者以循環(huán)方式從隊列中讀取,但這種做法丟掉了消息排序的概念。

    分區(qū)機制還為Kafka代理帶來了水平可伸縮性。每個分區(qū)都有專門的主節(jié)點,因此,任何重大主題(具有多個分區(qū))都可以利用代理的整個集群執(zhí)行寫操作。這是Kafka和消息隊列之間的又一個區(qū)別,后者利用集群來提高可用性,而Kafka可以平衡代理之間的負載,并提高可用性、持久性和吞吐量。

    如果你打算發(fā)布擁有多個分區(qū)的主題,那么生產(chǎn)者需要在發(fā)布記錄時指定分區(qū)。(只有一個分區(qū)的主題沒有這種問題。)實現(xiàn)方法有兩種:直接的方式(指定分區(qū)索引)和間接的方式(通過記錄鍵的方式,該鍵可以通過哈希生成唯一的分區(qū)索引)。擁有同樣哈希的記錄會占據(jù)同一個分區(qū)。假設一個主題具有多個分區(qū),則具有不同鍵的記錄可能也會位于不同的分區(qū)中。但是,由于哈希沖突,具有不同哈希值的記錄也可能會在同一個分區(qū)中。這就是哈希的本質(zhì)。如果你了解哈希表的運作方式,就會發(fā)現(xiàn)這正是哈希表的原理。

    實際的記錄處理由消費者負責,在一個消費者組(可選)內(nèi)進行操作。Kafka可以保證分區(qū)最多只能指定給一個消費者組內(nèi)的一個消費者。(我們說“最多”是考慮到可能所有消費者都離線的情況。)當組中的第一個消費者訂閱該主題時,它會收到該主題上的所有分區(qū)。當?shù)诙€消費者加入時,它會收到大約一半的分區(qū),從而降低了第一個消費者的大約一半的負擔。這樣,只要你的事件流中有足夠多的分區(qū),就能并行處理事件流,根據(jù)需要添加消費者(最好使用自動伸縮機制)。

    控制記錄的吞吐量可以通過兩個途徑完成:

  • 主題分區(qū)架構(gòu)。主題應該按照獨立事件子流的最大數(shù)量分區(qū)。換句話說,記錄的順序只有在絕對必要的時候才需要保證。如果任何兩個記錄都不相關,那么不應該被綁定到同一個分區(qū)。這就需要使用不同的鍵,因為Kafka使用記錄的鍵作為哈希的來源,以保證分區(qū)映射的一致性。

  • 組內(nèi)的消費者數(shù)量。你可以增加消費者數(shù)量來匹配輸入記錄的負載,最大等于主題中的分區(qū)數(shù)量。(你甚至可以擁有多個消費者,但能夠獲得至少一個分區(qū)的活躍消費者數(shù)量的上限就是分區(qū)數(shù)量,其余的消費者只能處于閑置狀態(tài)。)注意消費者可以是進程或線程。根據(jù)消費者的負載類型,你可以采用多個獨立的消費者線程,或者在線程池中處理記錄。

  • 如果你想知道為什么Kafka這么快,它的性能特性是怎樣實現(xiàn)的,或者怎樣才能伸縮你的集群,那么看完這篇文章,你就應該得到答案了。

    更明確地說,Kafka并不是最快的(即并不是吞吐量最大的)消息中間件,有些平臺的吞吐量更大,其中有軟件實現(xiàn)的也有硬件實現(xiàn)的。Kafka對于吞吐量與延遲之間的平衡處理也算不上最好的,Apache Pulsar的吞吐量平衡性更好,還能提供順序一致性和可靠性保證。選擇Kafka的原因作為整個生態(tài)系統(tǒng)的原因是,從整體上來說它還沒有對手。它展示了優(yōu)異的性能,同時還提供了龐大、成熟且一直在進步的社區(qū)。

    Kafka的設計者和維護者設計了一個非常優(yōu)秀的、以性能為主的方案。其設計幾乎沒有任何返工或補丁的跡象。不論是將工作量交個客戶端,還是代理的日志式架構(gòu),甚至是批處理、壓縮、零復制I/O和流式并行,Kafka幾乎打敗了所有面向消息的中間件,不論是商業(yè)的還是開源的。更精彩的是,這些實現(xiàn)沒有在持久性、記錄順序、“至少一次”傳輸語義等質(zhì)量方面做出任何妥協(xié)。

    作為消息平臺,Kafka并不簡單,需要學習許多知識才能掌握。你必須理解全序和偏序、主題、分區(qū)、消費者、消費者組等概念,才能毫無障礙地設計并構(gòu)建一個高性能的事件驅(qū)動系統(tǒng)。盡管學習曲線陡峭,但結(jié)果非常值得。

    原文鏈接:https://medium.com/swlh/why-kafka-is-so-fast-bde0d987cd03

    聲明:本文由CSDN翻譯,轉(zhuǎn)載請說明來源。


    CSDN協(xié)同行業(yè)大佬,攜手打造13長熱門知識圖譜及IT成長路線,助力千萬IT人成長,快速實現(xiàn)職場進階!

    總結(jié)

    以上是生活随笔為你收集整理的为什么 Kafka 如此之快?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 麻豆污视频 | 91福利在线观看视频 | 亚洲欧洲日韩国产 | 日韩精品第一页 | 欧美 日韩 中文 | 国产又粗又猛又黄又爽无遮挡 | 欧美亚洲综合网 | 国产高清视频一区二区 | 成人动漫在线播放 | 日韩图片区 | 欧美变态视频 | 亚洲图片一区二区 | 69视频免费在线观看 | 高h av | 精品国产av无码一区二区三区 | 肉色超薄丝袜脚交一区二区 | 日韩在线 中文字幕 | 欧美日韩精品一二三区 | 久久久亚洲一区 | 欧美日本免费 | 爱操综合| 人妻少妇精品无码专区久久 | 欧美日韩视频 | 欧美日韩另类视频 | 狠狠操天天射 | 黄色网址进入 | 午夜18视频在线观看 | 熟妇高潮喷沈阳45熟妇高潮喷 | av一级 | 久久久亚洲一区二区三区 | 66精品| 日本黄色大片在线观看 | 免费一级淫片 | 久久九九视频 | 国产乱了高清露脸对白 | 黑人性高潮 | 高潮爽爆喷水h | 日韩精品 欧美 | 999av| 欧美激情18 | 国内激情 | 视频二区在线 | 国产欧美一区二区三区精品酒店 | 亚洲av成人无码久久精品老人 | 国产夫妻久久 | 亚洲精品乱码久久久久久蜜桃91 | 日韩精品在线观看免费 | 亚洲天堂精品视频 | 精品中文一区二区三区 | 天堂在线视频免费观看 | 女生被男生桶 | 99热3| av资源网址 | 免费成人美女在线观看 | 国产美女操 | 中文字字幕一区二区三区四区五区 | 国产第100页 | 一区二区三区不卡视频 | 亚洲麻豆一区二区三区 | 白石茉莉奈中文字幕在 | 亚洲区国产区 | 麻豆自拍视频 | 日韩精品久久久久久久酒店 | 少妇高潮惨叫久久久久 | 午夜粉色视频 | 视频一区 中文字幕 | 青娱乐伊人 | 欧美性猛交xxxx黑人 | 中文字幕在线观看三区 | av狠狠 | 欧美日韩国产片 | 91重口味 | 欧美视频网址 | 69er小视频 | 超碰95在线| 亚洲精品一区二区三区婷婷月 | 免费a网址 | 自拍偷拍电影 | 不卡的中文字幕 | 波多野结衣a级片 | 日本天堂一区 | 天天爱天天操 | 东京热一区二区三区四区 | 国产999精品 | 久久网一区二区 | www国产亚洲精品 | 国产精品五区 | 国产精品日 | 国产精品一区二区三区在线 | 国产女大学生av | 成人黄色在线 | 亚洲一区二区三区综合 | 国内精品嫩模av私拍在线观看 | 123超碰| 成人午夜在线观看视频 | 国产综合欧美 | 亚洲天堂av在线免费观看 | 99国产精品久久 | 成人激情视频 |