溫馨提示×

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

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Hadoop中的數(shù)據(jù)傾斜是什么意思

發(fā)布時(shí)間:2021-12-09 14:00:10 來源:億速云 閱讀:156 作者:小新 欄目:云計(jì)算

小編給大家分享一下Hadoop中的數(shù)據(jù)傾斜是什么意思,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

    在并行計(jì)算中我們總希望分配的每一個(gè)task 都能以差不多的粒度來切分并且完成時(shí)間相差不大,但是集群中可能硬件不同,應(yīng)用的類型不同和切分的數(shù)據(jù)大小不一致總會(huì)導(dǎo)致有部分任務(wù)極大的拖慢了整個(gè)任務(wù) 的完成時(shí)間,硬件不同就不說了,應(yīng)用的類型不同其中就比如page rank 或者data mining 里面一些計(jì)算,它的每條記錄消耗的成本不太一樣,這里只討論關(guān)于關(guān)系型運(yùn)算的(一般能用SQL表述的) 數(shù)據(jù)切分上的數(shù)據(jù)傾斜問題.

    hadoop 中數(shù)據(jù)傾斜會(huì)極大影響性能的一個(gè)背景是mapreduce 框架中總是不分條件的進(jìn)行sort . 在通用情況下map sort + partition +reduce sort 可以得到結(jié)果,但是這個(gè)過程不一定是最優(yōu)的.  對(duì)于關(guān)系型計(jì)算,其中數(shù)據(jù)傾斜影響最大的地方在reduce 的sort , reduce 處理的數(shù)據(jù)量的大小如果超過給定的reduce jvm 的大小的2倍不到的閾值的時(shí)候(這個(gè)閾值是我猜測(cè)的,具體以實(shí)際監(jiān)控運(yùn)行情況為準(zhǔn)),reduce 端會(huì)發(fā)生multi-pass merge sort 的情況, 這個(gè)時(shí)候觀察這些運(yùn)行較慢的reduce task 的metrics 會(huì)發(fā)現(xiàn)reduce 跟IO 相關(guān)的metrics 會(huì)比其他reduce 大很多. 具體的細(xì)節(jié)參考今年hadoop summit 上Todd 的performance tuning 的ppt (26頁):

http://www.slideshare.net/cloudera/mr-perf

這種在reduce 端不分條件的排序只是hadoop 是這種實(shí)現(xiàn),并不是mapreduce 框架一定需要排序,其他的mapreduce 實(shí)現(xiàn)或者其他的分布式計(jì)算框架可能在reduce 上的這種瓶頸會(huì)小一些, 比如shark 里面的group by 就是基于hash 而不是sort 的.

    對(duì)于關(guān)系型的計(jì)算中常見的數(shù)據(jù)傾斜有兩種:group by 和 join , 其他有可能的有:

in或exists 的操作尤其是in或exists 作為subquery 的返回(in 或exists 有時(shí)候會(huì)變成left semi join),

有相同輸入源的union 或union all 也許也會(huì)有(其他集合類型的操作intersect 之類也許也是). 

hive 中的udtf 也算一種.

這里只討論最常見的group by 和join 的情況.

數(shù)據(jù)分布:

    正常的數(shù)據(jù)分布理論上都是傾斜的,就是我們所說的20-80原理:80%的財(cái)富集中在20%的人手中, 80%的用戶只使用20%的功能 , 20%的用戶貢獻(xiàn)了80%的訪問量 , 不同的數(shù)據(jù)字段可能的數(shù)據(jù)傾斜一般有兩種情況:

一種是唯一值非常少,極少數(shù)值有非常多的記錄值(唯一值少于幾千)

一種是唯一值比較多,這個(gè)字段的某些值有遠(yuǎn)遠(yuǎn)多于其他值的記錄數(shù),但是它的占比也小于百分之一或千分之一

分區(qū):

常見的mapreduce分區(qū)方式為hash 和range ,

hash partition 的好處是比較彈性,跟數(shù)據(jù)類型無關(guān),實(shí)現(xiàn)簡單(設(shè)定reduce個(gè)數(shù)就好,一般不需要自己實(shí)現(xiàn))

