Углубленный анализ серии Redis (7) — Список структур данных Redis

Redis задняя часть Архитектура балансировки нагрузки

предисловие

список(list) тип используется для хранения несколькихаккуратныйизнить. существуетRedis, ты сможешьоба концапровестивставлять(pushнеожиданно возникнуть(pop) операция, вы также можете получитьуказанный диапазонизсписок элементов,ПолучатьУкажите индекс индексаизэлементЖдать.

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

как показано на рисунке,a,b,c,d,eпять элементовслева направосформировалупорядоченный список, каждая строка в списке называетсяэлемент(element), список может хранить до2 ^ 32 - 1элементы.

  • списоквставлятьинеожиданно возникнутьдействовать

  • списокПолучать,перехватыватьиУдалитьдействовать

Другие статьи

текст

1. Связанные команды

Далее будет следоватьсписокиз5своего родаТип операцииВведите команду:

1.1 Добавление команд

1.1.1 Вставка элементов справа

rpush key value [value ...]

код нижесправа налевовставить элементc,b,a:

127.0.0.1:6379> rpush listkey c b a
(integer) 3

lrange 0 -1команда можетслева направополучить списоквсе элементы:

127.0.0.1:6379> lrange listkey 0 -1
1) "c"
2) "b"
3) "a"

1.1.2 Вставка элементов слева

lpush key value [value ...]

как использовать иrpushто же самое, но излевая вставка, которые здесь повторяться не будут.

1.1.3 Вставка элементов до или после элемента

linsert key before|after pivot value

linsertКоманда начнется ссписокнайти вПервыйравныйpivotэлемент, в которомвперед(before)илиЗадний(after) вставляет новый элементvalue, например, в списке будет следующая операцияэлемент bВставить передredis:

127.0.0.1:6379> linsert listkey before b redis
(integer) 4

Возвращаемый результат4, представляющий текущийсписокиздлина, текущий список становится:

127.0.0.1:6379> lrange listkey 0 -1
1) "c"
2) "redis"
3) "b"
4) "a"

1.2 Команда запроса

1.2.1 Получить список элементов в указанном диапазоне

lrange key start stop

lrangeДействие получает списокуказанный индексОхват всех элементов.

индекс индексаЕсть две особенности:

  • Во-первых, индексный индексслева направосоответственно0прибытьN-1,носправа налевосоответственно-1прибыть-N.

  • Второй,lrangeсерединаendварианты включаютсам, этот и многие языки программирования не содержатendНе совсем то же самое.

слева направополучить первый2к4элементы, вы можете сделать следующее:

127.0.0.1:6379> lrange listkey 1 3
1) "redis"
2) "b"
3) "a"

справа налевополучить первый1к3элементы, вы можете сделать следующее:

127.0.0.1:6379> lrange listkey -3 -1
1) "redis"
2) "b"
3) "a"

1.2.2 Получить элемент по указанному индексу списка

lindex key index

например текущий списокпоследнийэлементa:

127.0.0.1:6379> lindex listkey -1
"a"

1.2.3 Получить длину списка

llen key

Например, следующий примертекущая длина списказа4:

127.0.0.1:6379> llen listkey
(integer) 4

1.3 Команда удаления

1.3.1 Извлечение элементов из левой части списка

lpop key

Следующие операции будутсписоккрайний левый элементcвсплывать, после всплыватьсписокстатьredis,b,a.

127.0.0.1:6379> lpop listkey
"c"
127.0.0.1:6379> lrange listkey 0 -1
1) "redis"
2) "b"
3) "a"

1.3.2 Извлечение элементов из правой части списка

rpop key

как его использовать иlpopто же самое, только из спискаПравильноВыталкивает метаэлемент.

127.0.0.1:6379> lpop listkey
"a"
127.0.0.1:6379> lrange listkey 0 -1
1) "c"
2) "redis"
3) "b"

1.3.3 Удалить указанный элемент

lrem key count value

lremКоманда начнется ссписокнайти вравный valueэлементыУдалить,в соответствии сcountРазница делится на три случая:

  • count > 0:слева направо, удалить доcountэлементы.

  • count < 0:справа налево, удалить доcount абсолютная величинаэлементы.

  • count = 0,удалить все.

Например, чтобы перечислитьслева направовставлять5Кусокa, то токсписокстать“a a a a a redis b a”, следующие операции будут начинаться со спискалевыйначать удаление4заaЭлементы:

