亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 數據庫 > Redis > 正文

Redis緩存詳解

2020-03-17 12:39:03
字體:
來源:轉載
供稿:網友

下面來正式分享今天的文章吧:

。搭建Redis服務端,并用客戶端連接

。封裝緩存父類,定義Get,Set等常用方法

。定義RedisCache緩存類,執行Redis的Get,Set方法

。構造出緩存工廠調用方法

下面一步一個腳印的來分享:

。搭建Redis服務端,并用客戶端連接

首先,咋們去這個地址下載安裝文件https://github.com/dmajkic/redis/downloads,我這里的版本是:redis-2.4.5-win32-win64里面有32位和64位的執行文件,我這里服務器是64位的下面給出截圖和用到部分程序的說明:

Redis,緩存

現在,咋們直接可以用鼠標雙擊redis-server.exe這個應用程序,這樣就打開了redis服務窗體(您也可以下載一個windows服務承載器,把redis服務運行在windows的服務中,就不用擔心每次關閉redis服務黑色窗體后無法訪問redis了),運行起來是這樣:

Redis,緩存

有紅色框的信息就表示成功了,這里redis服務監聽的端口默認是6379,要修改端口或者更多的配置信息請找到redis.conf配置文件,具體配置信息介紹可以來這里http://www.shouce.ren/api/view/a/6231

再來,打開客戶端連接服務端,咋們退到64bit文件夾的目錄中,鼠標移到64bit文件夾上并且安裝Shift鍵,同時點擊鼠標的右鍵,選中"在此處打開命令窗口"這樣快速進入到了該文件夾的cmd命令窗口中(當然不同的操作系統不同,這里演示的是windows的操作;還有其他進入的方式這里不做介紹,因為個人感覺這是最快的);然后,在命令窗口中錄入redis-cli.exe -h localhost -p 6379回車來訪問服務端,效果圖:

Redis,緩存

再來看下服務端窗體截圖:

Redis,緩存

沒錯這樣客戶端就連接上服務端了,可以簡單在客戶端執行下set,get命令:

Redis,緩存

如果是客戶端要訪問遠程的redis服務端,只需要把localhost換成可訪問的ip就行了如果還需要密碼等更多配置請去上面的那個地址鏈接;

 。封裝緩存父類,定義Get,Set等常用方法

先來,上父類的代碼:

public class BaseCache : IDisposable  {    protected string def_ip = string.Empty;    protected int def_port = 0;    protected string def_password = string.Empty;    public BaseCache()    {    }    public virtual void InitCache(string ip = "", int port = 0, string password = "")    {    }    public virtual bool SetCache<T>(string key, T t, int timeOutMinute = 10) where T : class,new()    {      return false;    }    public virtual T GetCache<T>(string key) where T : class,new()    {      return default(T);    }    public virtual bool Remove(string key)    {      return false;    }    public virtual bool FlushAll()    {      return false;    }    public virtual bool Any(string key)    {      return false;    }    public virtual void Dispose(bool isfalse)    {      if (isfalse)      {      }    }    //手動釋放    public void Dispose()    {      this.Dispose(true);      //不自動釋放      GC.SuppressFinalize(this);    }  }

