Как понять ключ истечения срока действия Redis при встрече с красивым интервьюером

Redis

  Когда мы встретили на собеседовании красивую интервьюершу, мы подумали, что собеседование пройдет легче и пришло время хорошо показать свои навыки. Однако появляется следующая сцена: когда бьюти-интервьюер слышит, что вы использовали Redis, возникает проблема.

👩Интервьюер:Q1, знаете ли вы команду для Redis, чтобы установить время истечения срока действия ключа?

👧 ты: Вы не постеснялись сказать кучу команд и употреблений, типа expire и прочих команд

(🎈 В этот раз вы хотите спросить, что просто? Но неужели все так просто? Красавица-интервьюер сделала паузу и продолжила спрашивать)

👩Интервьюер:Q2, как вы говорите о том, как Redis реализует настройку времени истечения срока действия? И как судить о сроке действия ключа?
👧 ты:(Думаю это не сложно для меня в данный момент), а потом я еще раз об этом говорил, структура данных redisDb в сервере БД Redis и определение времени истечения срока действия

(🎈Вы опять думаете, что не стоит спрашивать, давайте сменим тему Redis, значит вы не правы)

👩Интервьюер:(Глядя на вас с улыбкой) Q3, как насчет стратегии удаления просроченных ключей и стратегии удаления и реализации просроченных ключей Redis?
🤦‍️ ты: В это время ваш ответ не так гладок, и иногда ваш разум заблокирован.

(🎈Это потому, что вы можете быть немного запутались, или вы знаете только стратегию удаления некоторых ключей с истекшим сроком действия, но не знаете, как ее реализовать. Думаете, вопрос интервьюера окончен?)

👩Интервьюер:Q4, как быть с ключами с истекшим сроком действия в других ссылках (таких как AOF, RDB)?
🤦🤦вы: ......

(🎈Это ещё больше смущает. Я не всё знаю, а может и не знаю. Я хотел хорошо выступить, и ещё думал, что интервью будет легче, но не ожидал, что испытаю такое )

Чтобы избежать этой неловкой сцены, теперь вам нужно записать следующий контент, чтобы вы могли хорошо выступить перед красивой интервьюершей.

1. Основные сведения об истечении срока действия Redis

База данных Redis используется на сервере базы данных.redisDbСтруктура данных, структура следующая:

typedef struct redisDb {
     dict *dict;     /* 键空间 key space */
     dict *expires;    /* 过期字典 */
     dict *blocking_keys;  /* Keys with clients waiting for data (BLPOP) */
     dict *ready_keys;   /* Blocked keys that received a PUSH */
     dict *watched_keys;   /* WATCHED keys for MULTI/EXEC CAS */
     struct evictionPoolEntry *eviction_pool; /* Eviction pool of keys */
     int id;      /* Database ID */
     long long avg_ttl;   /* Average TTL, just for stats */
} redisDb;

в,

  • ключевое пространство (key space): Словарь dict используется для хранения всех пар ключ-значение в базе данных.
  • просроченный словарь (expires): Сохраните время истечения срока действия всех ключей в базе данных, используется время истеченияUNIXПредставление метки времени, а значениеlong longцелое число

1.1 Команда установки времени истечения срока действия

  • EXPIRE \<key> \<ttl>: Команда используется для установки времени истечения срока действия ключевого ключа после ttl секунд.
  • PEXPIRE \<key> \<ttl>: Команда используется для установки времени истечения срока действия ключевого ключа после ttl миллисекунд.
  • EXPIREAT \<key> \<timesramp>: команда используется для установки времени истечения срока действия ключа на временную метку в секундах, указанную временной меткой.
  • PEXPIREAT \<key> \<timesramp>: команда используется для установки времени истечения срока действия ключа на отметку времени, указанную отметкой времени в миллисекундах.

Установить время истечения:

redis> set Ccww   5 2 0  
ok  
redis> expire Ccww 5  
ok  

Используйте структуру redisDb для хранения представления графа данных:

1.2 Сохранение и определение срока годности

Суждение просроченного ключа фактически проходитпросроченный словарьЧтобы судить, шаги:

  1. Проверьте, существует ли данный ключ в словаре с истекшим сроком действия, если да, получите время истечения срока действия ключа.
  2. Судя по тому, превышает ли текущая отметка времени UNIX время истечения срока действия ключа, если да, то срок действия ключа истек, в противном случае срок действия ключа не истек.

2. Стратегия удаления просроченного ключа

2.1 Три разные стратегии удаления

  1. Регулярно удалять: создать запланированное задание, установив время истечения срока действия ключа. Когда срок действия ключа истечет, немедленно удалите ключ.
  2. ленивое удаление: Пусть срок действия ключа истекает независимо, но каждый раз, когда ключ получен из пространства ключей, проверять, истек ли срок действия полученного ключа, если срок его действия истек, удалить ключ, если нет, вернуть ключ
  3. регулярно удалять: Программа каждый раз проверяет базу и удаляет в ней просроченные ключи, а сколько просроченных ключей удалять и сколько баз проверять, определяется алгоритмом.

