午夜视频免费看_日韩三级电影网站_国产精品久久一级_亚洲一级在线播放_人妻体内射精一区二区三区_91夜夜揉人人捏人人添红杏_91福利在线导航_国产又粗又猛又黄又爽无遮挡_欧美日韩一区在线播放_中文字幕一区二区三区四区不卡 _日日夜夜精品视频免费观看_欧美韩日一区二区三区

主頁(yè) > 知識(shí)庫(kù) > redis 數(shù)據(jù)刪除策略和逐出算法的問(wèn)題小結(jié)

redis 數(shù)據(jù)刪除策略和逐出算法的問(wèn)題小結(jié)

熱門(mén)標(biāo)簽:400電話(huà)辦理的口碑 一個(gè)地圖標(biāo)注多少錢(qián) 四川穩(wěn)定外呼系統(tǒng)軟件 地圖標(biāo)注工廠入駐 廊坊外呼系統(tǒng)在哪買(mǎi) b2b外呼系統(tǒng) 南京手機(jī)外呼系統(tǒng)廠家 臺(tái)灣電銷(xiāo) 高碑店市地圖標(biāo)注app

數(shù)據(jù)存儲(chǔ)和有效期

redis 工作流程中,過(guò)期的數(shù)據(jù)并不需要馬上就要執(zhí)行刪除操作。因?yàn)檫@些刪不刪除只是一種狀態(tài)表示,可以異步的去處理,在不忙的時(shí)候去把這些不緊急的刪除操作做了,從而保證 redis 的高效

數(shù)據(jù)的存儲(chǔ)

在redis中數(shù)據(jù)的存儲(chǔ)不僅僅需要保存數(shù)據(jù)本身還要保存數(shù)據(jù)的生命周期,也就是過(guò)期時(shí)間。在redis 中 數(shù)據(jù)的存儲(chǔ)結(jié)構(gòu)如下圖:

獲取有效期

Redis是一種內(nèi)存級(jí)數(shù)據(jù)庫(kù),所有數(shù)據(jù)均存放在內(nèi)存中,內(nèi)存中的數(shù)據(jù)可以通過(guò)TTL指令獲取其狀態(tài)

刪除策略

在內(nèi)存占用與CPU占用之間尋找一種平衡,顧此失彼都會(huì)造成整體redis性能的下降,甚至引發(fā)服務(wù)器宕機(jī)或內(nèi)存泄漏。

定時(shí)刪除

創(chuàng)建一個(gè)定時(shí)器,當(dāng)key設(shè)置過(guò)期時(shí)間,且過(guò)期時(shí)間到達(dá)時(shí),由定時(shí)器任務(wù)立即執(zhí)行對(duì)鍵的刪除操作

優(yōu)點(diǎn)

節(jié)約內(nèi)存,到時(shí)就刪除,快速釋放掉不必要的內(nèi)存占用

缺點(diǎn)

CPU壓力很大,無(wú)論CPU此時(shí)負(fù)載多高,均占用CPU,會(huì)影響redis服務(wù)器響應(yīng)時(shí)間和指令吞吐量

總結(jié)

用處理器性能換取存儲(chǔ)空間

惰性刪除

數(shù)據(jù)到達(dá)過(guò)期時(shí)間,不做處理。等下次訪(fǎng)問(wèn)該數(shù)據(jù),如果未過(guò)期,返回?cái)?shù)據(jù)。發(fā)現(xiàn)已經(jīng)過(guò)期,刪除,返回不存在。這樣每次讀寫(xiě)數(shù)據(jù)都需要檢測(cè)數(shù)據(jù)是否已經(jīng)到達(dá)過(guò)期時(shí)間。也就是惰性刪除總是在數(shù)據(jù)的讀寫(xiě)時(shí)發(fā)生的。

expireIfNeeded函數(shù)

對(duì)所有的讀寫(xiě)命令進(jìn)行檢查,檢查操作的對(duì)象是否過(guò)期。過(guò)期就刪除返回過(guò)期,不過(guò)期就什么也不做~。

執(zhí)行數(shù)據(jù)寫(xiě)入過(guò)程中,首先通過(guò)expireIfNeeded函數(shù)對(duì)寫(xiě)入的key進(jìn)行過(guò)期判斷。

/*
 * 為執(zhí)行寫(xiě)入操作而取出鍵 key 在數(shù)據(jù)庫(kù) db 中的值。
 *
 * 和 lookupKeyRead 不同,這個(gè)函數(shù)不會(huì)更新服務(wù)器的命中/不命中信息。
 *
 * 找到時(shí)返回值對(duì)象,沒(méi)找到返回 NULL 。
 */
robj *lookupKeyWrite(redisDb *db, robj *key) {

 // 刪除過(guò)期鍵
 expireIfNeeded(db,key);

 // 查找并返回 key 的值對(duì)象
 return lookupKey(db,key);
}

執(zhí)行數(shù)據(jù)讀取過(guò)程中,首先通過(guò)expireIfNeeded函數(shù)對(duì)寫(xiě)入的key進(jìn)行過(guò)期判斷。

/*
 * 為執(zhí)行讀取操作而取出鍵 key 在數(shù)據(jù)庫(kù) db 中的值。
 *
 * 并根據(jù)是否成功找到值,更新服務(wù)器的命中/不命中信息。
 *
 * 找到時(shí)返回值對(duì)象,沒(méi)找到返回 NULL 。
 */
robj *lookupKeyRead(redisDb *db, robj *key) {
 robj *val;

 // 檢查 key 釋放已經(jīng)過(guò)期
 expireIfNeeded(db,key);

 // 從數(shù)據(jù)庫(kù)中取出鍵的值
 val = lookupKey(db,key);

 // 更新命中/不命中信息
 if (val == NULL)
 server.stat_keyspace_misses++;
 else
 server.stat_keyspace_hits++;

 // 返回值
 return val;
}

執(zhí)行過(guò)期動(dòng)作expireIfNeeded其實(shí)內(nèi)部做了三件事情,分別是:

  • 查看key判斷是否過(guò)期
  • 向slave節(jié)點(diǎn)傳播執(zhí)行過(guò)期key的動(dòng)作并發(fā)送事件通知
  • 刪除過(guò)期key
