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

一篇文章帶你學(xué)習(xí)etcd-wal模塊解析

數(shù)據(jù)庫 其他數(shù)據(jù)庫
etcd會判斷命令是否合法,然后Leader 收到提案后,通過 Raft 模塊的事件總線保存待發(fā)給 Follower 節(jié)點(diǎn)的消息和待持久化的日志條目,日志條目是封裝的entry。

[[408646]]

Part1常見的數(shù)據(jù)庫日志

傳統(tǒng)數(shù)據(jù)庫的日志,例如 redo log(重做日志),記錄的是修改后的數(shù)據(jù)。其實(shí)就是 MySQL 里經(jīng)常說到的 WAL 技術(shù),它的關(guān)鍵點(diǎn)就是先寫日志,再寫磁盤。

  • redo log 是 InnoDB 引擎特有的;binlog 是 MySQL 的 Server 層實(shí)現(xiàn)的,所有引擎都可以使用。redo log 是物理日志,記錄的是“在某個(gè)數(shù)據(jù)頁上做了什么修改”;
  • binlog 是邏輯日志,記錄的是這個(gè)語句的原始邏輯,比如“給 ID=2 這一行的 c 字段加 1 ”。redo log 是循環(huán)寫的,空間固定會用完;
  • binlog 是可以追加寫入的。“追加寫”是指 binlog 文件寫到一定大小后會切換到下一個(gè),并不會覆蓋以前的日志。

redis使用AOF(Append Only File),這樣做的好處是會在執(zhí)行命令成功后保存,不需要提前驗(yàn)證命令是否正確。AOF會保存服務(wù)器執(zhí)行的所有寫操作到日志文件中,在服務(wù)重啟以后,會執(zhí)行這些命令來恢復(fù)數(shù)據(jù)。而 AOF 里記錄的是 Redis 收到的每一條命令,這些命令是以文本形式保存的。

etcd會判斷命令是否合法,然后Leader 收到提案后,通過 Raft 模塊的事件總線保存待發(fā)給 Follower 節(jié)點(diǎn)的消息和待持久化的日志條目,日志條目是封裝的entry。etcdserver 從 Raft 模塊獲取到以上消息和日志條目后,作為 Leader,它會將 put 提案消息廣播給集群各個(gè)節(jié)點(diǎn),同時(shí)需要把集群 Leader 任期號、投票信息、已提交索引、提案內(nèi)容持久化到一個(gè) WAL(Write Ahead Log)日志文件中,用于保證集群的一致性、可恢復(fù)性。

Part2wal源碼分析

etcd server在啟動時(shí),會根據(jù)是否wal目錄來確定之前etcd是否創(chuàng)建過wal,如果沒有創(chuàng)建wal,etcd會嘗試調(diào)用wal.Create方法,創(chuàng)建wal。否則使用wal.Open及wal.ReadAll方法是reload之前的wal,邏輯在etcd/etcdserver/server.go的NewServer方法里,存在wal時(shí)會調(diào)用restartNode,下面分創(chuàng)建wal和加載wal兩種情況作介紹。

wal的關(guān)鍵對象介紹如下

wal日志結(jié)構(gòu).png

dir:wal文件保存的路徑

dirFile:dir打開后的一個(gè)目錄fd對象

metadata:創(chuàng)建wal時(shí)傳入的字節(jié)序列,etcd里面主要是序列化的是節(jié)點(diǎn)id及集群id相關(guān)信息,后續(xù)每創(chuàng)建一個(gè)wal文件就會將其寫到wal的首部。

state:wal在append過程中保存的hardState信息,每次raft傳出的hardState有變化都會被更新,并會及時(shí)刷盤,在wal有切割時(shí)會在新的wal頭部保存最新的

hardState信息,etcd重啟后會讀取最后一次保存的hardState用來恢復(fù)宕機(jī)或機(jī)器重啟時(shí)storage中hardState狀態(tài)信息,hardState的結(jié)構(gòu)如下:

  1. type HardState struct { 
  2.  Term             uint64 `protobuf:"varint,1,opt,name=term" json:"term"
  3.  Vote             uint64 `protobuf:"varint,2,opt,name=vote" json:"vote"
  4.  Commit           uint64 `protobuf:"varint,3,opt,name=commit" json:"commit"
  5.  XXX_unrecognized []byte `json:"-"

start:記錄最后一次保存的snapshot的元數(shù)據(jù)信息,主要是snapshot中最后一條日志Entry的index和Term,walpb.Snapshot的結(jié)構(gòu)如:

  1. type Snapshot struct { 
  2.  Index            uint64 `protobuf:"varint,1,opt,name=index" json:"index"
  3.  Term             uint64 `protobuf:"varint,2,opt,name=term" json:"term"
  4.  XXX_unrecognized []byte `json:"-"

decoder:負(fù)責(zé)在讀取WAL日志文件時(shí),將protobuf反序列化成Record實(shí)例。

readClose:用于關(guān)閉decoder關(guān)聯(lián)的reader,關(guān)閉wal讀模式,通過是在readALL之后調(diào)用該函數(shù)實(shí)現(xiàn)的

enti:最后一次保存到wal中的日志Entry的index

encoder:負(fù)責(zé)將寫入WAL日志文件的Record實(shí)例進(jìn)行序列化成protobuf。

size :創(chuàng)建臨時(shí)文件時(shí)預(yù)分配空間的大小,默認(rèn)是 64MB (由wal.SegmentSizeBytes指定,該值也是每個(gè)日志文件的大小)。

locks:當(dāng)前WAL實(shí)例管理的所有WAL日志文件對應(yīng)的句柄。

fp:filePipeline實(shí)例負(fù)責(zé)創(chuàng)建新的臨時(shí)文件。

WAL創(chuàng)建

先來看一下wal.Create()方法,該方法不僅會創(chuàng)建WAL實(shí)例,而是做了很多初始化工作,其大致步驟如下:

(1)創(chuàng)建臨時(shí)目錄,并在臨時(shí)目錄中創(chuàng)建編號為“0-0”的WAL日志文件,WAL日志文件名由兩部分組成,一部分是seq(單調(diào)遞增),另一部分是該日志文件中的第一條日志記錄的索引值。

(2)嘗試為該WAL日志文件預(yù)分配磁盤空間。

(3)向該WAL日志文件中寫入一條crcType類型的日志記錄、一條metadataType類型的日志記錄及一條snapshotType類型的日志記錄。

(4)創(chuàng)建WAL實(shí)例關(guān)聯(lián)的filePipeline實(shí)例。

(5)將臨時(shí)目錄重命名為WAL.dir字段指定的名稱。這里之所以先使用臨時(shí)目錄完成初始化操作再將其重命名的方式,主要是為了讓整個(gè)初始化過程看上去是一個(gè)原子操作。這樣上層模塊只需要檢查wal的目錄是否存在。

wal.Create()方法的具體實(shí)現(xiàn)如下:

  1. // Create creates a WAL ready for appending records. The given metadata is 
  2. // recorded at the head of each WAL file, and can be retrieved(檢索) with ReadAll. 
  3. func Create(dirpath string, metadata []byte) (*WAL, error) { 
  4.      
  5.  // keep temporary wal directory so WAL initialization appears atomic 
  6.     //先使用臨時(shí)目錄完成初始化操作再將其重命名的方式,主要是為了讓整個(gè)初始化過程看上去是一個(gè)原子操作。 
  7.  tmpdirpath := filepath.Clean(dirpath) + ".tmp" 
  8.  if fileutil.Exist(tmpdirpath) { 
  9.   if err := os.RemoveAll(tmpdirpath); err != nil { 
  10.    return nil, err 
  11.   } 
  12.  } 
  13.  if err := fileutil.CreateDirAll(tmpdirpath); err != nil { 
  14.   return nil, err 
  15.  } 
  16.  // dir/filename  ,filename從walName獲取  seq-index.wal 
  17.  p := filepath.Join(tmpdirpath, walName(0, 0)) 
  18.  // 創(chuàng)建對文件上互斥鎖 
  19.  f, err := fileutil.LockFile(p, os.O_WRONLY|os.O_CREATE, fileutil.PrivateFileMode) 
  20.  if err != nil { 
  21.   return nil, err 
  22.  } 
  23.  // 定位到文件末尾 
  24.  if _, err = f.Seek(0, io.SeekEnd); err != nil { 
  25.   return nil, err 
  26.  } 
  27.  // 預(yù)分配文件,大小為SegmentSizeBytes(64MB) 
  28.  if err = fileutil.Preallocate(f.File, SegmentSizeBytes, true); err != nil { 
  29.   return nil, err 
  30.  } 
  31.  // 新建WAL結(jié)構(gòu) 
  32.  w := &WAL{ 
  33.   dir:      dirpath, 
  34.   metadata: metadata,// metadata 可為nil 
  35.  } 
  36.  // 在這個(gè)wal文件上創(chuàng)建一個(gè)encoder 
  37.  w.encoder, err = newFileEncoder(f.File, 0) 
  38.  if err != nil { 
  39.   return nil, err 
  40.  } 
  41.  // 把這個(gè)上了互斥鎖的文件加入到locks數(shù)組中 
  42.  w.locks = append(w.locks, f) 
  43.  if err = w.saveCrc(0); err != nil { 
  44.   return nil, err 
  45.  } 
  46.  // 將metadataType類型的record記錄在wal的header處 
  47.  if err = w.encoder.encode(&walpb.Record{Type: metadataType, Data: metadata}); err != nil { 
  48.   return nil, err 
  49.  } 
  50.  // 保存空的snapshot 
  51.  if err = w.SaveSnapshot(walpb.Snapshot{}); err != nil { 
  52.   return nil, err 
  53.  } 
  54.  // 之前以.tmp結(jié)尾的文件,初始化完成之后重命名 
  55.  if w, err = w.renameWal(tmpdirpath); err != nil { 
  56.   return nil, err 
  57.  } 
  58.  // directory was renamed; sync parent dir to persist rename 
  59.  pdir, perr := fileutil.OpenDir(filepath.Dir(w.dir)) 
  60.  if perr != nil { 
  61.   return nil, perr 
  62.  } 
  63.     // 將parent dir 進(jìn)行同步到磁盤 
  64.  if perr = fileutil.Fsync(pdir); perr != nil { 
  65.   return nil, perr 
  66.  } 
  67.  
  68.     return w, nil 

WAL日志文件遵循一定的命名規(guī)則,由walName實(shí)現(xiàn),格式為"序號--raft日志索引.wal"。

  1. // 根據(jù)seq和index產(chǎn)生wal文件名 
  2. func walName(seq, index uint64) string { 
  3.  return fmt.Sprintf("%016x-%016x.wal", seq, index

在創(chuàng)建的過程中,Create函數(shù)還向WAL日志中寫入了兩條數(shù)據(jù),一條就是記錄metadata,一條是記錄snapshot,WAL中的數(shù)據(jù)都是以Record為單位保存的,結(jié)構(gòu)定義如下:

  1. // 存儲在wal穩(wěn)定存儲中的消息一共有兩種,這是第一種普通記錄的格式 
  2. type Record struct { 
  3.  Type             int64  `protobuf:"varint,1,opt,name=type" json:"type"
  4.  Crc              uint32 `protobuf:"varint,2,opt,name=crc" json:"crc"
  5.  Data             []byte `protobuf:"bytes,3,opt,name=data" json:"data,omitempty"
  6.  XXX_unrecognized []byte `json:"-"

Record類型

其中Type字段表示該Record的類型,取值可以是以下幾種:

  1. const ( 
  2.  metadataType int64 = iota + 1 
  3.  entryType 
  4.  stateType 
  5.  crcType 
  6.  snapshotType 
  7.  // warnSyncDuration is the amount of time allotted to an fsync before 
  8.  // logging a warning 
  9.  warnSyncDuration = time.Second 

對應(yīng)于raft中的Snapshot(應(yīng)用狀態(tài)機(jī)的Snapshot),WAL中也會記錄一些Snapshot的信息(但是它不會記錄完整的應(yīng)用狀態(tài)機(jī)的Snapshot數(shù)據(jù)),WAL中的Snapshot格式定義如下:

  1. // 存儲在wal中的第二種Record消息,snapshot 
  2. type Snapshot struct { 
  3.  Index            uint64 `protobuf:"varint,1,opt,name=index" json:"index"
  4.  Term             uint64 `protobuf:"varint,2,opt,name=term" json:"term"
  5.  XXX_unrecognized []byte `json:"-"

在保存Snapshot的(注意這里的Snapshot是WAL里的Record類型,不是raft中的應(yīng)用狀態(tài)機(jī)的Snapshot)SaveSnapshot函數(shù)中:

  1. // 持久化walpb.Snapshot 
  2. func (w *WAL) SaveSnapshot(e walpb.Snapshot) error { 
  3.  // pb序列化,此時(shí)的e可為空的 
  4.  b := pbutil.MustMarshal(&e) 
  5.  w.mu.Lock() 
  6.  defer w.mu.Unlock() 
  7.     // 創(chuàng)建snapshotType類型的record 
  8.  rec := &walpb.Record{Type: snapshotType, Data: b} 
  9.  // 持久化到wal中 
  10.  if err := w.encoder.encode(rec); err != nil { 
  11.   return err 
  12.  } 
  13.  // update enti only when snapshot is ahead of last index 
  14.  if w.enti < e.Index { 
  15.   // index of the last entry saved to the wal 
  16.   // e.Index來自應(yīng)用狀態(tài)機(jī)的Index 
  17.   w.enti = e.Index 
  18.  } 
  19.  // 同步刷新磁盤 
  20.  return w.sync() 

一條Record需要先把序列化后才能持久化,這個(gè)是通過encode函數(shù)完成的(encoder.go),代碼如下:

  1. // 將Record序列化后持久化到WAL文件 
  2. func (e *encoder) encode(rec *walpb.Record) error { 
  3.  e.mu.Lock() 
  4.  defer e.mu.Unlock() 
  5.  e.crc.Write(rec.Data) 
  6.  // 生成數(shù)據(jù)的crc 
  7.  rec.Crc = e.crc.Sum32() 
  8.  var ( 
  9.   data []byte 
  10.   err  error 
  11.   n    int 
  12.  ) 
  13.  if rec.Size() > len(e.buf) { 
  14.   // 如果超過預(yù)分配的buf,就使用動態(tài)分配 
  15.   data, err = rec.Marshal() 
  16.   if err != nil { 
  17.    return err 
  18.   } 
  19.  } else { 
  20.   // 否則就使用與分配的buf 
  21.   n, err = rec.MarshalTo(e.buf) 
  22.   if err != nil { 
  23.    return err 
  24.   } 
  25.   data = e.buf[:n] 
  26.  } 
  27.  lenField, padBytes := encodeFrameSize(len(data)) 
  28.  // 先寫recode編碼后的長度 
  29.  if err = writeUint64(e.bw, lenField, e.uint64buf); err != nil { 
  30.   return err 
  31.  } 
  32.  if padBytes != 0 { 
  33.   // 如果有追加數(shù)據(jù)(對齊需求) 
  34.   data = append(data, make([]byte, padBytes)...) 
  35.  } 
  36.  // 寫recode內(nèi)容 
  37.  _, err = e.bw.Write(data) 
  38.  return err 

從代碼可以看到,一個(gè)Record被序列化之后(這里為protobuf格式),會以一個(gè)Frame的格式持久化。Frame首先是一個(gè)長度字段(encodeFrameSize完成,在encoder.go文件),64bit,56bit存數(shù)據(jù)。其中MSB表示這個(gè)Frame是否有padding字節(jié),接下來才是真正的序列化后的數(shù)據(jù)。一般一個(gè)page是4096字節(jié),對齊到8字節(jié),不會出現(xiàn)一個(gè)double被拆到兩個(gè)page的情況,在cache中,也不會被拆開:

  1. func encodeFrameSize(dataBytes int) (lenField uint64, padBytes int) { 
  2.  lenField = uint64(dataBytes) 
  3.  // force 8 byte alignment so length never gets a torn write 
  4.  padBytes = (8 - (dataBytes % 8)) % 8 
  5.  if padBytes != 0 { 
  6.   // lenField的高56記錄padding的長度 
  7.   lenField |= uint64(0x80|padBytes) << 56 // 最高位為1用于表示含有padding,方便在decode的時(shí)候判斷 
  8.  } 
  9.  return lenField, padBytes 

最終,下圖展示了包含了兩個(gè)WAL文件的示例圖。

filePipeline類型

filePipeline采用“餓漢式”,即提前創(chuàng)建一些文件備用,這樣可以加快文件的創(chuàng)建速度。filePipeline它負(fù)責(zé)預(yù)創(chuàng)建日志文件并為日志文件預(yù)分配空間。在filePipeline中會啟動一個(gè)獨(dú)立的后臺goroutine來創(chuàng)建“.tmp”結(jié)尾的臨時(shí)文件,當(dāng)進(jìn)行日志文件切換時(shí),直接將臨時(shí)文件進(jìn)行重命名即可使用。結(jié)構(gòu)體filePipeline中各個(gè)字段的含義如下。

dir(string類型):存放臨時(shí)文件的目錄。

size (int64 類型):創(chuàng)建臨時(shí)文件時(shí)預(yù)分配空間的大小,默認(rèn)是 64MB (由wal.SegmentSizeBytes指定,該值也是每個(gè)日志文件的大小)。

count(int類型):當(dāng)前filePipeline實(shí)例創(chuàng)建的臨時(shí)文件數(shù)。

filec(chan*fileutil.LockedFile 類型):新建的臨時(shí)文件句柄會通過 filec 通道返回給WAL實(shí)例使用。

errc(chan error類型):當(dāng)創(chuàng)建臨時(shí)文件出現(xiàn)異常時(shí),則將異常傳遞到errc通道中。

donec(chan struct{}類型):當(dāng)filePipeline.Close()被調(diào)用時(shí)會關(guān)閉donec通道,從而通知filePipeline實(shí)例刪除最后一次創(chuàng)建的臨時(shí)文件。

在newFilePipeline()方法中,除了創(chuàng)建filePipeline實(shí)例,還會啟動一個(gè)后臺goroutine來執(zhí)行filePipeline.run()方法,該后臺goroutine中會創(chuàng)建新的臨時(shí)文件并將其句柄傳遞到filec通道中。filePipeline.run()方法的具體實(shí)現(xiàn)如下:

  1. // filePipeline pipelines allocating disk space 
  2. type filePipeline struct { 
  3.  // dir to put files 
  4.  dir string 
  5.  // size of files to make, in bytes 
  6.  size int64 
  7.  // count number of files generated 
  8.  count int 
  9.  filec chan *fileutil.LockedFile 
  10.  errc  chan error 
  11.  donec chan struct{} 
  12. func newFilePipeline(dir string, fileSize int64) *filePipeline { 
  13.  fp := &filePipeline{ 
  14.   dir:   dir, 
  15.   size:  fileSize, 
  16.   filec: make(chan *fileutil.LockedFile), 
  17.   errc:  make(chan error, 1), 
  18.   donec: make(chan struct{}), 
  19.  } 
  20.  // 一直執(zhí)行預(yù)分配 
  21.  go fp.run() 
  22.  return fp 
  23. // Open returns a fresh file for writing. Rename the file before calling 
  24. // Open again or there will be file collisions. 
  25. func (fp *filePipeline) Open() (f *fileutil.LockedFile, err error) { 
  26.  select { 
  27.  case f = <-fp.filec: // 從filec通道中獲取文件描述符,并返回 
  28.  case err = <-fp.errc: // 如果創(chuàng)建失敗,從errc通道中獲取,并返回 
  29.  } 
  30.  return f, err 
  31.  
  32. func (fp *filePipeline) Close() error { 
  33.  close(fp.donec) 
  34.  return <-fp.errc //出現(xiàn)錯(cuò)誤,關(guān)閉donec通道并向errc通到中發(fā)送錯(cuò)誤 
  35.  
  36. func (fp *filePipeline) alloc() (f *fileutil.LockedFile, err error) { 
  37.  // count % 2 so this file isn't the same as the one last published   
  38.     // 創(chuàng)建臨時(shí)文件的編號是0或者1。 
  39.  fpath := filepath.Join(fp.dir, fmt.Sprintf("%d.tmp", fp.count%2)) 
  40.     //創(chuàng)建臨時(shí)文件,注意文件的模式與權(quán)限。 
  41.  if f, err = fileutil.LockFile(fpath, os.O_CREATE|os.O_WRONLY, fileutil.PrivateFileMode); err != nil { 
  42.   return nil, err 
  43.  } 
  44.  // 嘗試預(yù)分配,如果當(dāng)前文件系統(tǒng)不支持預(yù)分配空間,則不會報(bào)錯(cuò)。 
  45.  if err = fileutil.Preallocate(f.File, fp.sizetrue); err != nil { 
  46.   f.Close() //如果出現(xiàn)異常,則會關(guān)閉donec通道 
  47.   return nil, err 
  48.  } 
  49.  // 已經(jīng)分配的文件個(gè)數(shù) 
  50.  fp.count++ 
  51.  return f, nil //返回創(chuàng)建的臨時(shí)文件 
  52.  
  53. // goroutine 
  54. func (fp *filePipeline) run() { 
  55.  defer close(fp.errc) 
  56.  for { 
  57.   // 調(diào)用alloc()執(zhí)行創(chuàng)建臨時(shí)文件 
  58.   f, err := fp.alloc() 
  59.   if err != nil { 
  60.    fp.errc <- err 
  61.    return 
  62.   } 
  63.   select { 
  64.   case fp.filec <- f:  // 等待消費(fèi)方從這個(gè)channel中取出這個(gè)預(yù)創(chuàng)建的被鎖的文件 
  65.   case <-fp.donec:    //關(guān)閉時(shí)觸發(fā),刪除最后一次創(chuàng)建的臨時(shí)文件 
  66.    os.Remove(f.Name()) 
  67.    f.Close() 
  68.    return 
  69.   } 
  70.  } 

本文轉(zhuǎn)載自微信公眾號「 運(yùn)維開發(fā)故事」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請聯(lián)系 運(yùn)維開發(fā)故事公眾號。

 

責(zé)任編輯:姜華 來源: 運(yùn)維開發(fā)故事
相關(guān)推薦

2021-05-15 09:18:04

Python進(jìn)程

2021-06-16 14:44:32

etcd-raftRaftLeader

2021-07-13 11:37:47

cpu架構(gòu)Linux

2021-11-17 10:11:08

PythonLogging模塊

2021-11-10 09:19:41

PythonShutil模塊

2022-02-21 09:44:45

Git開源分布式

2021-06-30 00:20:12

Hangfire.NET平臺

2023-05-12 08:19:12

Netty程序框架

2023-05-08 08:21:15

JavaNIO編程

2021-03-09 14:04:01

JavaScriptCookie數(shù)據(jù)

2021-09-27 09:18:30

ListIterato接口方法

2021-01-26 23:46:32

JavaScript數(shù)據(jù)結(jié)構(gòu)前端

2024-01-30 13:47:45

2023-07-30 15:18:54

JavaScript屬性

2021-02-26 20:01:57

SVG濾鏡元素

2021-05-18 08:30:42

JavaScript 前端JavaScript時(shí)

2023-09-06 14:57:46

JavaScript編程語言

2024-04-19 14:23:52

SwitchJavaScript開發(fā)

2021-06-24 09:05:08

JavaScript日期前端

2021-03-05 18:04:15

JavaScript循環(huán)代碼
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

久久se这里有精品| 久操精品在线| 午夜成人在线视频| 欧美一区二区综合| 97人妻精品一区二区三区| 欧美国产高潮xxxx1819| 国产丝袜一区二区三区| 国产成人美女视频| 九色porny丨入口在线| 国产精品久久久久久妇女6080| www.成人av| 波多野结衣在线观看视频| 中文在线日韩| 一区二区三区精品99久久| 免费在线观看日韩av| 欧美7777| 亚洲综合图片区| 亚洲欧洲日韩精品| 亚洲aaaaaaa| 精品一二三四在线| 日韩免费观看视频| 国产精品白浆一区二小说| 四季av在线一区二区三区| 亚洲精品suv精品一区二区| 日本三级黄色网址| 日本成人三级电影| 午夜不卡av免费| 超碰在线免费观看97| 久久久久国产精品嫩草影院| 粉嫩蜜臀av国产精品网站| 国产欧美日韩丝袜精品一区| 一级黄色大片视频| 在线精品观看| 欧美激情影音先锋| 欧美日韩在线观看免费| 国产精品99在线观看| 亚洲欧美国产精品| 野外性满足hd| 国产日韩三级| 精品少妇一区二区三区免费观看 | 日韩福利视频导航| 91国内揄拍国内精品对白| 欧美黄色一级网站| 欧美在线高清| 超薄丝袜一区二区| 波多野结衣喷潮| 日韩影院二区| 日韩一中文字幕| 免费一级黄色录像| 精品国产一级毛片| 亚洲欧洲日本专区| 久久精品国产亚洲av久| 婷婷精品在线观看| 精品亚洲一区二区三区四区五区| 中国极品少妇xxxx| 老汉色老汉首页av亚洲| 亚洲电影免费观看高清完整版在线 | 欧美一级理论片| 色综合久久久无码中文字幕波多| 欧美日韩黄色| 精品美女被调教视频大全网站| 日本少妇一级片| 国产伦理久久久久久妇女| 亚洲国产小视频在线观看| 日本黄色录像片| 亚洲区小说区| 在线亚洲欧美视频| 青青操在线视频观看| 亚洲最大av| 久久久久久国产精品久久| 日韩欧美视频在线免费观看| 先锋影音久久| 国产精品免费网站| 国产深喉视频一区二区| 国产成人精品一区二| 国产精品区一区二区三在线播放| 日本成人一区| 国产精品毛片无遮挡高清| 亚洲欧美日韩不卡| 123区在线| 欧洲日韩一区二区三区| 九一精品久久久| 第四色中文综合网| 国产丝袜一区二区三区免费视频| 九九九视频在线观看| 午夜精品视频一区二区三区在线看| 欧美精品在线播放| 日本熟妇乱子伦xxxx| 石原莉奈在线亚洲二区| 成人乱色短篇合集| 污污的视频网站在线观看| 国产日本欧洲亚洲| 国产内射老熟女aaaa| 老色鬼在线视频| 欧美色倩网站大全免费| 欧美人与性动交α欧美精品| 亚洲黄色录像| 久久久精品中文字幕| 日本一区二区免费在线观看| 日韩中文欧美在线| 操人视频欧美| 幼a在线观看| 亚洲a一区二区| 手机av在线网| 一区三区在线欧| 欧美成人午夜激情| 波多野结衣毛片| 东方欧美亚洲色图在线| 亚洲精品免费在线看| 黄色在线观看视频网站| 欧美酷刑日本凌虐凌虐| 色无极影院亚洲| 欧美三级小说| 国产精品永久在线| 免费在线国产| 亚洲高清视频的网址| 日本高清一区二区视频| 伊人成综合网伊人222| 欧美精品第一页在线播放| 在线免费av网| 国产亚洲制服色| aa在线观看视频| 一区视频网站| 美女av一区二区三区| 欧美日韩 一区二区三区| 波多野结衣一区二区三区 | 一区二区三区精品视频在线观看 | 国产毛片毛片毛片毛片| 日本一区二区三区免费乱视频 | 美女国产一区二区三区| 欧美成ee人免费视频| 黑人另类精品××××性爽| 欧美人与禽zozo性伦| 永久免费av无码网站性色av| 亚洲欧美日韩国产综合精品二区| 国产精品av一区| 丝袜在线观看| 91精品国产一区二区| 亚洲AV成人无码精电影在线| 蜜臀av性久久久久蜜臀aⅴ四虎 | 激情欧美一区| 国产v亚洲v天堂无码| 性欧美videoshd高清| 91精品婷婷国产综合久久竹菊| xxxxx99| 日本伊人色综合网| 日本一区二区三不卡| 三上悠亚一区二区| 亚洲欧美日韩在线一区| 在线观看日本网站| 久久久不卡影院| 久久精品视频91| 不卡在线一区| 国产精品中文在线| 欧美jizz18hd性欧美| 欧美久久婷婷综合色| 91动漫免费网站| 韩国欧美一区二区| 色哟哟免费网站| aiai久久| 97在线看免费观看视频在线观看| 偷拍25位美女撒尿视频在线观看| 欧美日韩国产在线看| 欧美做受xxxxxⅹ性视频| 久久亚洲一区| 在线观看精品视频| 久久久久毛片免费观看| 欧美福利视频网站| 四虎精品在线| 欧美色欧美亚洲另类二区| 日本在线一级片| 国产成人av电影在线| 欧美精品久久久久久久久久久| 久久草在线视频| 国产精品露脸av在线| 久cao在线| 亚洲成人精品视频在线观看| 日韩视频在线观看一区| 国产精品久久久久久户外露出| 亚洲综合中文网| 久久国产欧美| 国产欧美自拍视频| 免费看久久久| 国产精品视频xxxx| xxxx在线视频| 国产一区二区精品丝袜| 精品国产九九九| 欧美视频在线观看 亚洲欧| 特黄一区二区三区| 成人美女视频在线看| 精品久久久噜噜噜噜久久图片 | 人体久久天天| 国产欧美日韩视频| 激情国产在线| 最近2019年好看中文字幕视频 | 久久精品一区四区| 特黄特黄一级片| 丝瓜av网站精品一区二区| 国产欧美123| 国产一区二区三区探花| 97夜夜澡人人双人人人喊| 欧美最新精品| 久久青草福利网站| 国产超级va在线视频| 国产婷婷色综合av蜜臀av| 99久久久国产精品无码网爆| 日韩欧美极品在线观看| 欧美国产日韩综合| 国产精品亲子伦对白| 99久久人妻精品免费二区| 久久成人免费电影| av网址在线观看免费| 国内精品福利| 一区二区三区四区久久| 自拍欧美一区| 国产区一区二区| 国产一区二区在线观| 国产精品永久在线| 校园春色亚洲色图| 午夜精品一区二区三区在线视频| 草莓福利社区在线| 日韩中文字幕在线播放| 欧美老女人性开放| 日韩av在线不卡| 亚洲av综合色区无码一二三区| 欧美日韩免费在线视频| 丰满熟女人妻一区二区三| 欧美日韩免费看| 国产主播在线观看| 亚洲一卡二卡三卡四卡无卡久久 | 91香蕉电影院| 综合欧美精品| 国产区精品视频| 久久99国产精品二区高清软件| 琪琪第一精品导航| 深夜在线视频| 欧美在线观看网址综合| 欧美激情网站| 欧美性视频在线| 性感女国产在线| 午夜精品福利在线观看| 2020av在线| 91黑丝高跟在线| 麻豆免费版在线观看| 性欧美激情精品| 日韩伦理福利| 国产成人小视频在线观看| 久久野战av| 国产欧美欧洲在线观看| 久久久久久一区二区三区四区别墅| 国产精品日韩精品| 亚洲狼人在线| 亚洲字幕一区二区| 538任你躁精品视频网免费| 成人毛片网站| 久久午夜影院| 欧美久久在线| 色综合咪咪久久网| 中文字幕精品在线播放| 国产精品99免费看| 日韩伦理在线免费观看| 亚洲一区日韩| 国产理论在线播放| 久久99精品久久只有精品| 亚洲成人手机在线观看| 成人一区二区三区中文字幕| 中文字幕免费高清视频| 国产午夜亚洲精品理论片色戒| 男人天堂资源网| 亚洲自拍偷拍综合| 久久国产视频精品| 欧美人与性动xxxx| 丰满少妇在线观看bd| 日韩精品免费看| jizz在线观看| 欧美富婆性猛交| 欧美日韩美女| 亚洲伊人一本大道中文字幕| 超碰精品在线观看| 精品欧美国产| 欧美高清视频在线观看mv| 国产黄色激情视频| 性感少妇一区| 波多野结衣电影免费观看| www国产精品av| 手机av在线看| 高潮白浆女日韩av免费看| 一级黄色片网站| 亚洲精品久久久久久久久久久久 | 亚洲欧美成人vr| 99久re热视频精品98| 亚洲欧美大片| 99国产精品免费视频| 国产午夜精品一区二区三区视频| 国产精品嫩草影院俄罗斯| 日韩欧美国产高清91| 99久久婷婷国产一区二区三区| 亚洲黄一区二区| 免费在线观看黄色网| 欧美一级视频免费在线观看| 中文成人激情娱乐网| 欧美一区二区在线| 激情av一区| 在线不卡一区二区三区| 91影院在线免费观看| 91精品一区二区三区蜜桃| 日韩欧美在线视频| 亚洲精品久久久狠狠狠爱 | 91九色美女在线视频| 国产欧美一区二区三区在线| 亚洲8888| 人人妻人人澡人人爽欧美一区双 | 无码国产精品一区二区免费式直播 | 国产精品久久久久久久免费大片 | 亚洲熟妇无码av在线播放| 免费高清视频精品| 玖玖爱在线观看| 亚洲不卡一区二区三区| 国产精品久久久久久久久久久久久久久久 | 日韩区在线观看| 免费看美女视频在线网站| 国产91热爆ts人妖在线| 欧美精品密入口播放| 无码人妻精品一区二区蜜桃百度| 蜜桃av一区二区| 国产又粗又黄又猛| 色88888久久久久久影院野外| 日本人妻熟妇久久久久久| 欧美高清在线观看| 中文字幕成人| 天天干天天操天天干天天操| 免费黄网站欧美| 欧美日韩生活片| 欧美自拍偷拍一区| 国产资源在线看| 国产成人精品网站| 自拍欧美一区| 无码少妇一区二区三区芒果| 久久亚洲一级片| 无码人妻久久一区二区三区| 亚洲欧美日韩精品久久| 在线观看爽视频| 欧美日韩精品免费看| 香蕉久久国产| 五月天综合视频| 日本韩国精品在线| jizz在线免费观看| 成人国产精品免费视频| 亚洲国产日韩欧美在线| 亚洲热在线视频| 亚洲一区二区欧美| 天堂在线观看av| 欧美一级成年大片在线观看| 偷拍视屏一区| 色哟哟精品视频| 日韩毛片高清在线播放| 精品人妻少妇嫩草av无码专区| 久久99国产精品自在自在app| eeuss国产一区二区三区四区| 每日在线观看av| 久久午夜老司机| 在线免费观看中文字幕| 精品国产欧美一区二区三区成人| 99亚洲男女激情在线观看| 神马午夜伦理影院| 99久久99久久久精品齐齐| 午夜精品免费观看| 久久精品视频一| 久久综合另类图片小说| 国产超碰在线播放| 亚洲男人电影天堂| 无码精品黑人一区二区三区| 国产精品成人aaaaa网站| 99久久九九| 给我免费观看片在线电影的| 欧美亚洲图片小说| 少女频道在线观看高清| 久久久久网址| 黑人巨大精品欧美一区| 四虎成人精品永久免费av| 亚洲三级 欧美三级| 国产精品亚洲四区在线观看| 青青青国产在线观看| 国产精品天干天干在线综合| 亚洲国产精品一| 日本亚洲欧美三级| 综合激情网站| 亚洲a v网站| 欧美变态tickling挠脚心| 国产精品专区免费| 屁屁影院ccyy国产第一页| 中文字幕欧美日韩一区| 狠狠人妻久久久久久综合麻豆| 国产精品久久二区| 在线观看视频日韩| 日本黄色录像视频| 亚洲乱码国产乱码精品精天堂| 五月亚洲婷婷| 黄色三级视频在线| 黄网站色欧美视频|