眾所周知,傳統存儲系統對固態介質的利用方式共有多種,冬瓜哥本文就針對每一種方式做個分析和總結。雖然說論文都有個摘要,但是冬瓜哥想直奔主題,就不啰嗦了。

  【方式1】

  連鍋端/AFA

  第一種是一刀切連鍋端,直接把機械盤替換為固態盤,這種方式獲得的性能提升最高,但無疑付出的成本也是最高的,這就是所謂All Flash Array(AFA),全閃存陣列。然而,如果不加任何改動僅僅做簡單替換的話,會發現AFA根本無法發揮出固態盤的性能,比如,一個24盤位的中端存儲系統控制器,如果全部換成24塊SAS SSD的話,其最大隨機讀IOPS大概只能到200K到300K之間,如果按照每塊盤隨機讀IOPS到50k的話,那么24塊的總和應該是1200K,也就是120萬,當然,還需要拋去做Raid等其他底層模塊的處理所耗費的時間開銷,但是,二十到三十萬IOPS相對于120萬的話,這效率也太低了。

  全固態陣列,是一種虛擬化設備,所謂虛擬化設備,是指從這個設備的前端只能看到虛擬出來的資源而看不到該設備后端所連接的任何物理設備(帶內虛擬化);或者在數據路徑上可以看到后端的物理設備且可以讀寫,但是在控制路徑上需要在對物理設備進行讀寫之前咨詢一下元數據服務器(帶外虛擬化)。帶外虛擬化性能高,但是架構復雜不透明,需要在前端主機上安裝特殊的客戶端。帶內虛擬化方式則可以對前端主機保持完全透明。目前的全固態陣列,為了保證充分的通用性,所以普遍使用帶內虛擬化方式,也就是說,對于基于x86平臺的AFA,其軟硬件架構本質上與傳統存儲別無二致,差別就在于IO路徑的優化力度上。傳統陣列的IO處理路徑無法發揮出固態介質的性能根本原因就在于參與IO處理的模塊太多太冗長,因此,全固態陣列基本會在以下幾個角度上做優化從而釋放其所連接的固態盤/閃存卡的性能。

  1. 簡化功能

  比如快照重刪Thin遠程復制、Raid2.0之流、自動分層/緩存(本來也就一個層)等。所有這些模塊的存在,都會影響性能。雖然可以使用流水線化的IO處理方式來提升吞吐量,但是流水線對IO的時延是毫無幫助的,而且流水線級數越多,每個IO的處理時延就越高。吞吐量雖然是一個很重要的指標,只要底層并發度足夠大(更詳細的分析可參考冬瓜哥另一篇文章《關于IO時延你被騙了多久》),再加上流水線化,就可以達到很高的數字;但是時延的指標,對于一些場景來講同樣很重要,比如OLTP場景,時延只能靠縮減流水線級數(處理模塊的數量)或者提升每個模塊的處理速度這兩種手段來實現,沒有任何其他途徑。然而,也并非要把所有數據管理功能全都拋掉,如果這樣的話,那么所有基于x86平臺的AFA最后就只能拼價格,因為沒有任何特色。所以,保留哪些功能,保留下來的功能模塊又怎樣針對固態介質做優化,就是AFA廠商需要攻克的難關了。

  2. 用原有的協議棧,加入多隊列等優化

  對于IO處理的主戰場來講,協議棧無疑是一道無法越繞開的城墻,拿Linux來講,協議棧從通用塊層一直延伸到底層IO通道控制器的驅動程序(Low Layer Device Driver,LLDD),IO路徑上的這一大段,都可以統稱為協議棧。開發者可以完全利用現有Linux內核的這些成熟的協議棧來設計AFA,但是其性能很差,比如通用塊層在較老的內核版本中,其只有一個bio(Block IO)請求隊列,在機械盤時代,機械盤就像老爺車一樣,這個隊列基本都是堵得,也就是Queue Full狀態,瀆指針永遠追不上寫指針。

  而在固態存儲時代,這個隊列又頻繁地欠載(Underrun),瀆指針追上了寫指針,因為底層的處理速度太快了,以至于隊列中還沒有更多的IO入隊,底層就把隊列中所有IO都處理完了。欠載的后果就是底層無法獲取足夠多的IO請求,那么吞吐量就會降下來。這就像抽水機一樣,大家可能有人見過工地上的抽水機,咣嘰咣嘰的,活塞每運動一次,水流就冒出來,而當活塞退回原位從水源吸水的時候,出水端水流就小了?;钊看文芪娜萘?,就是隊列深度。

  好在,在IO路徑處理上,系統并不是處理完隊列中所有IO之后,才允許新的IO入隊,IO可以隨時入隊(上游模塊壓入隊列等待處理)或者出隊(下游模塊從隊列中取走執行),但是,這種方式也帶來了一個問題,就是鎖的問題。出隊入隊操作,都要鎖住整個隊列首尾指針對應的變量,因為不能允許多個模塊同時操作指針變量,會不一致。這一鎖定,性能就會受到影響,從而導致頻繁欠載。有些號稱無鎖隊列,只不過是將鎖定操作從軟件執行變成利用硬件原子操作指令來讓硬件完成,底層還是需要鎖定的。那么,這方面如何優化?道理很簡單,大家都擠在一個隊列里操作,何不多來幾個隊列呢?隊列之間一般沒有關聯,根本不需要隊列間鎖定,這就增加了并發度,能夠釋放固態介質的性能。在最新的Linux內核中,通用塊層已經實現了多隊列。所以,如果還想利用現成的塊層來節約開發量,那么無疑要選擇新內核版本了。

 

  3. 拋棄原有的協議棧,包括塊層,自己開發新協議棧

  通用塊層之所以通用,就是因為它考慮了最通用的場景,定義了很多像模像樣的數據結構、接口、流程,而且加入了很多功能模塊,比如LVM,軟Raid,Device Mapper,DRBD、IO Scheduler等等,雖然這些模塊多數都可以被bypass掉,但是這些東西對于那些想完全榨干性能的架構師來講,就多余了。

  有些AFA或者一些分布式存儲系統在IO路徑中完全拋棄塊層,而自己寫了一個內核模塊掛接到VFS層下面,接受應用發送的IO請求,經過簡單處理之后直接交給底層協議棧(比如SCSI協議棧)處理。不幸的是,SCSI協議棧本身則是個比塊層還要厚的層。IO出了龍潭又入虎穴,對于基于SATA/SAS SSD的AFA來講,SCSI層很難繞過,因為這個協議棧太過底層,SCSI指令集異常復雜,協議狀態機、設備發現、錯誤恢復機制等哪一樣都夠受的,如果拋棄SCSI協議棧自己開發一個新的輕量級SCSI協議棧,那是不切實際的,你會發現倒頭來不得不把那些重的代碼加回來,因為SCSI體系本身的復雜性已經決定了協議棧實現上的復雜性。

  所以,基于SATA/SAS SSD搭建的固態陣列,其性能也就那么回事,時延一定高。然而,如果使用的是PCIE閃存卡或者2.5寸盤的話,那么就可以完全拋棄SCSI協議棧。有些PCIE閃存卡的驅動中包含了自定義的私有協議棧,其中包含了指令集、錯誤處理、監控等通用協議棧的大部分功能,其直接注冊到塊層;而NVMe協議棧迅速成了定海神針,參差不齊混亂不堪的協議棧,不利于行業的規模性發展,NVMe協議棧就是專門針對非易失性高速存儲介質開發的輕量級協議棧,輕量級的指令集和錯誤恢復邏輯,超高的并發隊列數量和隊列深度。AFA后端如果使用NVMe閃存卡/盤的話,那么這塊也就沒有什么可優化的了。如果還想優化,那就得從更底層來優化了,也就是連NVMe協議棧也拋掉,只保留PCIE閃存卡/盤的LLDD驅動,上面的部分全部重寫,不過這樣看上去沒什么必要,因為LLDD上層接口也是符合NVMe規范的,設備固件也只能處理NVMe指令,所以,針對已經優化過的協議棧繼續優化,受益很低,成本很高。要想繼續優化,還有一條路可走,那就是連內核態驅動都拋掉。

  4.拋棄原有的協議棧和設備驅動,完全從頭開發

  塊層可以拋,底層協議棧也可以拋,最底層的內核設備驅動是否也可以拋棄呢?若為性能故,三者皆可拋!操作系統內核的存在,對性能是無益的,內核增加了方便性和安全性,必然犧牲性能。如果要追求極致性能,就要連操作系統內核都Bypass掉。當然,運行在OS中的程序是不可能脫離OS內核而存在的,但是這并不妨礙其打開一個小窗口,將IO指令直接發送給硬件,無需經過內核模塊的轉發,這就是所謂內核Bypass,指的是IO路徑上的大部分操作不陷入內核。

  當然,這需要PCIE閃存卡/盤廠商首先實現一個很小的代理驅動,這個驅動負責將PCIE設備的寄存器空間映射到用戶程序空間,之后還要負責響應中斷和代理DMA操作,其他時候就不參與任何IO處理了,用戶程序可以直接讀寫設備寄存器,這樣可以實現更高的性能,但是對開發者能力要求甚高,其需要自行實現一個用戶態的IO處理狀態機,或者說IO協議棧,搞不好的話,連原生驅動的性能都不如。所以,這已經超出了目前多數產品開發設計者的可承受范圍,在如今這個互聯網+的浮躁時代,多數人更注重快速出產品,而不是十年磨一劍鑄就經典。

  5.針對多核心進行優化

  不管利用上述哪種設計模式,都需要針對多核心CPU平臺進行優化。有些存儲廠商在幾乎十年前就開始了多CPU多核心的系統優化,而某大牌廠商,據冬瓜哥所知,直到幾年前才著手優化多核心多CPU,當時,其產品雖然硬件配置上是多核心多CPU,其實其軟件內部的主要IO模塊根本都是串行架構的,也就是根本用不起來多CPU,具體廠商冬瓜哥就不提了,只是想讓大家明白一個事情,就是廠商的這些產品,表面吹的很光鮮,而后面的水可能很深,有時候可能也是很黑的。

  6.采用專用FPGA加速

  存儲系統到底是否可以使用硬加速?這得首先看一下存儲系統的本質,存儲系統的最原始形態,其實不是存儲,而是網絡,也就是只負責轉發IO請求即可,不做任何處理(或者說虛擬化),如果僅僅是IO轉發,那不就成了交換機了么,是的,交換機是否可以使用通用CPU來完成?可以,軟交換機就是,但是性能的確是不如硬交換機的,硬交換機直接用Crossbar或者MUX來直接傳遞數據,而CPU則需要通過至少一次內存拷貝,收包、分析+查路由、發包,這個處理過程時延遠高于硬交換,雖然可以用流水線化處理以及并行隊列的障眼法也達到較高的吞吐量,但是只要考察其時延,立馬露餡。

  再來說說增加了很多功能的存儲系統,也就是虛擬化存儲系統,其內部使用通用CPU完成所有邏輯,不僅是簡單的IO轉發了,而且要處理,比如計算XOR,計算Hash,查表計算Thin卷的地址映射,Raid2.0元數據的更新維護,響應中斷,拷貝數據,等等。那么上述這些工作,哪些可以硬加速呢?那些大運算量,大數據拷貝量,模式重復固定的運算,都可以被硬加速,比如XOR計算,重刪Hash計算,固定模式的元數據維護(比如bitmap、鏈表、bloomfilter等)、字符串匹配搜索、指令譯碼等。(詳情可參考冬瓜哥的“大話存儲”公眾號的第一篇文章《聊聊FPGA/CAPI/CPU》)。

  至于復雜的判斷邏輯或者說控制邏輯,尤其是全局控制部分,還得通用CPU出馬,因為在這個層面上,充滿了變數。所以,即便是采用了FPGA的存儲系統,其一定也是靠通用CPU來完成總體控制的,有些單片FPGA存儲系統,那也不過是利用了FPGA內部集成的通用CPU硬核來做總控罷了。目前市面上的FPGA,已經不單純是一大塊可編程邏輯了,與其說是FPGA,不如說是帶可編程邏輯的SoC更合適,或者說是把一堆成熟外圍器件比如DDR控制器、PCIE控制器、通用CPU、RAM、SRAM等,與FPGA可編程部分集成到一起的一個整體單片系統,該系統也是什么都能做,雖然內部集成的核心可能遠比不上x86平臺的性能,但是對于專用系統,基本已足夠。所以,用了FPGA就不需要Linux了么?非也。用了FPGA就不需要NVMe驅動了么?非也。FPGA在這里充其量起到一個offload一些計算的作用了。

  【方式2】

  共存但不交叉

  Nima,方式1這一節篇幅竟然這么長,冬瓜哥自己都怕了。再來說說方式2,共存但不交叉。這個方式是指在同一個存儲系統內,既有固態介質又有機械盤,但是它們不被放置在同一個Raid組內,比如8個機械盤做一個Raid5,另外4個SSD又做了一個Raid10,各玩各的互不干擾。說不干擾,是假的,這里的干擾,是一種更深層次的干擾,典型的代表是“快慢盤問題”,能力強的能力弱的,在同一個體系內,會發生什么問題?大家都清楚,能力弱的會拖慢能力強的。

  對于存儲系統,一樣的,系統內的資源是有限的,比如某個鏈表,其中記錄有針對機械盤的IO的指令和數據,這些IO的執行相對于固態介質來講簡直是慢如蝸牛,那么,當固態盤執行完一個IO之后,由于這些被機械盤占用的資源無法釋放,新的IO就無法占用這些資源,導致固態盤在單位時間內的閑置率增加,那么性能就無法發揮,被慢盤拖慢了。同樣的現象甚至出現在全機械盤系統內,如果某個盤有問題,響應時間變長,除了影響Raid組內其他盤之外,也影響了其他Raid組的性能發揮。解決這類問題,就要針對固態盤開辟專用的資源,而這又會增加不少的開發量和測試量。

  【方式3】

  散熱設計和供電

  還有一種方式,是將固態介質用作元數據的存儲,比如存放Hash指紋庫、Thin/分層/Raid2.0的重映射表等、文件系統元數據等量較大的元數據,這些元數據如果都被載入內存的話恐怕放不開,因為存儲系統的內存主要是被用來緩存讀寫數據,從而提升性能,如果將大量空間用于元數據存放,那么性能就無法保證,但是反過來,如果大部分元數據無法被載入內存,那么性能也無法保證,因為對于文件系統、分層、Raid2.0等,每筆IO都無法避免查表,而且是個同步操作,如果元數據緩存不命中,到磁盤載入,這樣性能就會慘不忍睹。所以固態盤此時派上了用場,可以作為針對元數據的二級緩存使用,容量足夠大,讀取時響應速度夠快,更新則可以在RAM中積累然后批量更新到Flash,所以即便Flash寫性能差,也不是問題。

  【方式4】

  非易失性寫緩存/NVRAM

  大家都知道分布式系統一般是利用節點間鏡像來防止一個節點宕機之后緩存數據的丟失。而如果是所有節點全部掉電呢?比如某長時間停電,或者雷擊等導致包括UPS在內的全部電力供應中斷,整體掉電的幾率還是存在的。此時,緩存鏡像依然無法防止丟數據。而傳統存儲內部有一個BBU或者UPS,相當于二級保險。

  對于分布式系統,要增加這種二級保險的話,成本會非常高,因為分布式系統的節點太多,但是的確有些分布式系統廠商采用了NVRAM/NVDIMM來保護關鍵元數據或者Journal,而沒有用BBU來保護整個機器的內存,因為后者需要定制化硬件設計,服務器機箱內無法容下BBU了。

  目前,NVDIMM需要改很多周邊的軟硬件,不透明,而基于PCIE接口的NVRAM卡則可以無需修改BIOS和OS內核即可使用,其可以模擬成塊設備,或者將卡上的RAM空間映射到用戶態。隨著NVDIMM,以及Intel Apache Pass項目的推進,相信后期非易失性DIMM會逐漸普及開來。

  【方式5】

  透明分層

  上述介紹的混合機械盤和固態盤的方案,對應用來講都不是透明的,都需要應用或者系統管理員自行感知和安排數據的保存位置。透明分層則是一種對應用透明的加速方案,傳統存儲產品最看重對應用透明,所以自動分層技術成為了傳統存儲的標配特性。大家的做法類似,都是自動統計每個數據塊的訪問頻率,然后做排序,將熱點數據從低速介質上移到高速介質,冷數據則下移到低速介質。沒太大技術含量,無非就是誰家能做更小的分塊粒度,熱點識別的精準度就越高,但是耗費的元數據空間越大,搜索效率越低,所有參數都是各種平衡的結果。

  自動分層有一個尷尬的地方,就是對于新寫入的數據塊的處理策略,是先寫入低速分層再向上遷移,還是與先寫入高速分層再“下沉”給應用的體驗有區別,哪個能始終保證寫入性能?這些策略,每個廠商都有各自的選擇。在此冬瓜哥想用一個典型設計來想大家介紹一下自動分層方案在實際產品中的全貌。

  目前針對自動分層方案,業界的產品中,Dell在其Fluid Data系列方案中有兩個技術比較有特色。第一個是Fast Track技術,也就是系統可以將熱數據透明的放置在磁盤的外圈,而冷數據則搬移到內圈。外圈轉速高,等待時間短,可以獲得更高的IOPS和帶寬。

  第二個則是利用寫重定向快照來實現讀寫分離的、基于全固態存儲系統的跨Raid級別(Raid10和Raid5)的分層方案,號稱可以以磁盤的價格實現全固態存儲的性能,這個方案冬瓜哥認為還是非常有特色的。

  首先,系統將Tier1層,也就是固態介質層,分為兩個子層,一個是采用Raid10方式的且由SLC Flash構成的子層,這個層采用無寫懲罰的Raid10冗余保護方式,而且采用壽命和性能最高的SLC規格的Flash介質,所以僅承載寫IO和針對新寫入數據的讀IO,基本不必關心壽命和性能問題,所以又被稱為Write Intensive(WI)層,當然,這一層的容量也不會很大;另一個是采用Raid5方式的且由MLC Flash構成的子層,僅承載讀IO,所以Raid5的寫懲罰并不會導致讀性能下降,又被稱為Read Intensive(RI)層,這一層相對容量較大。如下圖所示為一種典型的固態+機械盤混合存儲配比方案。

  那么,Dell流動數據方案是如何實現讀寫分離的呢?其巧妙的利用了寫重定向快照技術(注:Dell Compellent系統里的快照被稱為“Replay”)。如下圖所示,類型一中的方式,屬于傳統分層方式,也就是白天統計訪問頻率,傍晚或者深夜進行排序和熱點判斷以及數據搬移,這種方式是目前多數廠商普遍的實現方式,沒有什么亮點。然而,Dell流動數據方案除了支持這種傳統方式之外還支持另一種即圖中所示的“按需數據調度”分層方式。

  這種比較奇特的方式可以實現讀寫分離,但是必須依賴于快照,也就是說,只有當快照生成之后,這種方式才起作用,如果用戶沒有主動做快照,那么系統也會后臺自動做快照來支撐這種分層方式的執行,冬瓜哥在此想為大家介紹一下這種方式的具體機理。

  大家都知道寫重定向快照的底層原理(不了解的可以閱讀冬瓜哥的《大話存儲(終極版)》),快照生成之后,源數據塊只會被讀取,不會被原地覆蓋寫入,因為覆蓋寫入的數據塊都會被重定向到新的空閑數據塊,在Dell流動數據按需數據調度技術中,這些新覆蓋寫入的數據塊依然會被寫入到Raid10模式的Tier1 SSD中,也就是WI層,那么,尚存在于WI層的源數據塊后續只會被讀?。ㄟ@類數據塊又被稱為“只讀活躍頁”),不會被原地覆蓋寫入,那么就沒有必要繼續在WI層中存放,可以將它們在后臺全部轉移到Raid5模式的Tier1 SSD中也就是RI層存放,對于那些已經被更改過一次的數據塊(新寫入數據塊被重定向,對應的原有數據塊此時就被稱為“不再訪問的歷史頁”),其永遠不會被生產卷所訪問到,那么就可以將這些數據塊直接遷移到最低性能層級,也就是Tier3的機械盤中存儲。

  如果系統內當前并沒有生成快照,或者所有快照已經被用戶刪除,那么當SLC的WI層級達到95%滿之后,系統會自動觸發一個快照,目的是重新翻盤,將快照之后新寫入的塊寫到SLC,而之前的塊搬移到MLC層級中,已被覆寫的塊直接搬移到機械盤,后續如果再達到95%滿,就再做一次快照重新翻盤,利用這種方式,可保證SLC層級只接受寫入操作以及針對新寫入塊的讀操作,而MLC層級只接受讀操作,實現了讀寫分離,充分發揮了SLC和MLC各自的優勢。戴爾建議每天至少生成一個Replay,可以安排在負載不高的時段,并根據數據寫入量來提前規劃SLC分層的容量。95%這個觸發機制只是最后一道防線。

  另外,當某個數據塊被搬移到RI層后,如果發生了針對該塊的寫入操作,那么,其被寫入之后(新塊寫到SLC層),該塊在MLC中的副本就不會再被生產卷訪問,系統會將其遷移到最低層級的機械盤從而空出MLC層的空間。另外,MLC中那些長期未被讀到的數據塊,也會被系統遷移到磁盤層。

  利用這種寫重定向快照技術和多個層級的介質,Dell Fluid Data解決方案實現了讀寫分離,讓寫總是寫到SLC,讀總是讀MLC,同時MLC中的數據再慢慢向下淘汰到機械盤,這種方式相比定期觸發數據搬移的傳統分層技術來講,更加具有實時性,在SLC層和MLC層之間的流動性非常強,能夠應對突發的熱點,更像是一種實時緩存;而在MLC和機械盤之間,流動性較低,除了將快照中被新數據“覆蓋”的塊拷貝到機械盤之外,還定期根據長期的冷熱度將MLC層中的塊搬移到機械盤,這又是傳統分層的思想。所以Dell Fluid Data分層解決方案是一個結合了緩存和分層各自優點的,利用寫重定向快照技術充分發揮了SLC和MLC各自讀寫特長的優秀解決方案。

  【方式6】

  透明緩存

  然而,自動分層有個劣勢,就是其識別的“熱點”必須是長期熱點,對于突發性短期熱點,無能為力,因為其統計周期一般是小時級別的,有些熱點恐怕幾分鐘就過去了。另外一個劣勢,就是無法判斷出人為熱點,比如5分鐘之后,管理員明確知道某個文件或者某個庫一定會招致很高的訪問壓力,此時,傳統的自動分層就無能為力,因此冬瓜哥在之前的“可視化存儲智能解決方案”對應的產品中,就加入了這種對人為熱點的支持,提供自動和手動以及混合模式,可以讓用戶靈活的決定將什么數據放在哪里,但是依然是對應用透明的,只相當于給存儲系統提供了準確的提示信息而已。

  此外,針對這種突發性實時熱點,一個最典型的粒子就是VDI啟動風暴場景,這個突發熱點是分層沒法解決的,除非使用了鏈接克隆然后利用冬瓜哥在“可視化存儲智能解決方案”中所設計的類似技術,將克隆主體數據手動透明遷移到固態介質上。

  應對這種突發熱點,一種更合適的方式,就是固態介質緩存。緩存比分層更加實時,因為所有的讀寫數據先從內存進入SSD緩存,再到機械盤,所有數據都有進入緩存的機會,利用LRU及其各種變種算法,能將那些短時間內訪問頻繁的數據留在SSD中。所以,應對VDI啟動風暴這種場景,使用緩存方式既能保證透明又可以獲得不錯的性能。

  針對緩存解決方案,Dell的Fluid Cache for SAN 解決方案將固態介質緩存直接放置在了主機端,利用更靠近CPU的PCIE閃存卡作為緩存介質,并且多臺服務器上的固態介質還可以形成一個全局統一的緩存池。整體的拓撲構成如下圖所示:

  一個緩存域最多由9臺服務器組成,其中至少要包含3臺緩存節點(插有PCIE閃存卡),其余6臺節點可以是客戶端節點(也可以是緩存節點),客戶端節點通過專用的Client向緩存節點直接讀取緩存數據,當然,緩存節點自身的應用程序也可以直接讀取本地或者其他緩存節點的數據。讀寫緩存走的是萬兆或者40GE網絡,來保證低時延,同時這個網絡也承載緩存鏡像流量,每個節點的寫緩存,會通過RDMA鏡像到其他緩存節點一份,當寫緩存被同步到后端的Compellent存儲系統之后,才會作廢對端的鏡像副本,以此來保障一個節點宕機之后的系統可用性。某個卷的數據塊可以被配置為僅緩存在本機的PCIE閃存介質中,也可以均衡緩存到所有節點(默認配置)。

  緩存模式的這種強實時性,使得其非常適合于實時加速,比如OLTP場景,下圖所示為由一個8節點緩存集群的性能加速效果,使得可并發的用戶數量達到了6倍,同時平均響應時間降低了99.3%。

未經允許不得轉載:存儲在線-存儲專業媒體 » 存儲極客 | 淺析固態介質在存儲系統中的應用方式
分享到

wangky

存儲在線(DOSTOR)高級編輯

相關推薦

精品国产午夜肉伦伦影院,双性老师灌满浓jing上课h,天天做天天爱夜夜爽,攵女乱h边做边走