精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

從零實現一個 K-V 存儲引擎

存儲 存儲軟件
寫這篇文章的目的,是為了幫助更多的人理解 rosedb,我會從零開始實現一個簡單的包含 PUT、GET、DELETE 操作的 k-v 存儲引擎。

[[408244]]

本文轉載自微信公眾號「roseduan寫字的地方」,作者roseduan。轉載本文請聯系roseduan寫字的地方公眾號。

寫這篇文章的目的,是為了幫助更多的人理解 rosedb,我會從零開始實現一個簡單的包含 PUT、GET、DELETE 操作的 k-v 存儲引擎。

你可以將其看做是一個簡易版本的 rosedb,就叫它 minidb 吧(mini 版本的 rosedb)。

無論你是 Go 語言初學者,還是想進階 Go 語言,或者是對 k-v 存儲感興趣,都可以嘗試自己動手實現一下,我相信一定會對你幫助很大的。

說到存儲,其實解決的一個核心問題就是,怎么存放數據,怎么取出數據。在計算機的世界里,這個問題會更加的多樣化。

計算機當中有內存和磁盤,內存是易失性的,掉電之后存儲的數據全部丟失,所以,如果想要系統崩潰再重啟之后依然正常使用,就不得不將數據存儲在非易失性介質當中,最常見的便是磁盤。

所以,針對一個單機版的 k-v,我們需要設計數據在內存中應該怎么存放,在磁盤中應該怎么存放。

當然,已經有很多優秀的前輩們去探究過了,并且已經有了經典的總結,主要將數據存儲的模型分為了兩類:B+ 樹和 LSM 樹。

本文的重點不是講這兩種模型,所以只做簡單介紹。

B+ 樹

B+ 樹由二叉查找樹演化而來,通過增加每層節點的數量,來降低樹的高度,適配磁盤的頁,盡量減少磁盤 IO 操作。

B+ 樹查詢性能比較穩定,在寫入或更新時,會查找并定位到磁盤中的位置并進行原地操作,注意這里是隨機 IO,并且大量的插入或刪除還有可能觸發頁分裂和合并,寫入性能一般,因此 B+ 樹適合讀多寫少的場景。

LSM 樹

LSM Tree(Log Structured Merge Tree,日志結構合并樹)其實并不是一種具體的樹類型的數據結構,而只是一種數據存儲的模型,它的核心思想基于一個事實:順序 IO 遠快于隨機 IO。

和 B+ 樹不同,在 LSM 中,數據的插入、更新、刪除都會被記錄成一條日志,然后追加寫入到磁盤文件當中,這樣所有的操作都是順序 IO,因此 LSM 比較適用于寫多讀少的場景。

看了前面的兩種基礎存儲模型,相信你已經對如何存取數據有了基本的了解,而 minidb 基于一種更加簡單的存儲結構,總體上它和 LSM 比較類似。

我先不直接干巴巴的講這個模型的概念,而是通過一個簡單的例子來看一下 minidb 當中數據 PUT、GET、DELETE 的流程,借此讓你理解這個簡單的存儲模型。

PUT

我們需要存儲一條數據,分別是 key 和 value,首先,為預防數據丟失,我們會將這個 key 和 value 封裝成一條記錄(這里把這條記錄叫做 Entry),追加到磁盤文件當中。Entry 的里面的內容,大致是 key、value、key 的大小、value 的大小、寫入的時間。

所以磁盤文件的結構非常簡單,就是多個 Entry 的集合。

磁盤更新完了,再更新內存,內存當中可以選擇一個簡單的數據結構,比如哈希表。哈希表的 key 對應存放的是 Entry 在磁盤中的位置,便于查找時進行獲取。

這樣,在 minidb 當中,一次數據存儲的流程就完了,只有兩個步驟:一次磁盤記錄的追加,一次內存當中的索引更新。

GET

再來看 GET 獲取數據,首先在內存當中的哈希表查找到 key 對應的索引信息,這其中包含了 value 存儲在磁盤文件當中的位置,然后直接根據這個位置,到磁盤當中去取出 value 就可以了。

DEL

然后是刪除操作,這里并不會定位到原記錄進行刪除,而還是將刪除的操作封裝成 Entry,追加到磁盤文件當中,只是這里需要標識一下 Entry 的類型是刪除。

然后在內存當中的哈希表刪除對應的 key 的索引信息,這樣刪除操作便完成了。