range partition 需要實(shí)現(xiàn)者自己了解數(shù)據(jù)分布, 有時(shí)候需要手工做sample取樣. 同時(shí)也不夠彈性, 表現(xiàn)在幾個(gè)方面,1. 對(duì)同一個(gè)表的不同字段都需要實(shí)現(xiàn)不同的range partition,  對(duì)于時(shí)間這種字段根據(jù)查詢類型的不同或者過濾條件的不同切分range 的大小都不一定.

2 .有時(shí)候可能設(shè)計(jì)使用多個(gè)字段組合的情況, 這時(shí)候又不能使用之前單個(gè)字段的partition 類, 并且多個(gè)字段組合之間有可能有隱含的聯(lián)系,比如出生日期和星座,商品和季節(jié).

3. 手工做sample 非常耗時(shí)間,需要使用者對(duì)查詢使用的數(shù)據(jù)集的分布有領(lǐng)域知識(shí).

4. 分配方式是死的,reduce 個(gè)數(shù)是確定的,一旦某種情況下發(fā)生傾斜,調(diào)整參數(shù)

其他的分區(qū)類型還有hbase 的hregionpartitioner  或者totalorder partitioner  等.

能夠想到的關(guān)于數(shù)據(jù)傾斜的一些解決方式(歡迎補(bǔ)充,尤其是有沒有做搜索或者數(shù)據(jù)挖掘的朋友有碰到類似問題):

1. 增加reduce 的jvm內(nèi)存

2. 增加reduce 個(gè)數(shù)

3. customer partition

4. 其他優(yōu)化的討論.

5. reduce sort merge排序算法的討論

6. 正在實(shí)現(xiàn)中的hive skewed join.

7. pipeline

8. distinct

9. index 尤其是bitmap index

方式1:既然reduce 本身的計(jì)算需要以合適的內(nèi)存作為支持,在硬件環(huán)境容許的情況下,增加reduce 的內(nèi)存大小顯然有改善數(shù)據(jù)傾斜的可能,這種方式尤其適合數(shù)據(jù)分布第一種情況,單個(gè)值有大量記錄, 這種值的所有紀(jì)錄已經(jīng)超過了分配給reduce 的內(nèi)存,無論你怎么樣分區(qū)這種情況都不會(huì)改變. 當(dāng)然這種情況的限制也非常明顯, 1.內(nèi)存的限制存在,2.可能會(huì)對(duì)集群其他任務(wù)的運(yùn)行產(chǎn)生不穩(wěn)定的影響.

方式2:  這個(gè)對(duì)于數(shù)據(jù)分布第二種情況有效,唯一值較多,單個(gè)唯一值的記錄數(shù)不會(huì)超過分配給reduce 的內(nèi)存. 如果發(fā)生了偶爾的數(shù)據(jù)傾斜情況,增加reduce 個(gè)數(shù)可以緩解偶然情況下的某些reduce 不小心分配了多個(gè)較多記錄數(shù)的情況. 但是對(duì)于第一種數(shù)據(jù)分布無效.

方式3: 一種情況是某個(gè)領(lǐng)域知識(shí)告訴你數(shù)據(jù)分布的顯著類型,比如hadoop definitive guide 里面的溫度問題,一個(gè)固定的組合(觀測(cè)站點(diǎn)的位置和溫度) 的分布是固定的, 對(duì)于特定的查詢?nèi)绻懊鎯煞N方式都沒用,實(shí)現(xiàn)自己的partitioner 也許是一個(gè)好的方式.

方式4: 目前有的一些針對(duì)數(shù)據(jù)傾斜的優(yōu)化比如pig 的skewed join

http://pig.apache.org/docs/r0.7.0/piglatin_ref1.html#Skewed+Joins

pig 文檔上面說是根據(jù)數(shù)據(jù)輸入的統(tǒng)計(jì)信息來確定分區(qū)(也就是range partition?),另外不清楚這個(gè)行為是否是動(dòng)態(tài)運(yùn)行時(shí)候才決定的,也就是運(yùn)行之前有一步pig 自動(dòng)做sample 的工作,因?yàn)閜ig 是沒有統(tǒng)計(jì)信息這一說的.

hive 中的group by