2.2 Преимущества и недостатки трех стратегий удаления

2.2.1 Запланированное удаление

  • преимущество:Удобная для памяти стратегия удаления по времени может гарантировать, что ключи с истекшим сроком действия будут удалены как можно быстрее, а память, занятая в течение периода, будет освобождена.
  • недостаток:Это не является дружественным к процессорному времени.Когда есть много ключей с истекшим сроком действия, удаление задач будет занимать большую часть времени процессора.Когда памяти не мало, но времени процессора мало, время процессора используется для удаления просроченных ключей, которым нечего делать. делать с текущей задачей. Время ответа сервера и пропускная способность

2.2.2 Ленивое удаление

  • преимущество:Она не требует процессорного времени. Ключи с истекшим сроком действия проверяются и удаляются каждый раз, когда ключ извлекается из пространства ключей. Цель удаления ограничена обрабатываемым в данный момент ключом. Эта стратегия не будет тратить время ЦП на другие ненужные задачи удаления.
  • недостаток:Он не дружит с памятью, и ключ с истекшим сроком действия не может быть удален по истечении срока его действия, в результате чего занятая память не будет освобождена. Возможна даже утечка памяти.Когда есть много ключей с истекшим сроком действия, и эти ключи с истекшим сроком действия не были доступны, это может привести к тому, что они будут храниться в памяти все время, что приведет к утечкам памяти.

2.2.4 Периодическое удаление

Поскольку удаление по расписанию будет занимать слишком много процессорного времени, влиять на время отклика и пропускную способность сервера, а ленивое удаление тратит слишком много памяти, существует опасность утечки памяти, поэтому существует стратегия регулярного удаления, которая объединяет и компрометирует эти два процесса. стратегии.

  1. Стратегия периодического удаления выполняет удаление ключей с истекшим сроком действия через регулярные промежутки времени и уменьшает влияние удаления на время ЦП, ограничивая продолжительность и частоту удаления.
  2. Стратегия временного удаления эффективно снижает потери памяти, вызванные ключами с истекшим сроком действия.

Сложность стратегии запланированного удаления заключается в определении продолжительности и частоты операции удаления:

  Операция удаления выполняется слишком часто. Или, если время выполнения слишком велико, стратегия периодического удаления выродится в стратегию периодического удаления, так что слишком много процессорного времени будет потрачено на удаление просроченных ключей. Наоборот, так же, как и при ленивом удалении, происходит пустая трата памяти. Следовательно, для использования стратегии периодического удаления необходимо разумно установить продолжительность выполнения и частоту выполнения операции удаления в соответствии с ситуацией на сервере.

3. Стратегия удаления ключа истечения срока действия Redis

  Сервер Redis использует две стратегии отложенного удаления и периодического удаления вместе.Благодаря сотрудничеству между этими двумя стратегиями сервер может достичь баланса между разумным использованием процессорного времени и пустой тратой памяти.

3.1 Реализация стратегии ленивого удаления

  Redis сначала найдет этот ключ при выполнении любых команд чтения и записи. Ленивое удаление используется в качестве точки входа перед поиском ключа. Если срок действия ключа истечет, ключ будет удален.

robj *lookupKeyRead(redisDb *db, robj *key) {
          robj *val;
	 expireIfNeeded(db,key); // 切入点
	 val = lookupKey(db,key);
	 if (val == NULL)
	  server.stat_keyspace_misses++;
	 else
	  server.stat_keyspace_hits++;
	 return val;
}

пройти черезexpireIfNeededФункция проверяет, удалена ли клавиша ввода

int expireIfNeeded(redisDb *db, robj *key) {
     /* 取出键的过期时间 */
    mstime_t when = getExpire(db,key);
    mstime_t now;
    
     /* 没有过期时间返回0*/
    if (when < 0) return 0; /* No expire for this key */

    /* 服务器loading时*/
    if (server.loading) return 0;

    /* 根据一定规则获取当前时间*/
    now = server.lua_caller ? server.lua_time_start : mstime();
    /* 如果当前的是从(Slave)服务器
     * 0 认为key为无效
     * 1 if we think the key is expired at this time. 
     * */
    if (server.masterhost != NULL) return now > when;

     /* key未过期,返回 0 */
    if (now <= when) return 0;

     /* 删除键 */
    server.stat_expiredkeys++;
    propagateExpire(db,key,server.lazyfree_lazy_expire);
    notifyKeyspaceEvent(NOTIFY_EXPIRED,
        "expired",key,db->id);
    return server.lazyfree_lazy_expire ? dbAsyncDelete(db,key) :
                                         dbSyncDelete(db,key);
}

3.2 Реализация политики периодического удаления

Периодическое удаление ключа    будет периодически выполнять задачи в Redis (serverCron, выполняется каждые 100 мс по умолчанию), и это вхождение Redismasterузел, потому чтоslaveУзел синхронизируется с помощью команды DEL главного узла для удаления ключа.

for (j = 0; j < dbs_per_call; j++) {
 int expired;
 redisDb *db = server.db+(current_db % server.dbnum);
 
 current_db++;
 
 /* 超过25%的key已过期,则继续. */
 do {
  unsigned long num, slots;
  long long now, ttl_sum;
  int ttl_samples;
 
  /* 如果该db没有设置过期key,则继续看下个db*/
  if ((num = dictSize(db->expires)) == 0) {
   db->avg_ttl = 0;
   break;
  }
  slots = dictSlots(db->expires);
  now = mstime();
 
  /*但少于1%时,需要调整字典大小*/
  if (num && slots > DICT_HT_INITIAL_SIZE &&
   (num*100/slots < 1)) break;
 
  expired = 0;
  ttl_sum = 0;
  ttl_samples = 0;
 
  if (num > ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP)
   num = ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP;// 20
 
  while (num--) {
   dictEntry *de;
   long long ttl;
 
   if ((de = dictGetRandomKey(db->expires)) == NULL) break;
   ttl = dictGetSignedIntegerVal(de)-now;
   if (activeExpireCycleTryExpire(db,de,now)) expired++;
   if (ttl > 0) {
    /* We want the average TTL of keys yet not expired. */
    ttl_sum += ttl;
    ttl_samples++;
   }
  }
 
  /* Update the average TTL stats for this database. */
  if (ttl_samples) {
   long long avg_ttl = ttl_sum/ttl_samples;
 
   /样本获取移动平均值 */
   if (db->avg_ttl == 0) db->avg_ttl = avg_ttl;
   db->avg_ttl = (db->avg_ttl/50)*49 + (avg_ttl/50);
  }
  iteration++;
  if ((iteration & 0xf) == 0) { /* 每迭代16次检查一次 */
   long long elapsed = ustime()-start;
 
   latencyAddSampleIfNeeded("expire-cycle",elapsed/1000);
   if (elapsed > timelimit) timelimit_exit = 1;
  }
 /* 超过时间限制则退出*/
  if (timelimit_exit) return;
  /* 在当前db中,如果少于25%的key过期,则停止继续删除过期key */
 } while (expired > ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP/4);
}

   Пройдите каждый db по очереди (номер конфигурации по умолчанию — 16) и для каждого db случайным образом выберите 20 (ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP) ключ, чтобы определить, истек ли срок его действия. Если срок действия менее 25% ключей, выбранных в одном раунде, итерация будет прекращена. Кроме того, если в процессе итерации будет превышен определенный лимит времени, процесс удаления истекших быть прекращено.

4. Обработка просроченных ключей функциями AOF, RDB и репликации

4.1 RDB

Создать RDB-файл
 Программа проверит ключи в базе данных, и ключи с истекшим сроком действия не будут сохранены во вновь созданный файл RDB

Загрузить RDB-файл

  1. Основная служба загружает файл RDB, проверяет ключи, сохраненные в файле, игнорирует ключи с истекшим сроком действия и загружает ключи с неистекшим сроком действия.
  2. При загрузке файла RDB с сервера будут загружены все ключи (с истекшим и неистекшим сроком действия), сохраненные файлом, но синхронизация данных с главного сервера также очистит базу данных подчиненного сервера.

4.2 AOF

  • Запись файла AOF: при удалении ключа с истекшим сроком действия в файл AOF будет добавлена ​​команда DEL, чтобы явно записать, что ключ был удален.
  • Перезапись AOF: ключи с истекшим сроком действия не сохраняются в перезаписанном файле AOF.

4.3 Копировать

 Когда сервер работает в режиме репликации, удаление просроченного ключа с сервера контролируется главным сервером.Это преимущество в основном для поддержания согласованности данных главного и подчиненных серверов:

  1. После того, как главный сервер удалит ключ с истекшим сроком действия, он явным образом отправит команду DEL всем подчиненным серверам, чтобы указать подчиненным серверам удалить ключ с истекшим сроком действия.
  2. Когда подчиненный сервер выполняет команду чтения, отправленную клиентом, даже если он встречает ключ с истекшим сроком действия, он не удаляет ключ с истекшим сроком действия и ничего не делает.
  3. Обработка удаления выполняется на подчиненном сервере только после получения команды DEL главного сервера.

Вы в порядке, офицеры? Если вам это нравится, проведите пальцем, чтобы нажать 💗, нажмите, чтобы подписаться! ! Спасибо за Вашу поддержку!

Добро пожаловать в публичный аккаунт【Технический блог Ccww], впервые была запущена оригинальная техническая статья