可以看到,不管是插入、查詢、刪除,都只有兩個步驟:一次內存中的索引更新,一次磁盤文件的記錄追加。所以無論數據規模如何, minidb 的寫入性能十分穩定。

Merge

最后再來看一個比較重要的操作,前面說到,磁盤文件的記錄是一直在追加寫入的,這樣會導致文件容量也一直在增加。并且對于同一個 key,可能會在文件中存在多條 Entry(回想一下,更新或刪除 key 內容也會追加記錄),那么在數據文件當中,其實存在冗余的 Entry 數據。

舉一個簡單的例子,比如針對 key A, 先后設置其 value 為 10、20、30,那么磁盤文件中就有三條記錄:

此時 A 的最新值是 30,那么其實前兩條記錄已經是無效的了。

針對這種情況,我們需要定期合并數據文件,清理無效的 Entry 數據,這個過程一般叫做 merge。

merge 的思路也很簡單,需要取出原數據文件的所有 Entry,將有效的 Entry 重新寫入到一個新建的臨時文件中,最后將原數據文件刪除,臨時文件就是新的數據文件了。

這就是 minidb 底層的數據存儲模型,它的名字叫做 bitcask,當然 rosedb 采用的也是這種模型。它本質上屬于類 LSM 的模型,核心思想是利用順序 IO 來提升寫性能,只不過在實現上,比 LSM 簡單多了。

介紹完了底層的存儲模型,就可以開始代碼實現了,我將完整的代碼實現放到了我的 Github 上面,地址:

https://github.com/roseduan/minidb

文章當中就截取部分關鍵的代碼。