<property> 
  <name>hive.groupby.skewindata</name> 
  <value>false</value> 
  <description>Whether there is skew in data to optimize group by queries</description> 
</property> 
<property> 
  <name>hive.optimize.groupby</name> 
  <value>true</value> 
  <description>Whether to enable the bucketed group by from bucketed partitions / tables.</description> 
</property>

<property> 
  <name>hive.mapjoin.followby.map.aggr.hash.percentmemory</name> 
  <value>0.3</value> 
  <description>Portion of total memory to be used by map-side grup aggregation hash table, when this group by is followed by map join</description> 
</property> 
<property> 
  <name>hive.groupby.mapaggr.checkinterval</name> 
  <value>100000</value> 
  <description>Number of rows after which size of the grouping keys/aggregation classes is performed</description> 
</property>

其中最后一個(gè)參數(shù)hive.groupby.mapaggr.checkinterval 的思路跟in-memory combiner 相似, in-memeory combiner  是發(fā)生在mapper 端sort 之前,而不是現(xiàn)在的combiner發(fā)生在mapper sort 之后甚至在寫入磁盤之后重新讀磁盤然后排序合并. in-memeory combiner 最早好像是《Data-Intensive Text Processing with MapReduce》,mapr 去年的介紹ppt 里面好像提到它們也有這個(gè)優(yōu)化. mapper 端減少數(shù)據(jù)的機(jī)會(huì)比reduce 端的要大,所以一般不會(huì)看到reduce 端的combiner 的討論,但是這種思路也有,比如google tenzing 的join 討論里面有一個(gè)prev-next 的小優(yōu)化就是基于reduce 端的combiner, 但那個(gè)前提是基于block shuffle 實(shí)現(xiàn)的基礎(chǔ)上,數(shù)據(jù)已經(jīng)排過序了,所以join 時(shí)候前一條數(shù)據(jù)跟后一條數(shù)據(jù)相同的概率很大.

hive 中的skewed join :  之前的文章已經(jīng)介紹過兩表join 中hive 的幾個(gè)優(yōu)化,其中的skewed join 的類似思路就是上面介紹的skewed 的第二種:增加reduce 的個(gè)數(shù),hive 中是通過判斷閾值如果大于一個(gè)reduce 需要處理的數(shù)據(jù)量,重新起額外的task 來處理這些超額的reduce 本身需要處理的數(shù)據(jù), 這是一種較晚的補(bǔ)救措施,本身hive 開始分區(qū)的時(shí)候已經(jīng)傾斜(partition 的方式不合理), 當(dāng)運(yùn)行的時(shí)候通過運(yùn)行時(shí)監(jiān)控reduce 發(fā)現(xiàn)傾斜的特殊key 然后額外的起task 去處理,效果比較一般,感興趣的同學(xué)可以參考HIVE-3086 里面我和facebook 團(tuán)隊(duì)對(duì)這種優(yōu)化思路的討論. 第六節(jié)我會(huì)討論一下我所認(rèn)為的思路和facebook 正在做的思路之間的差別.

方式5 :  reduce 分配的內(nèi)存遠(yuǎn)小于處理的數(shù)據(jù)量時(shí),會(huì)產(chǎn)生multi-pass sort 的情況是瓶頸,那么就要問

1. 這種排序是有必要的嘛?

2. 是否有其他排序算法或優(yōu)化可以根據(jù)特定情況降低他瓶頸的閾值?

3. map reduce 適合處理這種情況嘛?

關(guān)于問題1. 如果是group by , 那么對(duì)于數(shù)據(jù)分布情況1 ,hash 比sort 好非常多,即使某一個(gè)reduce 比其他reduce 處理多的多的數(shù)據(jù),hash 的計(jì)算方式也不會(huì)差距太大.