/*
 * 檢查 key 是否已經(jīng)過(guò)期,如果是的話(huà),將它從數(shù)據(jù)庫(kù)中刪除。
 *
 * 返回 0 表示鍵沒(méi)有過(guò)期時(shí)間,或者鍵未過(guò)期。
 *
 * 返回 1 表示鍵已經(jīng)因?yàn)檫^(guò)期而被刪除了。
 */
int expireIfNeeded(redisDb *db, robj *key) {

 // 取出鍵的過(guò)期時(shí)間
 mstime_t when = getExpire(db,key);
 mstime_t now;

 // 沒(méi)有過(guò)期時(shí)間
 if (when  0) return 0; /* No expire for this key */

 /* Don't expire anything while loading. It will be done later. */
 // 如果服務(wù)器正在進(jìn)行載入,那么不進(jìn)行任何過(guò)期檢查
 if (server.loading) return 0;

 // 當(dāng)服務(wù)器運(yùn)行在 replication 模式時(shí)
 // 附屬節(jié)點(diǎn)并不主動(dòng)刪除 key
 // 它只返回一個(gè)邏輯上正確的返回值
 // 真正的刪除操作要等待主節(jié)點(diǎn)發(fā)來(lái)刪除命令時(shí)才執(zhí)行
 // 從而保證數(shù)據(jù)的同步
 if (server.masterhost != NULL) return now > when;

 // 運(yùn)行到這里,表示鍵帶有過(guò)期時(shí)間,并且服務(wù)器為主節(jié)點(diǎn)

 /* Return when this key has not expired */
 // 如果未過(guò)期,返回 0
 if (now = when) return 0;

 /* Delete the key */
 server.stat_expiredkeys++;

 // 向 AOF 文件和附屬節(jié)點(diǎn)傳播過(guò)期信息
 propagateExpire(db,key);

 // 發(fā)送事件通知
 notifyKeyspaceEvent(REDIS_NOTIFY_EXPIRED,
 "expired",key,db->id);

 // 將過(guò)期鍵從數(shù)據(jù)庫(kù)中刪除
 return dbDelete(db,key);
}

判斷key是否過(guò)期的數(shù)據(jù)結(jié)構(gòu)是db->expires,也就是通過(guò)expires的數(shù)據(jù)結(jié)構(gòu)判斷數(shù)據(jù)是否過(guò)期。
內(nèi)部獲取過(guò)期時(shí)間并返回。

/*
 * 返回字典中包含鍵 key 的節(jié)點(diǎn)
 *
 * 找到返回節(jié)點(diǎn),找不到返回 NULL
 *
 * T = O(1)
 */
dictEntry *dictFind(dict *d, const void *key)
{
 dictEntry *he;
 unsigned int h, idx, table;

 // 字典(的哈希表)為空
 if (d->ht[0].size == 0) return NULL; /* We don't have a table at all */

 // 如果條件允許的話(huà),進(jìn)行單步 rehash
 if (dictIsRehashing(d)) _dictRehashStep(d);

 // 計(jì)算鍵的哈希值
 h = dictHashKey(d, key);
 // 在字典的哈希表中查找這個(gè)鍵
 // T = O(1)
 for (table = 0; table = 1; table++) {

 // 計(jì)算索引值
 idx = h  d->ht[table].sizemask;

 // 遍歷給定索引上的鏈表的所有節(jié)點(diǎn),查找 key
 he = d->ht[table].table[idx];
 // T = O(1)
 while(he) {

 if (dictCompareKeys(d, key, he->key))
 return he;

 he = he->next;
 }

 // 如果程序遍歷完 0 號(hào)哈希表,仍然沒(méi)找到指定的鍵的節(jié)點(diǎn)
 // 那么程序會(huì)檢查字典是否在進(jìn)行 rehash ,
 // 然后才決定是直接返回 NULL ,還是繼續(xù)查找 1 號(hào)哈希表
 if (!dictIsRehashing(d)) return NULL;
 }

 // 進(jìn)行到這里時(shí),說(shuō)明兩個(gè)哈希表都沒(méi)找到
 return NULL;
}

優(yōu)點(diǎn)

節(jié)約CPU性能,發(fā)現(xiàn)必須刪除的時(shí)候才刪除。

缺點(diǎn)

內(nèi)存壓力很大,出現(xiàn)長(zhǎng)期占用內(nèi)存的數(shù)據(jù)。

總結(jié)

用存儲(chǔ)空間換取處理器性能

定期刪除

周期性輪詢(xún)r(jià)edis庫(kù)中時(shí)效性數(shù)據(jù),采用隨機(jī)抽取的策略,利用過(guò)期數(shù)據(jù)占比的方式刪除頻度。

優(yōu)點(diǎn)

CPU性能占用設(shè)置有峰值,檢測(cè)頻度可自定義設(shè)置

內(nèi)存壓力不是很大,長(zhǎng)期占用內(nèi)存的冷數(shù)據(jù)會(huì)被持續(xù)清理

缺點(diǎn)

需要周期性抽查存儲(chǔ)空間

定期刪除詳解

redis的定期刪除是通過(guò)定時(shí)任務(wù)實(shí)現(xiàn)的,也就是定時(shí)任務(wù)會(huì)循環(huán)調(diào)用serverCron方法。然后定時(shí)檢查過(guò)期數(shù)據(jù)的方法是databasesCron。定期刪除的一大特點(diǎn)就是考慮了定時(shí)刪除過(guò)期數(shù)據(jù)會(huì)占用cpu時(shí)間,所以每次執(zhí)行databasesCron的時(shí)候會(huì)限制cpu的占用不超過(guò)25%。真正執(zhí)行刪除的是 activeExpireCycle方法。

時(shí)間事件

對(duì)于持續(xù)運(yùn)行的服務(wù)器來(lái)說(shuō), 服務(wù)器需要定期對(duì)自身的資源和狀態(tài)進(jìn)行必要的檢查和整理, 從而讓服務(wù)器維持在一個(gè)健康穩(wěn)定的狀態(tài), 這類(lèi)操作被統(tǒng)稱(chēng)為常規(guī)操作(cron job)

在 Redis 中, 常規(guī)操作由 redis.c/serverCron() 實(shí)現(xiàn), 它主要執(zhí)行以下操作

1 更新服務(wù)器的各類(lèi)統(tǒng)計(jì)信息,比如時(shí)間、內(nèi)存占用、數(shù)據(jù)庫(kù)占用情況等。

2 清理數(shù)據(jù)庫(kù)中的過(guò)期鍵值對(duì)。

3 對(duì)不合理的數(shù)據(jù)庫(kù)進(jìn)行大小調(diào)整。

4 關(guān)閉和清理連接失效的客戶(hù)端。

5 嘗試進(jìn)行 AOF 或 RDB 持久化操作。

6 如果服務(wù)器是主節(jié)點(diǎn)的話(huà),對(duì)附屬節(jié)點(diǎn)進(jìn)行定期同步。

7 如果處于集群模式的話(huà),對(duì)集群進(jìn)行定期同步和連接測(cè)試。

因?yàn)?serverCron() 需要在 Redis 服務(wù)器運(yùn)行期間一直定期運(yùn)行, 所以它是一個(gè)循環(huán)時(shí)間事件: serverCron() 會(huì)一直定期執(zhí)行,直到服務(wù)器關(guān)閉為止。

在 Redis 2.6 版本中, 程序規(guī)定 serverCron() 每秒運(yùn)行 10 次, 平均每 100 毫秒運(yùn)行一次。 從 Redis 2.8 開(kāi)始, 用戶(hù)可以通過(guò)修改 hz選項(xiàng)來(lái)調(diào)整 serverCron() 的每秒執(zhí)行次數(shù), 具體信息請(qǐng)參考 redis.conf 文件中關(guān)于 hz 選項(xiàng)的說(shuō)明

查看hz

way1 : config get hz # "hz" "10"
way2 : info server # server.hz 10

serverCron()

serverCron()會(huì)定期的執(zhí)行,在serverCron()執(zhí)行中會(huì)調(diào)用databasesCron() 方法(serverCron()還做了其他很多事情,但是現(xiàn)在不討論,只談刪除策略)

int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) {
 // 略去多無(wú)關(guān)代碼

 /* We need to do a few operations on clients asynchronously. */
 // 檢查客戶(hù)端,關(guān)閉超時(shí)客戶(hù)端,并釋放客戶(hù)端多余的緩沖區(qū)
 clientsCron();

 /* Handle background operations on Redis databases. */
 // 對(duì)數(shù)據(jù)庫(kù)執(zhí)行各種操作
 databasesCron(); /* !我們關(guān)注的方法! */

databasesCron()

databasesCron() 中 調(diào)用了 activeExpireCycle()方法,來(lái)對(duì)過(guò)期的數(shù)據(jù)進(jìn)行處理。(在這里還會(huì)做一些其他操作~ 調(diào)整數(shù)據(jù)庫(kù)大小,主動(dòng)和漸進(jìn)式rehash)

// 對(duì)數(shù)據(jù)庫(kù)執(zhí)行刪除過(guò)期鍵,調(diào)整大小,以及主動(dòng)和漸進(jìn)式 rehash
void databasesCron(void) {

 // 判斷是否是主服務(wù)器 如果是 執(zhí)行主動(dòng)過(guò)期鍵清除
 if (server.active_expire_enabled  server.masterhost == NULL)
 // 清除模式為 CYCLE_SLOW ,這個(gè)模式會(huì)盡量多清除過(guò)期鍵
 activeExpireCycle(ACTIVE_EXPIRE_CYCLE_SLOW);

 // 在沒(méi)有 BGSAVE 或者 BGREWRITEAOF 執(zhí)行時(shí),對(duì)哈希表進(jìn)行 rehash
 if (server.rdb_child_pid == -1  server.aof_child_pid == -1) {
 static unsigned int resize_db = 0;
 static unsigned int rehash_db = 0;
 unsigned int dbs_per_call = REDIS_DBCRON_DBS_PER_CALL;
 unsigned int j;

 /* Don't test more DBs than we have. */
 // 設(shè)定要測(cè)試的數(shù)據(jù)庫(kù)數(shù)量
 if (dbs_per_call > server.dbnum) dbs_per_call = server.dbnum;

 /* Resize */
 // 調(diào)整字典的大小
 for (j = 0; j  dbs_per_call; j++) {
 tryResizeHashTables(resize_db % server.dbnum);
 resize_db++;
 }

 /* Rehash */
 // 對(duì)字典進(jìn)行漸進(jìn)式 rehash
 if (server.activerehashing) {
 for (j = 0; j  dbs_per_call; j++) {
 int work_done = incrementallyRehash(rehash_db % server.dbnum);
 rehash_db++;
 if (work_done) {
  /* If the function did some work, stop here, we'll do
  * more at the next cron loop. */
  break;
 }
 }
 }
 }
}

activeExpireCycle()

大致流程如下

1 遍歷指定個(gè)數(shù)的db(默認(rèn)的 16 )進(jìn)行刪除操作

2 針對(duì)每個(gè)db隨機(jī)獲取過(guò)期數(shù)據(jù)每次遍歷不超過(guò)指定數(shù)量(如20),發(fā)現(xiàn)過(guò)期數(shù)據(jù)并進(jìn)行刪除。

3 如果有多于25%的keys過(guò)期,重復(fù)步驟 2

除了主動(dòng)淘汰的頻率外,Redis對(duì)每次淘汰任務(wù)執(zhí)行的最大時(shí)長(zhǎng)也有一個(gè)限定,這樣保證了每次主動(dòng)淘汰不會(huì)過(guò)多阻塞應(yīng)用請(qǐng)求,以下是這個(gè)限定計(jì)算公式:

#define ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC 25 /* CPU max % for keys collection */ ``... ``timelimit = 1000000*ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC/server.hz/100;

也就是每次執(zhí)行時(shí)間的25%用于過(guò)期數(shù)據(jù)刪除。

void activeExpireCycle(int type) {
 // 靜態(tài)變量,用來(lái)累積函數(shù)連續(xù)執(zhí)行時(shí)的數(shù)據(jù)
 static unsigned int current_db = 0; /* Last DB tested. */
 static int timelimit_exit = 0; /* Time limit hit in previous call? */
 static long long last_fast_cycle = 0; /* When last fast cycle ran. */

 unsigned int j, iteration = 0;
 // 默認(rèn)每次處理的數(shù)據(jù)庫(kù)數(shù)量
 unsigned int dbs_per_call = REDIS_DBCRON_DBS_PER_CALL;
 // 函數(shù)開(kāi)始的時(shí)間
 long long start = ustime(), timelimit;

 // 快速模式
 if (type == ACTIVE_EXPIRE_CYCLE_FAST) {
 // 如果上次函數(shù)沒(méi)有觸發(fā) timelimit_exit ,那么不執(zhí)行處理
 if (!timelimit_exit) return;
 // 如果距離上次執(zhí)行未夠一定時(shí)間,那么不執(zhí)行處理
 if (start  last_fast_cycle + ACTIVE_EXPIRE_CYCLE_FAST_DURATION*2) return;
 // 運(yùn)行到這里,說(shuō)明執(zhí)行快速處理,記錄當(dāng)前時(shí)間
 last_fast_cycle = start;
 }

 /* 
 * 一般情況下,函數(shù)只處理 REDIS_DBCRON_DBS_PER_CALL 個(gè)數(shù)據(jù)庫(kù),
 * 除非:
 *
 * 1) 當(dāng)前數(shù)據(jù)庫(kù)的數(shù)量小于 REDIS_DBCRON_DBS_PER_CALL
 * 2) 如果上次處理遇到了時(shí)間上限,那么這次需要對(duì)所有數(shù)據(jù)庫(kù)進(jìn)行掃描,
 * 這可以避免過(guò)多的過(guò)期鍵占用空間
 */
 if (dbs_per_call > server.dbnum || timelimit_exit)
 dbs_per_call = server.dbnum;

 // 函數(shù)處理的微秒時(shí)間上限
 // ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC 默認(rèn)為 25 ,也即是 25 % 的 CPU 時(shí)間
 timelimit = 1000000*ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC/server.hz/100;
 timelimit_exit = 0;
 if (timelimit = 0) timelimit = 1;

 // 如果是運(yùn)行在快速模式之下
 // 那么最多只能運(yùn)行 FAST_DURATION 微秒 
 // 默認(rèn)值為 1000 (微秒)
 if (type == ACTIVE_EXPIRE_CYCLE_FAST)
 timelimit = ACTIVE_EXPIRE_CYCLE_FAST_DURATION; /* in microseconds. */

 // 遍歷數(shù)據(jù)庫(kù)
 for (j = 0; j  dbs_per_call; j++) {
 int expired;
 // 指向要處理的數(shù)據(jù)庫(kù)
 redisDb *db = server.db+(current_db % server.dbnum);

 // 為 DB 計(jì)數(shù)器加一,如果進(jìn)入 do 循環(huán)之后因?yàn)槌瑫r(shí)而跳出
 // 那么下次會(huì)直接從下個(gè) DB 開(kāi)始處理
 current_db++;

 do {
 unsigned long num, slots;
 long long now, ttl_sum;
 int ttl_samples;

 /* If there is nothing to expire try next DB ASAP. */
 // 獲取數(shù)據(jù)庫(kù)中帶過(guò)期時(shí)間的鍵的數(shù)量
 // 如果該數(shù)量為 0 ,直接跳過(guò)這個(gè)數(shù)據(jù)庫(kù)
 if ((num = dictSize(db->expires)) == 0) {
 db->avg_ttl = 0;
 break;
 }
 // 獲取數(shù)據(jù)庫(kù)中鍵值對(duì)的數(shù)量
 slots = dictSlots(db->expires);
 // 當(dāng)前時(shí)間
 now = mstime();

 // 這個(gè)數(shù)據(jù)庫(kù)的使用率低于 1% ,掃描起來(lái)太費(fèi)力了(大部分都會(huì) MISS)
 // 跳過(guò),等待字典收縮程序運(yùn)行
 if (num  slots > DICT_HT_INITIAL_SIZE 
 (num*100/slots  1)) break;

 /* 
 * 樣本計(jì)數(shù)器
 */
 // 已處理過(guò)期鍵計(jì)數(shù)器
 expired = 0;
 // 鍵的總 TTL 計(jì)數(shù)器
 ttl_sum = 0;
 // 總共處理的鍵計(jì)數(shù)器
 ttl_samples = 0;

 // 每次最多只能檢查 LOOKUPS_PER_LOOP 個(gè)鍵
 if (num > ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP)
 num = ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP;

 // 開(kāi)始遍歷數(shù)據(jù)庫(kù)
 while (num--) {
 dictEntry *de;
 long long ttl;

 // 從 expires 中隨機(jī)取出一個(gè)帶過(guò)期時(shí)間的鍵
 if ((de = dictGetRandomKey(db->expires)) == NULL) break;
 // 計(jì)算 TTL
 ttl = dictGetSignedIntegerVal(de)-now;
 // 如果鍵已經(jīng)過(guò)期,那么刪除它,并將 expired 計(jì)數(shù)器增一
 if (activeExpireCycleTryExpire(db,de,now)) expired++;
 if (ttl  0) ttl = 0;
 // 累積鍵的 TTL
 ttl_sum += ttl;
 // 累積處理鍵的個(gè)數(shù)
 ttl_samples++;
 }

 /* Update the average TTL stats for this database. */
 // 為這個(gè)數(shù)據(jù)庫(kù)更新平均 TTL 統(tǒng)計(jì)數(shù)據(jù)
 if (ttl_samples) {
 // 計(jì)算當(dāng)前平均值
 long long avg_ttl = ttl_sum/ttl_samples;
 
 // 如果這是第一次設(shè)置數(shù)據(jù)庫(kù)平均 TTL ,那么進(jìn)行初始化
 if (db->avg_ttl == 0) db->avg_ttl = avg_ttl;
 /* Smooth the value averaging with the previous one. */
 // 取數(shù)據(jù)庫(kù)的上次平均 TTL 和今次平均 TTL 的平均值
 db->avg_ttl = (db->avg_ttl+avg_ttl)/2;
 }

 // 我們不能用太長(zhǎng)時(shí)間處理過(guò)期鍵,
 // 所以這個(gè)函數(shù)執(zhí)行一定時(shí)間之后就要返回

 // 更新遍歷次數(shù)
 iteration++;

 // 每遍歷 16 次執(zhí)行一次
 if ((iteration  0xf) == 0  /* check once every 16 iterations. */
 (ustime()-start) > timelimit)
 {
 // 如果遍歷次數(shù)正好是 16 的倍數(shù)
 // 并且遍歷的時(shí)間超過(guò)了 timelimit
 // 那么斷開(kāi) timelimit_exit
 timelimit_exit = 1;
 }

 // 已經(jīng)超時(shí)了,返回
 if (timelimit_exit) return;

 // 如果已刪除的過(guò)期鍵占當(dāng)前總數(shù)據(jù)庫(kù)帶過(guò)期時(shí)間的鍵數(shù)量的 25 %
 // 那么不再遍歷
 } while (expired > ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP/4);
 }
}

hz調(diào)大將會(huì)提高Redis主動(dòng)淘汰的頻率,如果你的Redis存儲(chǔ)中包含很多冷數(shù)據(jù)占用內(nèi)存過(guò)大的話(huà),可以考慮將這個(gè)值調(diào)大,但Redis作者建議這個(gè)值不要超過(guò)100。我們實(shí)際線(xiàn)上將這個(gè)值調(diào)大到100,觀察到CPU會(huì)增加2%左右,但對(duì)冷數(shù)據(jù)的內(nèi)存釋放速度確實(shí)有明顯的提高(通過(guò)觀察keyspace個(gè)數(shù)和used_memory大小)。

可以看出timelimit和server.hz是一個(gè)倒數(shù)的關(guān)系,也就是說(shuō)hz配置越大,timelimit就越小。換句話(huà)說(shuō)是每秒鐘期望的主動(dòng)淘汰頻率越高,則每次淘汰最長(zhǎng)占用時(shí)間就越短。這里每秒鐘的最長(zhǎng)淘汰占用時(shí)間是固定的250ms(1000000*ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC/100),而淘汰頻率和每次淘汰的最長(zhǎng)時(shí)間是通過(guò)hz參數(shù)控制的。

因此當(dāng)redis中的過(guò)期key比率沒(méi)有超過(guò)25%之前,提高h(yuǎn)z可以明顯提高掃描key的最小個(gè)數(shù)。假設(shè)hz為10,則一秒內(nèi)最少掃描200個(gè)key(一秒調(diào)用10次*每次最少隨機(jī)取出20個(gè)key),如果hz改為100,則一秒內(nèi)最少掃描2000個(gè)key;另一方面,如果過(guò)期key比率超過(guò)25%,則掃描key的個(gè)數(shù)無(wú)上限,但是cpu時(shí)間每秒鐘最多占用250ms。

當(dāng)REDIS運(yùn)行在主從模式時(shí),只有主結(jié)點(diǎn)才會(huì)執(zhí)行上述這兩種過(guò)期刪除策略,然后把刪除操作”del key”同步到從結(jié)點(diǎn)。

if (server.active_expire_enabled  server.masterhost == NULL) // 判斷是否是主節(jié)點(diǎn) 從節(jié)點(diǎn)不需要執(zhí)行activeExpireCycle()函數(shù)。
 // 清除模式為 CYCLE_SLOW ,這個(gè)模式會(huì)盡量多清除過(guò)期鍵
 activeExpireCycle(ACTIVE_EXPIRE_CYCLE_SLOW);

隨機(jī)個(gè)數(shù)

redis.config.ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP 決定每次循環(huán)從數(shù)據(jù)庫(kù) expire中隨機(jī)挑選值的個(gè)數(shù)

逐出算法

如果不限制 reids 對(duì)內(nèi)存使用的限制,它將會(huì)使用全部的內(nèi)存。可以通過(guò) config.memory 來(lái)指定redis 對(duì)內(nèi)存的使用量 。

下面是redis 配置文件中的說(shuō)明

543 # Set a memory usage limit to the specified amount of bytes.
 544 # When the memory limit is reached Redis will try to remove keys
 545 # according to the eviction policy selected (see maxmemory-policy).
 546 #
 547 # If Redis can't remove keys according to the policy, or if the policy is
 548 # set to 'noeviction', Redis will start to reply with errors to commands
 549 # that would use more memory, like SET, LPUSH, and so on, and will continue
 550 # to reply to read-only commands like GET.
 551 #
 552 # This option is usually useful when using Redis as an LRU or LFU cache, or to
 553 # set a hard memory limit for an instance (using the 'noeviction' policy).
 554 #
 555 # WARNING: If you have replicas attached to an instance with maxmemory on,
 556 # the size of the output buffers needed to feed the replicas are subtracted
 557 # from the used memory count, so that network problems / resyncs will
 558 # not trigger a loop where keys are evicted, and in turn the output
 559 # buffer of replicas is full with DELs of keys evicted triggering the deletion
 560 # of more keys, and so forth until the database is completely emptied.
 561 #
 562 # In short... if you have replicas attached it is suggested that you set a lower
 563 # limit for maxmemory so that there is some free RAM on the system for replica
 564 # output buffers (but this is not needed if the policy is 'noeviction').
 
將內(nèi)存使用限制設(shè)置為指定的字節(jié)。當(dāng)已達(dá)到內(nèi)存限制Redis將根據(jù)所選的逐出策略(請(qǐng)參閱maxmemory策略)嘗試刪除數(shù)據(jù)。

如果Redis無(wú)法根據(jù)逐出策略移除密鑰,或者策略設(shè)置為“noeviction”,Redis將開(kāi)始對(duì)使用更多內(nèi)存的命令(如set、LPUSH等)進(jìn)行錯(cuò)誤回復(fù),并將繼續(xù)回復(fù)只讀命令,如GET。

當(dāng)將Redis用作LRU或LFU緩存或設(shè)置實(shí)例的硬內(nèi)存限制(使用“noeviction”策略)時(shí),此選項(xiàng)通常很有用。

警告:如果將副本附加到啟用maxmemory的實(shí)例,則將從已用內(nèi)存計(jì)數(shù)中減去饋送副本所需的輸出緩沖區(qū)的大小,這樣,網(wǎng)絡(luò)問(wèn)題/重新同步將不會(huì)觸發(fā)收回密鑰的循環(huán),而副本的輸出緩沖區(qū)將充滿(mǎn)收回的密鑰增量,從而觸發(fā)刪除更多鍵,依此類(lèi)推,直到數(shù)據(jù)庫(kù)完全清空。

簡(jiǎn)而言之。。。如果附加了副本,建議您設(shè)置maxmemory的下限,以便系統(tǒng)上有一些空閑RAM用于副本輸出緩沖區(qū)(但如果策略為“noeviction”,則不需要此限制)。

驅(qū)逐策略的配置

Maxmemery-policy volatile-lru

當(dāng)前已用內(nèi)存超過(guò) maxmemory 限定時(shí),觸發(fā)主動(dòng)清理策略

易失數(shù)據(jù)清理

volatile-lru:只對(duì)設(shè)置了過(guò)期時(shí)間的key進(jìn)行LRU(默認(rèn)值)

volatile-random:隨機(jī)刪除即將過(guò)期key

volatile-ttl : 刪除即將過(guò)期的

volatile-lfu:挑選最近使用次數(shù)最少的數(shù)據(jù)淘汰

全部數(shù)據(jù)清理

allkeys-lru : 刪除lru算法的key

allkeys-lfu:挑選最近使用次數(shù)最少的數(shù)據(jù)淘汰

allkeys-random:隨機(jī)刪除

禁止驅(qū)逐

(Redis 4.0 默認(rèn)策略)

noeviction : 永不過(guò)期,返回錯(cuò)誤當(dāng)mem_used內(nèi)存已經(jīng)超過(guò)maxmemory的設(shè)定,對(duì)于所有的讀寫(xiě)請(qǐng)求都會(huì)觸發(fā)redis.c/freeMemoryIfNeeded(void)函數(shù)以清理超出的內(nèi)存。注意這個(gè)清理過(guò)程是阻塞的,直到清理出足夠的內(nèi)存空間。所以如果在達(dá)到maxmemory并且調(diào)用方還在不斷寫(xiě)入的情況下,可能會(huì)反復(fù)觸發(fā)主動(dòng)清理策略,導(dǎo)致請(qǐng)求會(huì)有一定的延遲。

清理時(shí)會(huì)根據(jù)用戶(hù)配置的maxmemory-policy來(lái)做適當(dāng)?shù)那謇恚ㄒ话闶荓RU或TTL),這里的LRU或TTL策略并不是針對(duì)redis的所有key,而是以配置文件中的maxmemory-samples個(gè)key作為樣本池進(jìn)行抽樣清理。

maxmemory-samples在redis-3.0.0中的默認(rèn)配置為5,如果增加,會(huì)提高LRU或TTL的精準(zhǔn)度,redis作者測(cè)試的結(jié)果是當(dāng)這個(gè)配置為10時(shí)已經(jīng)非常接近全量LRU的精準(zhǔn)度了,并且增加maxmemory-samples會(huì)導(dǎo)致在主動(dòng)清理時(shí)消耗更多的CPU時(shí)間,建議:

1 盡量不要觸發(fā)maxmemory,最好在mem_used內(nèi)存占用達(dá)到maxmemory的一定比例后,需要考慮調(diào)大hz以加快淘汰,或者進(jìn)行集群擴(kuò)容。

2 如果能夠控制住內(nèi)存,則可以不用修改maxmemory-samples配置;如果Redis本身就作為L(zhǎng)RU cache服務(wù)(這種服務(wù)一般長(zhǎng)時(shí)間處于maxmemory狀態(tài),由Redis自動(dòng)做LRU淘汰),可以適當(dāng)調(diào)大maxmemory-samples。

這里提一句,實(shí)際上redis根本就不會(huì)準(zhǔn)確的將整個(gè)數(shù)據(jù)庫(kù)中最久未被使用的鍵刪除,而是每次從數(shù)據(jù)庫(kù)中隨機(jī)取5個(gè)鍵并刪除這5個(gè)鍵里最久未被使用的鍵。上面提到的所有的隨機(jī)的操作實(shí)際上都是這樣的,這個(gè)5可以用過(guò)redis的配置文件中的maxmemeory-samples參數(shù)配置。

數(shù)據(jù)逐出策略配置依據(jù)

使用INFO命令輸出監(jiān)控信息,查詢(xún)緩存int和miss的次數(shù),根據(jù)業(yè)務(wù)需求調(diào)優(yōu)Redis配置。

總結(jié)

到此這篇關(guān)于redis 數(shù)據(jù)刪除策略和逐出算法的問(wèn)題小結(jié)的文章就介紹到這了,更多相關(guān)redis 刪除策略 逐出算法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

您可能感興趣的文章:
  • 如何基于js及java分析并封裝排序算法
  • 詳解vue3.0 diff算法的使用(超詳細(xì))
  • 詳細(xì)分析JAVA加解密算法
  • SHA:安全散列算法簡(jiǎn)析 附實(shí)例
  • Python實(shí)現(xiàn)ElGamal加密算法的示例代碼
  • python實(shí)現(xiàn)mean-shift聚類(lèi)算法
  • 經(jīng)典實(shí)例講解C#遞歸算法
  • 通過(guò)代碼實(shí)例了解頁(yè)面置換算法原理

標(biāo)簽:甘南 河源 畢節(jié) 泰州 定州 南寧 拉薩 伊春

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《redis 數(shù)據(jù)刪除策略和逐出算法的問(wèn)題小結(jié)》,本文關(guān)鍵詞  redis,數(shù)據(jù),刪除,策略,和,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問(wèn)題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無(wú)關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《redis 數(shù)據(jù)刪除策略和逐出算法的問(wèn)題小結(jié)》相關(guān)的同類(lèi)信息!
  • 本頁(yè)收集關(guān)于redis 數(shù)據(jù)刪除策略和逐出算法的問(wèn)題小結(jié)的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章
    国产精品7m视频| 天天干在线观看| 亚洲国产又黄又爽女人高潮的| 韩国中文字幕av| 成人在线视频首页| 国产精品专区第二| 中文字幕观看视频| 综合国产在线视频| av在线播放网址| 亚洲成人免费在线观看| 久久av秘一区二区三区| 天天操天天爱天天干| 日韩在线免费视频| 成年人免费视频播放| 亚洲va韩国va欧美va| 日韩av电影免费观看| 免费高清在线一区| 日韩女优在线播放| 久草视频免费在线| 欧美精品视频www在线观看| 色婷婷一区二区三区av免费看| av男人天堂一区| 欧美福利精品| 国产一区二区三区免费看| 5566日本婷婷色中文字幕97| 午夜精品免费观看| 日韩精品在线视频美女| 岛国片在线免费观看| 欧美大片一区二区| 亚洲午夜久久久久久久久红桃| 欧美精品九九久久| 久久99久久98精品免观看软件| 欧美视频一区二区三区在线观看| www.污污视频| 欧美自拍丝袜亚洲| 视频免费在线观看| 日韩欧美精品在线| 欧美亚洲色综久久精品国产| 亚洲国产精品女人久久久| 秋霞欧美一区二区三区视频免费| 亚洲精品在线视频| 日产精品久久久久| 欧美劲爆第一页| 国产黄a三级三级看三级| 成人激情视频在线播放| 日韩高清不卡一区| 久久天堂国产精品| 久久这里只有精品视频网| 高清欧美精品xxxxx| 亚洲国产精品一区二区久久 | 91精品国产91久久久久麻豆 主演| 中文天堂在线一区| 男女男精品视频站| 欧美日本一区二区三区| 国产视频不卡在线| 日韩在线视频中文字幕| 亚洲一区中文字幕在线| 成人精品久久久| 成年人性生活视频| 亚洲精品成人av久久| 午夜精品久久久久久久99水蜜桃 | www.黄色在线| 亚洲二区在线视频| 波多野结衣三级视频| 欧美一二三区在线观看| 国产午夜精品理论片在线| 色噜噜狠狠色综合网图区 | 久久久亚洲精品无码| 亚洲丰满少妇videoshd| 亚洲欧洲在线观看| 日韩毛片在线免费看| 欧美视频在线观看 亚洲欧| 精品国产免费久久久久久婷婷| 欧美一区二区三区视频免费播放 | 亚洲在线观看视频| 成人免费观看视频| 日本a级片免费观看| 在线观看一区二区视频| 四虎影视1304t| 欧美激情精品久久久| 天堂中文资源在线观看| 日韩欧美一区二区三区四区 | 色婷婷激情五月| 热舞福利精品大尺度视频| 国产精品不卡在线| 少妇一级淫免费观看| 最近2019中文字幕一页二页 | 亚洲一卡二卡在线| 久久99精品久久久久久久青青日本| 国产视频911| 在线观看你懂的视频| 亚洲欧美成人精品| 国产女人高潮的av毛片| 精品日韩美女| 亚洲影视在线播放| 五月婷婷婷婷婷| 96精品视频在线| 国产成人在线观看免费网站| 成人羞羞国产免费网站| 欧美一级在线观看| 久久这里只有精品9| 韩国精品一区二区三区六区色诱| 日韩一区有码在线| 黄色工厂在线观看| 国内揄拍国内精品少妇国语| 国产伦精品一区二区三区免费迷 | 大桥未久一区二区三区| 色哟哟一区二区| 精国产品一区二区三区a片| 成人免费视频97| 国产精品成人免费精品自在线观看| 日本护士做爰视频| 97超碰蝌蚪网人人做人人爽| 国产精品中文欧美| 欧美男女交配视频| 日韩在线www| 国产一区二区三区四区五区入口| 日日躁夜夜躁aaaabbbb| 中文字幕欧美精品日韩中文字幕| 天天操天天舔天天干| av网站大全免费| 亚洲福利视频网站| 日本黄色大片视频| av片中文字幕| 久久精品国产亚洲精品| 国产一区二区在线观看免费| www.国产福利| 午夜精品久久久久久久久久久久| 99在线视频精品| 免费观看一级一片| 国产精品美女午夜av| 亚洲精品视频观看| 日韩免费av片| 色噜噜狠狠一区二区三区| 在线不卡中文字幕| 欧美特级特黄aaaaaa在线看| 精品www久久久久奶水| 久久亚洲影音av资源网 | 欧美丰满熟妇xxxxx| 欧美精品免费播放| 国产亚洲成aⅴ人片在线观看| 91免费在线看片| 国产chinese精品一区二区| 在线观看一区二区视频| 亚洲av无码乱码在线观看性色 | 欧美激情一区二区三区成人 | 欧美亚洲禁片免费| www黄色网址| 爽爽爽在线观看| 国产精品电影一区| 精品久久久久国产| 精品国产av一区二区三区| 亚洲精品高清无码视频| 国产做受69高潮| 亚洲人成网站在线| 自拍偷拍一区二区三区| 日韩欧美在线一区| www.午夜激情| 制服下的诱惑暮生| 成人福利网站在线观看11| 色婷婷亚洲一区二区三区| a毛片在线免费观看| www.超碰97.com| 国产精品女上位| 亚洲一区欧美在线| 精品国产av无码一区二区三区| 日韩中文字幕精品视频| 国产日韩av一区| 欧美性猛交bbbbb精品| 99热自拍偷拍| 欧美孕妇性xx| 日本韩国一区二区三区| 久久精品亚洲一区二区| 免费日本黄色网址| 狠狠干一区二区| 精品视频www| 国产日韩视频一区二区三区| 超碰在线观看91| 九九热免费在线观看| 亚洲xxx自由成熟| 亚洲国产精品小视频| 99精品免费观看| 黄色一级片网址| 欧美高清在线观看| 麻豆久久久久久久| 中文字幕 欧美 日韩| 国产精品区一区二区三在线播放| 亚洲国产高清高潮精品美女| 久久夜色精品国产欧美乱极品| www.com亚洲| 亚洲妇女无套内射精| 鲁丝一区二区三区免费| 久久精品国产精品亚洲| 欧美日韩亚洲精品一区二区三区 | 一本一道久久a久久综合蜜桃| 成人做爰66片免费看网站| 亚洲视频在线观看视频| 一二三区精品视频| 美日韩一区二区| 懂色av.com| 91插插插影院| 欧美日韩一区综合| 国内精品久久久久| 91精品免费在线| 国产精品免费网站在线观看| 免费观看黄一级视频| 男的操女的网站| 精品久久久99| 亚洲ai欧洲av| 国产成人精品最新| 日韩激情视频在线播放| 亚洲一区二区三区爽爽爽爽爽| 免费成人在线网站| 亚洲黄色免费观看| 久久人人妻人人人人妻性色av| 在线观看av的网址| 91香蕉嫩草影院入口| 久久影院中文字幕| 欧美日韩国产123区| 国产呦萝稀缺另类资源| 一区二区三区国产好的精华液| 欧美亚州在线观看| 日本91av在线播放| 亚洲欧洲在线观看| 91久久精品日日躁夜夜躁欧美| 成人激情视频网站| 日韩欧美国产成人精品免费| 欧洲国产精品| 国产精品偷伦免费视频观看的| 一区二区三区国产在线观看| 欧美色倩网站大全免费| 亚洲欧洲精品一区二区精品久久久| 免费成人在线网站| 97人妻精品一区二区三区软件| 国产馆在线观看| 一个人看的视频www| 国产精品久久..4399| 精品在线视频一区二区三区| 国产成人精品日本亚洲| 中文字幕日韩av综合精品| 欧美区一区二区三区| 亚洲精品国产精品乱码不99| a亚洲天堂av| 久久黄色级2电影| 亚洲精品久久久久久无码色欲四季 | 欧美日韩一级二级| 亚洲电影一区二区| 日本一区二区三区免费乱视频| 国产乱码精品1区2区3区| 亚洲aaa在线观看| 国产欧美日韩成人| 精人妻无码一区二区三区| 强乱中文字幕av一区乱码| 欧洲av一区二区三区| 亚洲图片欧美另类| 午夜精品免费看| 免费观看精品视频| www国产无套内射com| 日本高清不卡三区| 国精产品99永久一区一区| 国产一区二区丝袜| 97在线观看视频| 欧美国产亚洲精品久久久8v| 国产午夜精品视频免费不卡69堂| 日韩视频一区二区三区| 狠狠色噜噜狠狠狠狠97| 亚洲综合一区二区| 亚洲色大成网站www久久九九| 日本一区二区免费在线| 91欧美一区二区| 白白色 亚洲乱淫| 不卡的电视剧免费网站有什么| 国产成人av福利| 国产成人在线色| 国产成人免费高清| 国产高清在线精品| 大陆成人av片| 91在线精品一区二区| 91免费观看视频在线| 久久你懂得1024| 久久久99久久| 国产精品对白交换视频 | 国产在线观看精品| 亚洲在线观看视频| 国产欧美一区二区三区不卡高清| 国产精品国产三级欧美二区| 99久久精品免费看国产一区二区三区 | 国产乱女淫av麻豆国产| 激情小说欧美色图| 亚洲国产精品无码久久久久高潮| 大地资源二中文在线影视观看| 日韩精品卡通动漫网站| 91视频免费在观看| 亚洲激情一区二区| 国产精品自拍合集| 欧美日韩激情视频在线观看| 国产精品久久久久9999小说| 天天看片天天操| 国产精品300页| 中文字幕第69页| 好吊操这里只有精品| 中文字幕人妻精品一区| 狠狠躁夜夜躁av无码中文幕| 秋霞成人午夜伦在线观看| 风流少妇一区二区| 国产精品视频观看| 欧美日韩国产精品一区二区三区四区| 欧美午夜精品电影| 亚洲激情自拍图| 欧美乱妇40p| 国产精品久久久久久搜索| 国产精品一区二区免费看| 先锋影音欧美| 日本精品免费在线观看| 亚洲色图欧美自拍| 在线a欧美视频| 欧美岛国在线观看| 色狠狠av一区二区三区香蕉蜜桃| 在线中文字幕一区| 在线亚洲免费视频| 日韩电影网在线| 亚州成人av在线| 国产精品久久精品国产| 亚洲AV无码成人精品一区| 国产日韩成人内射视频 | 免费中文字幕在线观看| 99久久精品免费看国产交换| 久久99精品久久久久久国产越南| 久久久久88色偷偷免费| 欧美性猛交xxxx富婆| 国产丝袜精品视频| 欧亚精品中文字幕| 日韩av影视| 依人在线免费视频| 日韩欧美综合视频| 性欧美videos另类hd| 成人福利视频网站| 精品国产乱码久久久久久虫虫漫画 | 精品在线观看一区| 国产三级自拍视频| 成人网在线免费视频| 欧美日在线观看| 99久久精品免费看国产| 日韩欧美黄色动漫| 中文字幕亚洲在线| 99久久精品免费看国产一区二区三区| 91黄色在线看| 国产精品久久久久无码av色戒| 国产一级片一区二区| 国产黄色成人av| 欧美日韩在线免费观看| 色七七影院综合| 国产精品久久久久久久久久直播 | 亚洲大型综合色站| 精品久久久久久国产| 在线不卡欧美精品一区二区三区| 欧美国产日韩xxxxx| 日韩在线三区| 成人做爰www看视频软件| 无码人妻精品一区二区50| 成人美女视频在线看| 欧洲生活片亚洲生活在线观看| 欧美精品亚州精品| 亚洲精品成人久久久998| 黄色免费视频网站| 91国内精品视频| 久久久久国产精品免费免费搜索| 欧美精品丝袜久久久中文字幕| 青青青国产精品一区二区| 美女av免费观看| 久久久久久久麻豆| 另类小说视频一区二区| 色视频一区二区| 91a在线视频| 国产精品一区二区三区久久 | 亚洲精品在线91| 国产精品入口免费| 日本网站在线看| 国产精品久久久久久免费免熟| 国产精品久久久久久亚洲伦| 精品一区电影国产| 欧美国产综合视频| 尤物网站在线观看| 天天综合网在线观看| 日韩欧美在线国产| 欧美亚洲在线视频| 国产极品粉嫩福利姬萌白酱| 成人精品在线看| 国产亚洲精品bt天堂精选| 在线观看不卡av| 异国色恋浪漫潭| 欧美成人精品一区二区免费看片| 久久国产欧美日韩精品| 欧美一区二区播放| 国产经典一区二区三区| 无码一区二区精品| 免费成人在线视频观看| 日韩视频免费观看高清完整版在线观看| 99久久一区三区四区免费| 娇妻高潮浓精白浆xxⅹ| 天堂精品中文字幕在线| 欧美色网站导航| 国产精品久久一区二区三区| 人妻丰满熟妇aⅴ无码| 极品销魂美女一区二区三区| 精品日韩一区二区| 综合av色偷偷网| 成人免费在线视频播放| 丰满人妻一区二区三区四区| 亚洲香蕉伊在人在线观|