首先是打開數據庫,需要先加載數據文件,然后取出文件中的 Entry 數據,還原索引狀態,關鍵部分代碼如下:

  1. func Open(dirPath string) (*MiniDB, error) { 
  2.    // 如果數據庫目錄不存在,則新建一個 
  3.    if _, err := os.Stat(dirPath); os.IsNotExist(err) { 
  4.       if err := os.MkdirAll(dirPath, os.ModePerm); err != nil { 
  5.          return nil, err 
  6.       } 
  7.    } 
  8.  
  9.    // 加載數據文件 
  10.    dbFile, err := NewDBFile(dirPath) 
  11.    if err != nil { 
  12.       return nil, err 
  13.    } 
  14.  
  15.    db := &MiniDB{ 
  16.       dbFile: dbFile, 
  17.       indexes: make(map[string]int64), 
  18.       dirPath: dirPath, 
  19.    } 
  20.  
  21.    // 加載索引 
  22.    db.loadIndexesFromFile(dbFile) 
  23.    return db, nil 

再來看看 PUT 方法,流程和上面的描述一樣,先更新磁盤,寫入一條記錄,再更新內存:

  1. func (db *MiniDB) Put(key []byte, value []byte) (err error) { 
  2.    
  3.    offset := db.dbFile.Offset 
  4.    // 封裝成 Entry 
  5.    entry := NewEntry(key, value, PUT) 
  6.    // 追加到數據文件當中 
  7.    err = db.dbFile.Write(entry) 
  8.  
  9.    // 寫到內存 
  10.    db.indexes[string(key)] = offset 
  11.    return 

GET 方法需要先從內存中取出索引信息,判斷是否存在,不存在直接返回,存在的話從磁盤當中取出數據。

  1. func (db *MiniDB) Get(key []byte) (val []byte, err error) { 
  2.    // 從內存當中取出索引信息 
  3.    offset, ok := db.indexes[string(key)] 
  4.    // key 不存在 
  5.    if !ok { 
  6.       return 
  7.    } 
  8.  
  9.    // 從磁盤中讀取數據 
  10.    var e *Entry 
  11.    e, err = db.dbFile.Read(offset) 
  12.    if err != nil && err != io.EOF { 
  13.       return 
  14.    } 
  15.    if e != nil { 
  16.       val = e.Value 
  17.    } 
  18.    return 

DEL 方法和 PUT 方法類似,只是 Entry 被標識為了 DEL ,然后封裝成 Entry 寫到文件當中:

  1. func (db *MiniDB) Del(key []byte) (err error) { 
  2.    // 從內存當中取出索引信息 
  3.    _, ok := db.indexes[string(key)] 
  4.    // key 不存在,忽略 
  5.    if !ok { 
  6.       return 
  7.    } 
  8.  
  9.    // 封裝成 Entry 并寫入 
  10.    e := NewEntry(key, nil, DEL) 
  11.    err = db.dbFile.Write(e) 
  12.    if err != nil { 
  13.       return 
  14.    } 
  15.  
  16.    // 刪除內存中的 key 
  17.    delete(db.indexes, string(key)) 
  18.    return 

最后是重要的合并數據文件操作,流程和上面的描述一樣,關鍵代碼如下:

  1. func (db *MiniDB) Merge() error { 
  2.    // 讀取原數據文件中的 Entry 
  3.    for { 
  4.       e, err := db.dbFile.Read(offset) 
  5.       if err != nil { 
  6.          if err == io.EOF { 
  7.             break 
  8.          } 
  9.          return err 
  10.       } 
  11.       // 內存中的索引狀態是最新的,直接對比過濾出有效的 Entry 
  12.       if off, ok := db.indexes[string(e.Key)]; ok && off == offset { 
  13.          validEntries = append(validEntries, e) 
  14.       } 
  15.       offset += e.GetSize() 
  16.    } 
  17.  
  18.    if len(validEntries) > 0 { 
  19.       // 新建臨時文件 
  20.       mergeDBFile, err := NewMergeDBFile(db.dirPath) 
  21.       if err != nil { 
  22.          return err 
  23.       } 
  24.       defer os.Remove(mergeDBFile.File.Name()) 
  25.  
  26.       // 重新寫入有效的 entry 
  27.       for _, entry := range validEntries { 
  28.          writeOff := mergeDBFile.Offset 
  29.          err := mergeDBFile.Write(entry) 
  30.          if err != nil { 
  31.             return err 
  32.          } 
  33.  
  34.          // 更新索引 
  35.          db.indexes[string(entry.Key)] = writeOff 
  36.       } 
  37.  
  38.       // 刪除舊的數據文件 
  39.       os.Remove(db.dbFile.File.Name()) 
  40.       // 臨時文件變更為新的數據文件 
  41.       os.Rename(mergeDBFile.File.Name(), db.dirPath+string(os.PathSeparator)+FileName) 
  42.  
  43.       db.dbFile = mergeDBFile 
  44.    } 
  45.    return nil 

除去測試文件,minidb 的核心代碼只有 300 行,麻雀雖小,五臟俱全,它已經包含了 bitcask 這個存儲模型的主要思想,并且也是 rosedb 的底層基礎。

理解了 minidb 之后,基本上就能夠完全掌握 bitcask 這種存儲模型,多花點時間,相信對 rosedb 也能夠游刃有余了。

進一步,如果你對 k-v 存儲這方面感興趣,可以更加深入的去研究更多相關的知識,bitcask 雖然簡潔易懂,但是問題也不少,rosedb 在實踐的過程當中,對其進行了一些優化,但目前還是有不少的問題存在。

有的人可能比較疑惑,bitcask 這種模型簡單,是否只是一個玩具,在實際的生產環境中有應用嗎?答案是肯定的。

bitcask 最初源于 Riak 這個項目的底層存儲模型,而 Riak 是一個分布式 k-v 存儲,在 NoSQL 的排名中也名列前茅:

豆瓣所使用的的分布式 k-v 存儲,其實也是基于 bitcask 模型,并對其進行了很多優化。目前純粹基于 bitcask 模型的 k-v 并不是很多,所以你可以多去看看 rosedb 的代碼,可以提出自己的意見建議,一起完善這個項目。

最后,附上相關項目地址:

  • minidb:https://github.com/roseduan/minidb
  • rosedb:https://github.com/roseduan/rosedb

參考資料:

https://riak.com/assets/bitcask-intro.pdf

https://medium.com/@arpitbhayani/bitcask-a-log-structured-fast-kv-store-c6c728a9536b

 

題圖:from wallheaven.cc

 

責任編輯:武曉燕 來源: roseduan寫字的地方
相關推薦

2020-09-24 11:46:03

Promise

2019-04-24 15:06:37

Http服務器協議

2021-08-04 05:49:40

數據庫數時序數據庫技術

2022-03-21 08:49:01

存儲引擎LotusDB

2025-03-04 00:20:45

2014-09-25 09:51:29

Android App個人博客

2016-09-14 17:48:44

2011-03-28 09:56:03

存儲增刪操作

2025-04-17 01:30:00

開源PostgreSQL存儲引擎

2019-06-10 15:00:27

node命令行前端

2025-10-24 10:41:33

2025-01-03 09:00:00

代碼C++gTest

2017-03-15 08:43:29

JavaScript模板引擎

2017-08-11 17:55:48

前端JavaScript模板引擎

2017-03-20 17:59:19

JavaScript模板引擎

2025-05-22 06:44:23

2019-06-12 08:23:21

數據庫時間序列開源

2020-11-06 08:43:21

AIOps運維DevOps

2019-08-26 09:25:23

RedisJavaLinux
點贊
收藏

51CTO技術棧公眾號

色老太综合网| 刘亦菲毛片一区二区三区| 国产亚洲一区二区三区不卡| 欧美性猛交xxxx乱大交退制版| 综合视频在线观看| 成人午夜福利视频| 日韩影院免费视频| 久久国产精品99国产精| 久久午夜夜伦鲁鲁片| 日韩三区四区| 精品高清美女精品国产区| 无遮挡亚洲一区| 丰满少妇在线观看bd| 日本成人在线一区| 久久久久久国产精品久久| 欧美激情aaa| 91精品啪在线观看国产手机| 在线观看亚洲专区| 亚洲精品少妇一区二区| 欧美色视频免费| 国产精品一区专区| 国产99久久精品一区二区| 青青草手机视频在线观看| 国产一区二区电影在线观看| 精品国产免费人成电影在线观看四季| 免费观看成人网| 久久香蕉一区| 亚洲欧洲在线观看av| 免费日韩电影在线观看| 国内老熟妇对白hdxxxx| 蜜桃一区二区三区在线| 欧美一级在线亚洲天堂| 国产亚洲精品久久777777| 日本一区二区高清不卡| 亚洲美腿欧美激情另类| 激情综合激情五月| 国产精品亚洲一区二区在线观看 | 欧美一级理论片| xxxx一级片| 天堂电影一区| 午夜精品一区二区三区电影天堂 | 3d蒂法精品啪啪一区二区免费| 五月天婷婷久久| 国产尤物精品| 久久视频在线播放| 中文天堂资源在线| 国产成人一区| 亚洲男人天堂2019| 亚洲精品乱码久久久久久不卡| 97成人在线| 欧美一区二区三区视频在线观看| 亚洲综合欧美在线| 成人免费毛片嘿嘿连载视频…| 色综合久久综合网| 日韩av黄色网址| 麻豆免费版在线观看| 亚州成人在线电影| 成人免费在线网| 国产丝袜在线播放| 一区二区三区中文在线观看| 99亚洲国产精品| 国产在线观看av| 亚洲人成精品久久久久久| 日韩欧美999| aaa免费在线观看| 麻豆av在线导航| 亚洲丝袜制服诱惑| 大桥未久一区二区三区| 尤物在线网址| 亚洲最大成人网4388xx| 久无码久无码av无码| 大菠萝精品导航| 色综合久久九月婷婷色综合| 日本久久久久久久久久久久| 欧美少妇激情| 日韩欧美一二三四区| 被黑人猛躁10次高潮视频| www.神马久久| 亚洲欧美日韩精品久久亚洲区| x88av在线| 午夜影院欧美| 久久免费观看视频| 日韩在线播放中文字幕| 麻豆成人久久精品二区三区小说| 成人亲热视频网站| 蜜桃91麻豆精品一二三区 | 男人网站在线观看| 亚洲精品蜜桃乱晃| 中文国产成人精品| 国产一区二区视频在线观看免费| 亚洲精品1区2区| 国产精品 欧美在线| 国产乱人乱偷精品视频| 成人国产精品免费观看动漫| 日韩av一级大片| caopen在线视频| 五月天亚洲精品| 亚洲污视频在线观看| 视频二区欧美毛片免费观看| 国产午夜精品麻豆| 国产suv一区二区三区| 亚洲少妇在线| 91视频国产一区| 午夜影院免费视频| 日韩一区在线看| 欧美性大战久久久久xxx| 开心久久婷婷综合中文字幕| 亚洲第一精品久久忘忧草社区| 精品国产aaa| 在线观看不卡| 成人av在线天堂| 天堂av中文在线资源库| 国产精品入口麻豆原神| 国产男女免费视频| 国产精品成人3p一区二区三区| 亚洲аv电影天堂网| 久久一级免费视频| 性xx色xx综合久久久xx| 成人9ⅰ免费影视网站| av中文字幕在线| 五月天精品一区二区三区| 午夜av中文字幕| 国产日产精品一区二区三区四区的观看方式 | 日韩av片电影专区| 亚洲毛片在线播放| 自拍偷拍亚洲欧美日韩| 欧美伦理视频在线观看| 久久综合五月婷婷| 在线精品国产成人综合| 亚洲免费黄色网址| 国产69精品久久777的优势| 狼狼综合久久久久综合网| 伊人在我在线看导航| 欧美日韩午夜在线视频| 国产激情在线免费观看| 99热免费精品在线观看| 97久久人人超碰caoprom欧美 | 欧美国产日韩一区二区三区| 91九色蝌蚪91por成人| 久久精品一区蜜桃臀影院| 少妇人妻无码专区视频| 日韩精品免费视频一区二区三区 | 亚洲AV成人无码网站天堂久久| 美女精品在线| 久久久人人爽| 日韩伦理在线| 日韩精品在线免费| 国产精品一区二区6| 成人av高清在线| www.av毛片| 秋霞影视一区二区三区| 69视频在线免费观看| 少妇荡乳情欲办公室456视频| 亚洲伊人色欲综合网| 日韩高清一二三区| 国内自拍一区| 狠狠色综合色区| 黄色视屏在线免费观看| 亚洲级视频在线观看免费1级| 日韩成人免费在线视频| 99热在这里有精品免费| 18岁视频在线观看| 国产欧美日韩| 国产精品视频在线观看| gogogo高清在线观看免费完整版| 欧美日韩中文字幕精品| 亚洲色图27p| 国产一区二区三区在线观看精品| 青青草原网站在线观看| 91成人在线精品视频| 97在线免费视频| 三级视频在线| 欧美三日本三级三级在线播放| 精品女人久久久| 国产一区视频导航| 久久精品视频16| 一区二区小说| 国产免费久久av| 亚洲男同gay网站| 亚洲精品456在线播放狼人| 无码人妻一区二区三区线| 中文字幕一区二区三区四区不卡 | 日韩精品在线视频免费观看| 欧美激情久久久久久久久久久| 欧洲精品久久久| 日本网站在线免费观看视频| 91精品国产手机| 在线观看 中文字幕| 日本一区二区在线不卡| 日本特黄在线观看| 另类天堂av| 日韩视频在线观看视频| 美国成人xxx| 国产欧美日韩视频| 里番在线播放| 中文字幕在线观看亚洲| 风流老熟女一区二区三区| 在线观看免费亚洲| 久久久久久蜜桃| 欧美国产日本视频| 精品国产乱码久久久久夜深人妻| 久久久久久久欧美精品| 亚洲欧美一二三| 免费成人结看片| 不卡一区二区三区四区五区| 日韩制服一区| 国内精品久久影院| 美女隐私在线观看| 亚洲女人天堂网| 亚洲xxxx天美| 欧美日韩精品三区| 欧美一级淫片免费视频黄| 一区二区三区在线不卡| 国产白丝一区二区三区| 97se亚洲国产综合自在线观| 香蕉视频色在线观看| 日本特黄久久久高潮| 精品视频免费在线播放| 亚洲天堂免费| 午夜视频久久久| 日韩深夜福利| 国产成人精品福利一区二区三区| 高清亚洲高清| 日韩av理论片| 久草在线资源站手机版| 九九热99久久久国产盗摄| 1区2区3区在线观看| 精品一区二区三区三区| 色偷偷在线观看| 日韩一区二区影院| 国产又粗又猛又爽又黄的| 日本精品一区二区三区四区的功能| 久久中文字幕无码| 一区二区三区久久| 搜索黄色一级片| 国产精品久久久久毛片软件| 老牛影视av老牛影视av| 99久久国产综合色|国产精品| 2018国产精品| 丰满白嫩尤物一区二区| 中文字幕色网站| 精品一区二区三区在线播放视频 | 国产精品系列在线播放| 国产欧美一区二| 开心九九激情九九欧美日韩精美视频电影 | 国产天堂在线| 亚洲剧情一区二区| 日韩精品视频无播放器在线看| 亚洲第一中文字幕| 成人午夜视频一区二区播放| 欧美成人精品高清在线播放| 精品国产亚洲AV| 精品日韩99亚洲| 国产香蕉在线观看| 亚洲国产古装精品网站| 瑟瑟在线观看| 亚洲欧美激情视频| 国产高清一级毛片在线不卡| 中文字幕无线精品亚洲乱码一区| av基地在线| www.欧美精品| 超碰公开在线| 欧美激情区在线播放| 国产天堂在线播放视频| 91成人精品网站| 成人做爰视频www网站小优视频| 国产精品91一区| 日韩伦理一区二区| 亚洲a级在线观看| 99久久人爽人人添人人澡| 国内成+人亚洲| 国内精品久久久久久99蜜桃| 亚洲高清视频一区| 午夜久久99| 国产黄色一级网站| 青娱乐精品视频在线| 日韩va在线观看| 成人爽a毛片一区二区免费| 在线精品一区二区三区| 日本一区二区三区四区在线视频| 午夜激情福利电影| 亚洲国产精品久久久男人的天堂 | 7777精品伊人久久久大香线蕉完整版| 99久久精品国产一区二区成人| 精品av久久707| 国产在线视频资源| 久久国产精品久久久| a天堂资源在线| 国产精品视频男人的天堂| 日韩黄色av| 热re99久久精品国产99热| 欧美a级片视频| 丝袜人妻一区二区三区| 日本视频在线一区| 4438x全国最大成人| 国产调教视频一区| 亚洲欧美一区二区三区四区五区| 欧美性极品xxxx做受| 一区二区三区黄色片| 亚洲第一精品自拍| 日本在线免费网| 97在线看免费观看视频在线观看| 亚州精品国产| 久久99精品国产99久久| 91精品国产91久久综合| 播放灌醉水嫩大学生国内精品| 韩国av一区二区三区| aaaaa级少妇高潮大片免费看| 日韩美女视频一区| 日韩在线播放中文字幕| 精品少妇一区二区三区在线播放| 福利视频在线播放| 97精品视频在线| 国产精品麻豆| 亚洲国内在线| 亚洲综合另类| 亚洲欧美日韩色| 亚洲精品伦理在线| 一级黄色片在线播放| 亚洲精品在线看| 国产网红在线观看| 亚洲在线观看视频| 99久久夜色精品国产亚洲96| 国产熟女高潮视频| 91啪亚洲精品| 国产精品99无码一区二区| 91精品在线一区二区| 1区2区3区在线观看| 日本一区二区在线播放| 久久久伦理片| 中文字幕人妻熟女人妻洋洋| 韩国v欧美v亚洲v日本v| 成年人免费观看视频网站| 精品久久久久久久久久久| 午夜精品久久久久久久第一页按摩| xvideos亚洲人网站| 深夜视频一区二区| 日韩视频精品| 肉丝袜脚交视频一区二区| 午夜理伦三级做爰电影| 欧美日韩在线免费| 亚洲av成人精品一区二区三区在线播放 | 欧美色图片你懂的| www.亚洲.com| 国产精品久久久久久久久久新婚| 九一国产精品| 99视频精品免费| 国产亚洲美州欧州综合国| 久久久久久在线观看| 亚洲天堂av网| 蜜桃成人精品| 午夜精品视频在线观看一区二区| 日韩高清不卡在线| 一级黄色片网址| 欧美视频一区二区| 18视频免费网址在线观看| 成人黄色在线观看| 91精品久久久久久久蜜月| 永久免费黄色片| 一区二区三区高清在线| 亚洲av无码乱码国产精品久久| 欧美激情久久久久| 你懂的在线观看一区二区| 啊啊啊一区二区| 久久精品无码一区二区三区| 中文字幕免费播放| 久久久成人精品| 超碰97久久国产精品牛牛| 国产精品999视频| 久久久美女毛片| 亚洲熟女乱色一区二区三区久久久 | 永久91嫩草亚洲精品人人| 少妇性l交大片7724com| 亚洲国产精品久久久男人的天堂 | 欧美中文字幕在线观看视频| 成人激情动漫在线观看| 国产嫩bbwbbw高潮| 日韩小视频在线观看| 亚洲一区二区三区四区电影| 好吊妞无缓冲视频观看| 国产午夜亚洲精品理论片色戒 | 日本视频免费一区| 日韩精品123区| 亚洲国产日韩欧美在线99| 欧美aaa视频| 国产成人免费高清视频| 91片黄在线观看| 91精品人妻一区二区三区果冻| 欧美激情在线一区| 国产不卡一区| 日本美女久久久| 色呦呦网站一区| www久久日com| 蜜桃精品久久久久久久免费影院| 久久激情综合网| 日本三级片在线观看| 中文字幕自拍vr一区二区三区| 国产精品视屏| 三上悠亚在线一区| 欧美日韩美女视频|