問題2. 一個(gè)是如果實(shí)現(xiàn)block shuffle 肯定會(huì)極大的減少排序本身的成本, 另外,如果分區(qū)之后的reduce 不是使用copy –> sort-merge –> reduce 的計(jì)算方式, 在copy 之后將每個(gè)block 的頭部信息保存在內(nèi)存中,不用sort – merge 也可以直接計(jì)算reduce, 只不過這時(shí)候變成了隨機(jī)訪問,而不是現(xiàn)在的sort-merge 之后的順序訪問. block shuffle 的實(shí)現(xiàn)有兩種類型,一種是當(dāng)hadoop 中真正有了列數(shù)據(jù)格式的時(shí)候,數(shù)據(jù)有更大的機(jī)會(huì)已經(jīng)排過序并且按照block 來切分,一般block 為1M ( 可以關(guān)注avro-806 )  , 這時(shí)候的mapper 什么都不做,甚至連計(jì)算分區(qū)的開銷都小了很多倍,直接進(jìn)入reduce 最后一步,第二種類型為沒有列數(shù)據(jù)格式的支持,需要mapper 排序得到之后的block 的最大最小值,reduce 端在內(nèi)存中保存最大最小值,copy  完成后直接用這個(gè)值來做隨機(jī)讀然后進(jìn)行reduce. ( block shuffle  的實(shí)現(xiàn)可以關(guān)注 MAPREDUCE-4039 , hash 計(jì)算可以關(guān)注 MAPREDUCE-1639)

問題3 . map reduce 只有兩個(gè)函數(shù),一個(gè)map 一個(gè) reduce, 一旦發(fā)生數(shù)據(jù)傾斜就是partition 失效了,對(duì)于join 的例子,某一個(gè)key 分配了過多的記錄數(shù),對(duì)于只有一次partittion的機(jī)會(huì),分配錯(cuò)了數(shù)據(jù)傾斜的傷害就已經(jīng)造成了,這種情況很難調(diào)試,但是如果你是基于map- reduce-reduce 的方式計(jì)算,那么對(duì)于同一個(gè)key 不需要分配到同一個(gè)reduce 中,在第一個(gè)reduce 中得到的結(jié)果可以在第二個(gè)reduce 才匯總?cè)ブ?,第二個(gè)reduce 不需要sort – merge 的步驟,因?yàn)榍耙粋€(gè)reduce 已經(jīng)排過序了,中間的reduce 處理的數(shù)據(jù)不用關(guān)心partition 怎么分,處理的數(shù)據(jù)量都是一樣大,而第二個(gè)reduce 又不使用sort-merge 來排序,不會(huì)遇到現(xiàn)在的內(nèi)存大小的問題,對(duì)于skewed join 這種情況瓶頸自然小很多.

方式6:  目前hive 有幾個(gè)正在開發(fā)中的處理skewed join 情況的jira case,  HIVE-3086 , HIVE-3286 ,HIVE-3026 . 簡單介紹一下就是facebook 希望通過手工處理提前枚舉的方式列出單個(gè)傾斜的值,在join 的時(shí)候?qū)⑦@些值特殊列出當(dāng)作map join 來處理,對(duì)于其他值使用原來的方式. 我個(gè)人覺得這太不伸縮了,值本身沒有考慮應(yīng)用過濾條件和優(yōu)化方式之后的數(shù)據(jù)量大小問題,他們提前列出的值都是基于整個(gè)分區(qū)的. join key 如果為組合key 的情況也應(yīng)該沒有考慮,對(duì)metastore 的儲(chǔ)存問題有限制,對(duì)輸入的大表和小表都會(huì)scan 兩次( 一次處理非skew key , 一次處理skew key 做map join), 對(duì)輸出表也會(huì)scan 兩次(將兩個(gè)結(jié)果進(jìn)行merge) , skew key 必須提前手工列出這又存在額外維護(hù)的成本,目前因?yàn)檫€沒有完整的開發(fā)完到能夠投入生產(chǎn)的情況,所以等所有特性處理完了有了文檔在看看這個(gè)處理方式是否有 效,我個(gè)人認(rèn)為的思路應(yīng)該是接著bucked map join 的思路往下走,只不過不用提前處理cluster key 的問題, 這時(shí)候cluster key 的選擇應(yīng)該是join key + 某個(gè)能分散join key 的列, 這等于將大表的同一個(gè)key 的值分散到了多個(gè)不同的reduce 中,而小表的join key 也必須cluster 到跟大表對(duì)應(yīng)的同一個(gè)key , join 中對(duì)于數(shù)據(jù)分布第二種情況不用太難,增加reduce 個(gè)數(shù)就好,主要是第一種,需要大表的join key 能夠分散,對(duì)于同樣join key 的小表又能夠匹配到所有大表中的記錄. 這種思路就是不用掃描大表兩遍或者結(jié)果輸出表,不需要提前手工處理,數(shù)據(jù)是動(dòng)態(tài)sample 的應(yīng)用了過濾條件之后的數(shù)據(jù),而不是提前基于統(tǒng)計(jì)數(shù)據(jù)的不準(zhǔn)確結(jié)果. 這個(gè)基本思路跟tenzing 里面描述的distributed hash join 是一樣的,想辦法切成合適的大小然后用hash 和 map join .