 這里定義的方法沒有太多的注釋,更多的意思我想看方法名稱就明白了,這個父類主要實現了IDisposable,實現的Dispose()中主要用來釋放資源并且自定義了一個 public virtual void Dispose(bool isfalse)方法,這里面有一句是GC.SuppressFinalize(this);按照官網介紹的意思是阻塞自動釋放資源,其他的沒有什么了,繼續看下面的

。定義RedisCache緩存類,執行Redis的Get,Set方法

首先,咋們分別定義類RedisCache,MemcachedCache(這里暫未實現對memcache緩存的操作),并且繼承BaseCache,重寫Set,Get方法如下代碼:

/// <summary>  /// Redis緩存  /// </summary>  public class RedisCache : BaseCache  {    public RedisClient redis = null;    public RedisCache()    {      //這里去讀取默認配置文件數據      def_ip = "172.0.0.1";      def_port = 6379;      def_password = "";    }    #region Redis緩存    public override void InitCache(string ip = "", int port = 0, string password = "")    {      if (redis == null)      {        ip = string.IsNullOrEmpty(ip) ? def_ip : ip;        port = port == 0 ? def_port : port;        password = string.IsNullOrEmpty(password) ? def_password : password;        redis = new RedisClient(ip, port, password);      }    }    public override bool SetCache<T>(string key, T t, int timeOutMinute = 10)    {      var isfalse = false;      try      {        if (string.IsNullOrEmpty(key)) { return isfalse; }        InitCache();        isfalse = redis.Set<T>(key, t, TimeSpan.FromMinutes(timeOutMinute));      }      catch (Exception ex)      {      }      finally { this.Dispose(); }      return isfalse;    }    public override T GetCache<T>(string key)    {      var t = default(T);      try      {        if (string.IsNullOrEmpty(key)) { return t; }        InitCache();        t = redis.Get<T>(key);      }      catch (Exception ex)      {      }      finally { this.Dispose(); }      return t;    }    public override bool Remove(string key)    {      var isfalse = false;      try      {        if (string.IsNullOrEmpty(key)) { return isfalse; }        InitCache();        isfalse = redis.Remove(key);      }      catch (Exception ex)      {      }      finally { this.Dispose(); }      return isfalse;    }    public override void Dispose(bool isfalse)    {      if (isfalse && redis != null)      {        redis.Dispose();        redis = null;      }    }    #endregion  }  /// <summary>  /// Memcached緩存  /// </summary>  public class MemcachedCache : BaseCache  {  }

這里,用到的RedisClient類是來自nuget包引用的,這里nuget包是:

Redis,緩存

然后,來看下重寫的InitCache方法,這里面有一些ip,port(端口),password(密碼)參數,這里直接寫入在cs文件中沒有從配置文件讀取,大家可以擴展下;這些參數通過RedisClient構造函數傳遞給底層Socket訪問需要的信息,下面簡單展示下RedisClient幾個的構造函數:

public RedisClient();    public RedisClient(RedisEndpoint config);    public RedisClient(string host);    public RedisClient(Uri uri);    public RedisClient(string host, int port);    public RedisClient(string host, int port, string password = null, long db = 0);

至于Get,Set方法最終都是使用RedisClient對象訪問的,個人覺得需要注意的是Set方法里面的過期時間參數,目前還沒有試驗這種情況的效果:

?通過這幾種方法設置過期時間后,快到過期時間的時候如果此時有使用這個緩存key那么過期時間是否會往后自動增加過期時間有效期,這里暫時沒有試驗(這里是由于前面項目中的.net core框架中的memecache緩存都有這種設置,想來redis應該也有吧)

這里,需要重寫下public override void Dispose(bool isfalse)方法,因為調用完RedisClient后需要釋放,我們通過Dispose統一來手動釋放,而不是直接在調用的時候使用using()

。構造出緩存工廠調用方法

接下來,咋們需要定義一個緩存工廠,因為上面剛才定義了一個RedisCache和MemcachedCache明顯這里會有多個不同緩存的方法調用,所用咋們來定義個工廠模式來調用對應的緩存;這里的工廠模式沒有使用直接顯示創建new RedisCache(),new MemcachedCache()對象的方法,而是使用了反射的原理,創建對應的緩存對象;

先來,定義個枚舉,枚舉里面的聲明的名字要和咋們緩存類的名稱相同,代碼如下:

public enum CacheType {  RedisCache,  MemcachedCache }

再來,定義個工廠來CacheRepository(緩存工廠),并且定義方法Current如下代碼:

public static BaseCache Current(CacheType cacheType = CacheType.RedisCache)  {   var nspace = typeof(BaseCache);   var fullName = nspace.FullName;   var nowspace = fullName.Substring(0, fullName.LastIndexOf('.') + 1);   return Assembly.GetExecutingAssembly().CreateInstance(nowspace + cacheType.ToString(), true) as BaseCache;  }

*:通過傳遞枚舉參數,來確定反射CreateInstance()方法需要用到的typeName參數,從而來定義需要訪問的那個緩存對象,這里要注意的是加上了一個命名空間nowspace,因為緩存類可能和工廠類不是同一個命名空間,但是通常會和緩存基類是同命名空間所以在方法最開始的時候截取獲取了緩存類需要的命名空間(這里看自身項目來定吧);

*:Assembly.GetExecutingAssembly()這個是用來獲取當前應用程序集的路徑,這里就避免了咋們使用Assembly.Load()方法還需要傳遞程序集的路徑地址了

好了滿上上面要求后,咋們可以在測試頁面調用代碼如:CacheRepository.Current(CacheType.RedisCache).SetCache<MoFlightSearchResponse>(keyData, value);就如此簡單,咋們使用redis-cli.exe客戶端來看下緩存起來的數據:

Redis,緩存

怎么樣,您們的是什么效果呢,下面給出整體代碼

#region CacheRepository 緩存工廠(默認存儲Session中) /// <summary> /// 緩存枚舉 /// </summary> public enum CacheType {  BaseCache,  RedisCache,  MemcachedCache } /// <summary> /// 緩存工廠(默認存儲Session中) /// </summary> public class CacheRepository {  /// <summary>  /// 緩存工廠(默認存儲Session中, CacheKey = "SeesionKey")  /// </summary>  /// <param name="cacheType">緩存類型</param>  /// <returns></returns>  public static BaseCache Current(CacheType cacheType = CacheType.RedisCache)  {   var nspace = typeof(BaseCache);   var fullName = nspace.FullName;   var nowspace = fullName.Substring(0, fullName.LastIndexOf('.') + 1);   return Assembly.GetExecutingAssembly().CreateInstance(nowspace + cacheType.ToString(), true) as BaseCache;  } } /// <summary> /// 緩存基類(默認存儲Session中) /// </summary> public class BaseCache : IDisposable {  protected string def_ip = string.Empty;  protected int def_port = 0;  protected string def_password = string.Empty;  protected string CacheKey = "SeesionKey";  public BaseCache()  {  }  /// <summary>  /// 獲取自定義SessionId值  /// </summary>  /// <param name="key">key:使用唯一的登陸賬號</param>  /// <returns>hash值的SessionId</returns>  public virtual string GetSessionId(string key)  {   return Md5Extend.GetSidMd5Hash(key);  }  public virtual void InitCache(bool isReadAndWriter = true, string ip = "", int port = 0, string password = "")  {  }  public virtual bool SetCache<T>(string key, T t, int timeOutMinute = 10, bool isSerilize = false) where T : class,new()  {   var isfalse = false;   try   {    key = key ?? CacheKey;    if (t == null) { return isfalse; }    var session_json = JsonConvert.SerializeObject(t);    HttpContext.Current.Session.Timeout = timeOutMinute;    HttpContext.Current.Session.Add(key, session_json);    isfalse = true;   }   catch (Exception ex)   {    throw new Exception(ex.Message);   }   return isfalse;  }  public virtual T GetCache<T>(string key = null, bool isSerilize = false) where T : class,new()  {   var t = default(T);   try   {    key = key ?? CacheKey;    var session = HttpContext.Current.Session[key];    if (session == null) { return t; }    t = JsonConvert.DeserializeObject<T>(session.ToString());   }   catch (Exception ex)   {    throw new Exception(ex.Message);   }   return t;  }  public virtual bool Remove(string key = null)  {   var isfalse = false;   try   {    key = key ?? CacheKey;    HttpContext.Current.Session.Remove(key);    isfalse = true;   }   catch (Exception ex)   {    throw new Exception(ex.Message);   }   return isfalse;  }  /// <summary>  /// 增加緩存時間  /// </summary>  /// <returns></returns>  public virtual bool AddExpire(string key, int nTimeMinute = 10)  {   return true;  }  public virtual bool FlushAll()  {   return false;  }  public virtual bool Any(string key)  {   return false;  }  public virtual bool SetHashCache<T>(string hashId, string key, T t, int nTimeMinute = 10) where T : class,new()  {   return false;  }  public virtual List<string> GetHashKeys(string hashId)  {   return null;  }  public virtual List<string> GetHashValues(string hashId)  {   return null;  }  public virtual T GetHashValue<T>(string hashId, string key) where T : class,new()  {   var t = default(T);   return t;  }  public virtual bool RemoveHashByKey(string hashId, string key)  {   return false;  }  public virtual void Dispose(bool isfalse)  {   if (isfalse)   {   }  }  //手動釋放  public void Dispose()  {   this.Dispose(true);   //不自動釋放   GC.SuppressFinalize(this);  } } /// <summary> /// Redis緩存 /// </summary> public class RedisCache : BaseCache {  public IRedisClient redis = null;  public RedisCache()  {   //這里去讀取默認配置文件數據   def_ip = "127.0.0.1";   def_port = 6379;   def_password = "";  }  #region Redis緩存  public static object _lockCache = new object();  public override void InitCache(bool isReadAndWriter = true, string ip = "", int port = 0, string password = "")  {   if (redis == null)   {    ip = string.IsNullOrEmpty(ip) ? def_ip : ip;    port = port == 0 ? def_port : port;    password = string.IsNullOrEmpty(password) ? def_password : password;    //單個redis服務    //redis = new RedisClient(ip, port, password);    //集群服務 如果密碼,格式如:pwd@ip:port    var readAndWritePorts = new List<string> { "shenniubuxing3@127.0.0.1:6379" };    var onlyReadPorts = new List<string> {     "shenniubuxing3@127.0.0.1:6378",     "shenniubuxing3@127.0.0.1:6377"    };    var redisPool = new PooledRedisClientManager(     readAndWritePorts,     onlyReadPorts,     new RedisClientManagerConfig     {      AutoStart = true,      //最大讀取鏈接      MaxReadPoolSize = 20,      //最大寫入鏈接      MaxWritePoolSize = 10     })    {     //每個鏈接超時時間     ConnectTimeout = 20,     //連接池超時時間     PoolTimeout = 60    };    lock (_lockCache)    {     redis = isReadAndWriter ? redisPool.GetClient() : redisPool.GetReadOnlyClient();    }   }  }  public override bool AddExpire(string key, int nTimeMinute = 10)  {   var isfalse = false;   try   {    if (string.IsNullOrEmpty(key)) { return isfalse; }    InitCache();    //isfalse = redis.ExpireEntryIn(key, TimeSpan.FromMinutes(nTimeMinute));    isfalse = redis.ExpireEntryAt(key, DateTime.Now.AddMinutes(nTimeMinute));   }   catch (Exception ex)   {   }   finally { this.Dispose(); }   return isfalse;  }  public override bool SetCache<T>(string key, T t, int timeOutMinute = 10, bool isSerilize = false)  {   var isfalse = false;   try   {    if (string.IsNullOrEmpty(key)) { return isfalse; }    InitCache();    if (isSerilize)    {     var data = JsonConvert.SerializeObject(t);     var bb = System.Text.Encoding.UTF8.GetBytes(data);     isfalse = redis.Set<byte[]>(key, bb, TimeSpan.FromMinutes(timeOutMinute));    }    else { isfalse = redis.Set<T>(key, t, TimeSpan.FromMinutes(timeOutMinute)); }   }   catch (Exception ex)   {   }   finally { this.Dispose(); }   return isfalse;  }  public override T GetCache<T>(string key, bool isSerilize = false)  {   var t = default(T);   try   {    if (string.IsNullOrEmpty(key)) { return t; }    InitCache(false);    if (isSerilize)    {     var bb = redis.Get<byte[]>(key);     if (bb.Length <= 0) { return t; }     var data = System.Text.Encoding.UTF8.GetString(bb);     t = JsonConvert.DeserializeObject<T>(data);    }    else { t = redis.Get<T>(key); }   }   catch (Exception ex)   {   }   finally { this.Dispose(); }   return t;  }  public override bool Remove(string key)  {   var isfalse = false;   try   {    if (string.IsNullOrEmpty(key)) { return isfalse; }    InitCache();    isfalse = redis.Remove(key);   }   catch (Exception ex)   {   }   finally { this.Dispose(); }   return isfalse;  }  public override bool SetHashCache<T>(string hashId, string key, T t, int nTimeMinute = 10)  {   var isfalse = false;   try   {    if (string.IsNullOrEmpty(hashId) || string.IsNullOrEmpty(key) || t == null) { return isfalse; }    InitCache();    var result = JsonConvert.SerializeObject(t);    if (string.IsNullOrEmpty(result)) { return isfalse; }    isfalse = redis.SetEntryInHash(hashId, key, result);    if (isfalse) { AddExpire(key, nTimeMinute); }   }   catch (Exception ex)   {   }   finally { this.Dispose(); }   return isfalse;  }  public override List<string> GetHashKeys(string hashId)  {   var hashKeys = new List<string>();   try   {    if (string.IsNullOrEmpty(hashId)) { return hashKeys; }    InitCache();    hashKeys = redis.GetHashKeys(hashId);   }   catch (Exception ex)   {   }   finally { this.Dispose(); }   return hashKeys;  }  public override List<string> GetHashValues(string hashId)  {   var hashValues = new List<string>();   try   {    if (string.IsNullOrEmpty(hashId)) { return hashValues; }    InitCache();    hashValues = redis.GetHashValues(hashId);   }   catch (Exception ex)   {   }   finally { this.Dispose(); }   return hashValues;  }  public override T GetHashValue<T>(string hashId, string key)  {   var t = default(T);   try   {    if (string.IsNullOrEmpty(hashId) || string.IsNullOrEmpty(key)) { return t; }    InitCache();    var result = redis.GetValueFromHash(hashId, key);    if (string.IsNullOrEmpty(result)) { return t; }    t = JsonConvert.DeserializeObject<T>(result);   }   catch (Exception ex)   {   }   finally { this.Dispose(); }   return t;  }  public override bool RemoveHashByKey(string hashId, string key)  {   var isfalse = false;   try   {    if (string.IsNullOrEmpty(hashId) || string.IsNullOrEmpty(key)) { return isfalse; }    InitCache();    isfalse = redis.RemoveEntryFromHash(hashId, key);   }   catch (Exception ex)   {   }   finally { this.Dispose(); }   return isfalse;  }  public override void Dispose(bool isfalse)  {   if (isfalse && redis != null)   {    redis.Dispose();    redis = null;   }  }  #endregion } /// <summary> /// Memcached緩存 /// </summary> public class MemcachedCache : BaseCache { } #endregion

 這次分享的Redis緩存從搭建到使用希望給您們有幫助,還請多多支持點贊,謝謝。

以上就是本文的全部內容,希望本文的內容對大家的學習或者工作能帶來一定的幫助,同時也希望多多支持VEVB武林網!


注:相關教程知識閱讀請移步到Redis頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
久久久精品影院| 亚洲春色另类小说| 欧美精品videossex88| 成人精品一区二区三区| 久久夜精品香蕉| 51精品在线观看| 色妞在线综合亚洲欧美| 最近2019中文字幕第三页视频| 亚洲精品乱码久久久久久按摩观| 日韩电影免费观看在线观看| 久久久亚洲精选| 欧美黑人极品猛少妇色xxxxx| 欧美日韩国产综合视频在线观看中文| 丁香五六月婷婷久久激情| 秋霞午夜一区二区| 91久久久亚洲精品| 九九视频直播综合网| 最新国产精品拍自在线播放| 日韩免费av在线| 91热福利电影| 久久久久久久一| 2019中文字幕在线| 国产亚洲日本欧美韩国| 亚洲色图欧美制服丝袜另类第一页| 国产在线精品成人一区二区三区| 国产精品一区二区久久精品| 国产美女91呻吟求| 久久久亚洲福利精品午夜| 一区二区欧美亚洲| 亚洲国产精品免费| 亚洲a∨日韩av高清在线观看| 欧美中文字幕在线观看| 91久久国产综合久久91精品网站| 国产精品日韩在线观看| 91免费综合在线| 亚洲在线观看视频| 亚洲高清在线观看| 亚洲国产欧美一区| 久久国产精品久久久| 国产91精品久久久久久久| 中文精品99久久国产香蕉| 成人激情电影一区二区| 亚洲精品日韩av| 国产欧美va欧美va香蕉在| 2019中文字幕免费视频| 中文字幕一区二区三区电影| 国产亚洲精品综合一区91| 亚洲国产福利在线| 色综合久久中文字幕综合网小说| 2019中文字幕在线| 疯狂做受xxxx高潮欧美日本| 亚洲精品丝袜日韩| 欧美成人精品h版在线观看| 国产精品自产拍在线观看中文| 亚洲男人的天堂在线播放| 亚洲三级黄色在线观看| 18一19gay欧美视频网站| 亚洲伊人久久大香线蕉av| 亚洲美女喷白浆| 精品国产乱码久久久久酒店| 91精品国产综合久久香蕉的用户体验| 精品少妇v888av| 91精品免费视频| 日本韩国欧美精品大片卡二| 欧美美女操人视频| 欧美一区三区三区高中清蜜桃| 亚洲视频在线观看视频| 伊人亚洲福利一区二区三区| 欧美极品欧美精品欧美视频| 欧美亚洲另类激情另类| 久久久久九九九九| 91国产在线精品| 亚洲理论在线a中文字幕| 上原亚衣av一区二区三区| 最近2019中文字幕mv免费看| 久久久精品在线观看| 久久激情视频久久| 性视频1819p久久| 午夜精品久久久久久久99热| 亚洲国产精品va在看黑人| 国产精品igao视频| 一本色道久久88亚洲综合88| 国产精品日韩在线观看| 91国产美女视频| 亚洲欧洲日本专区| 成人情趣片在线观看免费| 欧美精品一区在线播放| 欧美日韩另类在线| 成人中文字幕在线观看| 日韩精品在线电影| 最近免费中文字幕视频2019| 国产欧美精品久久久| www国产亚洲精品久久网站| 国产日韩在线观看av| 亚洲精品美女久久久久| 欧美在线观看www| 久久久久久亚洲精品不卡| 国产偷亚洲偷欧美偷精品| www.欧美精品一二三区| 亚洲欧洲激情在线| 欧美成人免费小视频| 久久精品国产亚洲7777| 国产精品精品视频一区二区三区| 亚洲精品美女久久| 亚洲尤物视频网| 性欧美视频videos6一9| 91高潮在线观看| 欧美亚洲国产视频小说| 亚洲国产精品系列| 全亚洲最色的网站在线观看| 国产精品电影一区| 欧美亚洲国产日韩2020| 国产99在线|中文| 久热国产精品视频| 在线观看成人黄色| 2018中文字幕一区二区三区| 久久久久久久久国产| 亚洲欧美国产制服动漫| y97精品国产97久久久久久| 亚洲成在人线av| 亚洲天堂av电影| 北条麻妃一区二区在线观看| 狠狠干狠狠久久| 亚洲国产精品人久久电影| 亚洲护士老师的毛茸茸最新章节| 日韩精品黄色网| 日韩美女福利视频| 狠狠色噜噜狠狠狠狠97| 中文字幕一区日韩电影| 国产精品爱啪在线线免费观看| 91精品国产自产在线老师啪| 国产精品久久久久免费a∨| 亚洲激情在线观看视频免费| 国产在线观看91精品一区| 欧美成人精品在线播放| 久久成人免费视频| 久久精品国产精品亚洲| 国产日韩中文在线| 久久久国产精彩视频美女艺术照福利| 亚洲毛茸茸少妇高潮呻吟| 国产香蕉97碰碰久久人人| 亚洲欧美激情精品一区二区| 欧美大学生性色视频| 国产欧美一区二区三区久久人妖| 中国china体内裑精亚洲片| 2019av中文字幕| 欧美日韩中文字幕在线视频| 国产成人av网址| 欧美自拍大量在线观看| 国产日韩在线看片| 色综合老司机第九色激情| 欧美激情免费观看| 久久免费国产精品1| 欧美激情视频播放| 国产精品美女免费| 久久香蕉国产线看观看av| 亚洲国产精品va| 欧美激情亚洲视频| 精品国偷自产在线视频99| 欧美天天综合色影久久精品| 亚洲黄在线观看| 热re99久久精品国产66热| 另类专区欧美制服同性| 久久精品国产久精国产思思|