127.0.0.1:6379> lrem listkey 4 a
(integer) 4
127.0.0.1:6379> lrange listkey 0 -1
1) "a"
2) "redis"
3) "b"
4) "a"

1.3.4 Обрезка списков по диапазону индексов

127.0.0.1:6379> ltrim listkey 1 3
OK
127.0.0.1:6379> lrange listkey 0 -1
1) "redis"
2) "b"
3) "a"

1.4 Команда «Изменить»

1.4.1. Изменить элемент по указанному индексу нижнего индекса

ИсправлятьУкажите индекс индексаЭлементы:

lset key index newValue

Следующие операции будут перечислятьlistkeyв3элементы установлены наmysql:

127.0.0.1:6379> lset listkey 2 mysql
OK
127.0.0.1:6379> lrange listkey 0 -1
1) "redis"
2) "b"
3) "mysql"

1.5 Команды блокировки операций

блокировка попКоманда для работы выглядит следующим образом:

blpop key [key ...] timeout brpop key [key ...] timeout

blpopиbrpopдаlpopиrpopизблокирующая версия, они кромевсплывающее направлениеразные,инструкциив основном то же самое, поэтому следующееbrpopкоманду объяснить,brpopКоманда содержит два параметра:

  • key[key...]: списокнесколько ключей.

  • timeout:блокироватьединица времени:второй).

заtimeoutпараметры, атмосферасписок пустине нольДва случая:

  • список пуст

еслиtimeout = 3,Такклиентждать, пока3возвращается через несколько секунд, еслиtimeout = 0,ТакклиентВсегдаблокироватьПодождите минуту:

127.0.0.1:6379> brpop list:test 3
(nil)
(3.10s)
127.0.0.1:6379> brpop list:test 0
...阻塞...

Если данные были добавлены в течение этого периодаelement1, клиентвернуться сейчас:

127.0.0.1:6379> brpop list:test 3
1) "list:test"
2) "element1"
(2.06s)
  • список не пуст: клиент будетвернуться сейчас.
127.0.0.1:6379> brpop list:test 0
1) "list:test"
2) "element1"

в настоящее время используетbrpop, следует отметить два момента:

  • Один, еслинесколько ключей,Такbrpopвстречаслева направоперебирать ключи, когда естьключможетвсплывающий элемент, клиентвернуться сейчас:
127.0.0.1:6379> brpop list:1 list:2 list:3 0
..阻塞..

В этот момент другойклиентсоответственноlist:2иlist:3Вставить элемент:

client-lpush> lpush list:2 element2
(integer) 1
client-lpush> lpush list:3 element3
(integer) 1

клиентвернется немедленноlist:2серединаelement2,так какlist:2первыйможет всплытьЭлементы.

127.0.0.1:6379> brpop list:1 list:2 list:3 0
1) "list:2"
2) "element2"
  • Во-вторых, еслинесколько клиентовправильнотот же ключвоплощать в жизньbrpop,Таквыполнить первым brpopкомандаклиентМожетПолучатьк значению всплывающего окна.

в порядке в3выполнение на стороне клиентаbrpopЗаказ:

  • Клиент 1:
client-1> brpop list:test 0
...阻塞...
  • Клиент 2:
client-2> brpop list:test 0
...阻塞...
  • Клиент 3:
client-3> brpop list:test 0
...阻塞...

В это время другойклиент lpushэлементlist:testСписок:

client-lpush> lpush list:test element
(integer) 1

Такклиент 1получит элемент, потому чтоклиент 1выполнить первымbrpopкоманда, покаклиент 2иклиент 3будет продолжатьблокировать.

client> brpop list:test 0
1) "list:test"
2) "element"

Связанныйсписокизосновная командаБыло введено, следующая таблица является соответствующей командойвременная сложность:

2. Внутреннее кодирование

тип спискаВнутреннее кодированиеЕсть два вида:

2.1. почтовый список

Когда количество элементов в спискеменьше, чем list-max-ziplist-entriesконфигурация (по умолчанию512), а в спискекаждый элементзначениеменьше, чем list-max-ziplist-valueПри настройке (по умолчанию64байт),Redisвыберетziplistприйти каксписокизВнутренняя реализациядля уменьшения использования памяти.

2.2. связанный список

когдаТип спискане в состоянии удовлетворитьziplistусловия,RedisБудет использоватьсяlinkedlistв видесписокизВнутренняя реализация.

2.3. Преобразование кода

Следующий пример демонстрируетТип спискаизВнутреннее кодирование, и соответствующие изменения.

  • когда элементменьшеинет крупных элементовчас,Внутреннее кодированиезаziplist:
127.0.0.1:6379> rpush listkey e1 e2 e3
(integer) 3
127.0.0.1:6379> object encoding listkey
"ziplist"
  • Когда количество элементов превышает512Кусок,Внутреннее кодированиестатьlinkedlist:
127.0.0.1:6379> rpush listkey e4 e5 ... e512 e513
(integer) 513
127.0.0.1:6379> object encoding listkey
"linkedlist"
  • когда элемент превышает64 байт,Внутреннее кодированиетакже станетlinkedlist:
127.0.0.1:6379> rpush listkey "one string is bigger than 64 byte..."
(integer) 4
127.0.0.1:6379> object encoding listkey
"linkedlist"

Redis3.2версия обеспечиваетquicklist Внутреннее кодирование, проще говоря, этоziplistзаузелизlinkedlist, который сочетает в себеziplistиlinkedlistПреимущества обоихТип спискаобеспечивает лучшееВнутреннее кодированиеРеализация, принцип ее проектирования может относиться кRedisеще один авторMatt Stancliffблогredis-quicklist.

3. Сценарии применения

3.1 Очередь сообщений

пройти черезRedisизlpush + brpop комбинация команд, вы можете достичьочередь блокировки. как показано на рисунке:

производитель клиентиспользоватьlrpushиз спискаВставить элемент слева,Несколько клиентов-потребителейиспользоватьbrpopЗаказблокировкаиз"схватить"списокхвостикЭлементы,несколько клиентовгарантированное потреблениебалансировки нагрузкиивысокая доступность.

3.2. Список статей

каждыйПользовательиметь свои собственныеСписок статей, что сейчас требуетсянумерация страницПоказать список статей. Рассмотрите возможность использованиясписок, потому что список не толькоЗаказал, поддерживаяпо диапазону индексовПолучите элемент.

  • В каждой статье используетсяхэш-структурамагазине, например, у каждой статьи есть3атрибутыtitle,timestamp,content:
hmset acticle:1 title xx timestamp 1476536196 content xxxx
hmset acticle:2 title yy timestamp 1476536196 content yyyy
...
hmset acticle:k title kk timestamp 1476512536 content kkkk
  • список статей пользователюдобавить статью,user:{id}:articlesв виде списка пользовательских статейключ:
lpush user:1:acticles article:1 article:3 article:5
lpush user:2:acticles article:2 article:4 article:6
...
lpush user:k:acticles article:7 article:8
  • нумерация страницПолучатьСписок пользовательских статей, например нижеПоддельный кодполучить пользователейid=1первый10Статья:
articles = lrange user:1:articles 0 9
for article in {articles}
    hgetall {article}

использоватьсписоктипспастииПолучатьЕсть две проблемы со списками статей:

  • Первый: если каждый разнумерация страницприобретенныйбольше статей, который нужно выполнить несколько разhgetallоперации, вы можете рассмотреть возможность использованияPipelineпровестиМассовое приобретение, или рассмотрите возможность преобразования данных статьисериализовать в строкутип, использованиеmget Массовое приобретение.

  • второй:нумерация страницПолучатьСписок статейчас,lrangeкоманда в спискеЛучшая производительность на обоих концах,но еслибольший список, получить списоксредний диапазонЭлементыпроизводительность будет хуже. На этом этапе подумайте о том, чтобы составить списоквторичный расколили используйтеRedis 3.2изquicklistВнутренне закодированная реализация, она сочетает в себеziplistиlinkedlistВозможности для получения спискасредний диапазонэлементы также могут бытьЭффективное завершение.

3.3 Другие сценарии

На самом деле существует множество сценариев использования списков.

комбинация команд Соответствующая структура данных
lpush + lpop Куча
lpush + rpop Очередь
lpush + ltrim Ограниченная коллекция
lpush + brpop Очередь сообщений

резюме

В этой статье описываетсяRedisсерединасписокНекоторые изосновные команды,Внутреннее кодированиеиПрименимая сцена. отличается сочетаниемЗаказ, вы можете поставитьсписокконвертировать в разныеструктура данныхиспользовать.

Ссылаться на

«Разработка и эксплуатация Redis»


Добро пожаловать в технический публичный аккаунт: Zero One Technology Stack

零壹技术栈

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