方式7: 當(dāng)同時(shí)出現(xiàn)join 和group 的時(shí)候, 那么這兩個(gè)操作應(yīng)該是以pipeline (管道) 的方式執(zhí)行. 在join 的時(shí)候就可以直接使用group 的操作符減少大量的數(shù)據(jù),而不是等待join 完成,然后寫入磁盤,group 又讀取磁盤做group操作. HIVE-2206 正在做這個(gè)優(yōu)化. hive 里面是沒有pipeline 這個(gè)概念的. 像是cloudera 的crunch 或者twitter 的Scalding 都是有這種概念的.

方式8: distinct 本身就是group by 的一種簡寫,我原先以為count(distinct x)這種跟group by 是一樣的,但是發(fā)現(xiàn)hive 里面distinct 明顯比group by 要慢,可能跟group by 會(huì)有map 端的combiner有關(guān), 另外觀察到hive 在預(yù)估count(distinct x) 的reduce 個(gè)數(shù)比group by 的個(gè)數(shù)要少 , 所以hive 中使用count(distinct x) , 要么盡量把reduce 個(gè)數(shù)設(shè)置大,直接設(shè)置reduce 個(gè)數(shù)或者h(yuǎn)ive.exec.reducers.bytes.per.reducer 調(diào)小,我個(gè)人比較喜歡調(diào)后面一個(gè),hive 目前的reduce 個(gè)數(shù)沒有統(tǒng)計(jì)信息的情況下就是用map端輸入之前的數(shù)值, 如果你是join 之后還用count(distinct x) 的話,這個(gè)默認(rèn)值一般都會(huì)悲劇,如果有where 條件并能過濾一定數(shù)量的數(shù)據(jù),那么默認(rèn)reduce 個(gè)數(shù)可能就還好一點(diǎn). 不管怎樣,多浪費(fèi)一點(diǎn)reduce slot 總比等十幾甚至幾十分鐘要好, 或者轉(zhuǎn)換成group by 的寫法也不錯(cuò),寫成group by 的時(shí)候distributed by 也很有幫助.

方式9: hive 中的index 就是物化視圖,對(duì)于group by 和distinct 的情況等于變成了map 端在做計(jì)算,自然不存在傾斜. 尤其是bitmap index , 對(duì)于唯一值比較少的列優(yōu)勢(shì)更大,不過index 麻煩的地方在于需要判斷你的sql 是不是常用sql , 另外如果create index 的時(shí)候沒有選你查詢的時(shí)候用的字段,這個(gè)index 是不能用的( hive 中是永遠(yuǎn)不可能有DBMS中的用index 去lookup 或者join 原始表這種概念的)

其他建議:

網(wǎng)上能找到的另外一份很好的描述數(shù)據(jù)傾斜的資料是

http://nuage.cs.washington.edu/pubs/opencirrus2011.pdf

里面的map side skew 和expensive record 都不是關(guān)系型計(jì)算中的問題,所以不是這篇文章關(guān)注點(diǎn). 對(duì)于關(guān)系型計(jì)算,其中數(shù)據(jù)傾斜影響最大的地方在reduce 的sort. 這篇文章里面最后總結(jié)的5點(diǎn)好的建議值得參考,

其中第三條需要你知道應(yīng)用combiner 和特殊優(yōu)化方式是否帶來了性能的提升,hive 的map aggr 在數(shù)據(jù)分布情況1效果會(huì)比較好,數(shù)據(jù)分布情況2效果就不大,還有combiner 應(yīng)用的時(shí)候是消耗了系統(tǒng)資源的,確認(rèn)這種消耗是否值得而不是任何情況下都使用combiner. 

對(duì)于第四點(diǎn)關(guān)系型計(jì)算中map 傾斜情況不太常見. 一種可以舉出來的例子是分區(qū)不合理,或者h(yuǎn)ive 中的cluster by 的key 選擇不合理(都是使用目錄的方式分區(qū), 目錄是最小處理單元了).

  • Use domain knowledge when choosing the 
    map output partitioning scheme if the reduce operation is 
    expensive: Range partition or some other form of explicit 
    partition may be better than the default hash-partition

  • Try different partitioning schemes on sample 
    workloads or collect the data distribution at the reduce input 
    if a MapReduce job is expected to run several times

  • Implement a combiner to reduce the amount 
    of data going into the reduce-phase and, as such, significantly 
    dampen the effects of any type of reduce-skew

  • Use a pre-processing MapReduce job that 
    extracts properties of the input data in the case of a longruning, 
    skew-prone map phase. Appropriately partitioning the 
    data before the real application runs can significantly reduce 
    skew problems in the map phase.

  • Best Practice 5. Design algorithms whose runtime depends 
    only on the amount of input data and not the data distribution.

    另外一份是淘寶的數(shù)據(jù)傾斜總結(jié):

    http://www.alidata.org/archives/2109

    不過我個(gè)人覺得幫助不是太大,里面第一個(gè)解決方式空值產(chǎn)生的影響第一個(gè)Union All 的方式個(gè)人是極力反對(duì)的,同一個(gè)表尤其是大表掃描兩遍這額外的成本跟收益太不匹配,不推薦,第二個(gè)將特殊值變成random 的方式, 這個(gè)產(chǎn)生的結(jié)果是正確的嘛? 尤其是在各種情況下輸出結(jié)果是正確的嘛?里面背景好像是那個(gè)小表users 的主鍵為userid, 然后userid 又是join key , 而且還不為空? 不太推薦,背景條件和輸出的正確性與否存疑.

    第二個(gè)數(shù)據(jù)類型不同的問題我覺得跟HIVE-3445 都算是數(shù)據(jù)建模的問題,提前修改好是一樣的.

    第三個(gè)是因?yàn)樘詫毜膆adoop 版本中沒有map side hash aggr 的參數(shù)吧. 而且寫成distinct 還多了一個(gè)MR 步驟,不太推薦.

     

    數(shù)據(jù)傾斜在MPP 中也是一個(gè)課題,這也設(shè)計(jì)到一個(gè)數(shù)據(jù)重分配的問題,但是相對(duì)于MPP 中有比較成熟的機(jī)制,一個(gè)是mpp 在處理數(shù)據(jù)初始分布的時(shí)候總是會(huì)指定segmented by 或者distributed by 這種顯示分配到不同物理機(jī)器上的建表語句. 還有就是統(tǒng)計(jì)信息會(huì)幫助執(zhí)行引擎選擇合適的重新分布.但是統(tǒng)計(jì)信息也不是萬能的,比如

    1:統(tǒng)計(jì)信息的粒度和更新問題.

    2: 應(yīng)用了過濾條件之后的數(shù)據(jù)也許不符合原始期望的數(shù)據(jù)分布.

    3: 統(tǒng)計(jì)信息是基于采樣的,總于真實(shí)所有數(shù)據(jù)存在誤差.

    4: 統(tǒng)計(jì)信息是基于partittion 的, 對(duì)于查詢沒有涉及到partition 字段的切分就不能使用各partition 只和來表示總體的統(tǒng)計(jì)信息.

    5. 臨時(shí)表或者多步驟查詢的中間過程數(shù)據(jù)沒有統(tǒng)計(jì)信息的情況.

    6. 各種其他的算法優(yōu)化比如in-mapper combiner 或者google Tenzing 的prev – next combine 都會(huì)影響統(tǒng)計(jì)信息對(duì)于算法選擇的不同.


以上是“Hadoop中的數(shù)據(jù)傾斜是什么意思”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI