предисловие
список(list
) тип используется для хранения несколькихаккуратныйизнить. существуетRedis
, ты сможешьоба концапровестивставлять(push
)инеожиданно возникнуть(pop
) операция, вы также можете получитьуказанный диапазонизсписок элементов,ПолучатьУкажите индекс индексаизэлементЖдать.
списокЭто относительногибкийизструктура данных, который может выступать в роликучаиочередьроль, существует множество сценариев приложений в фактической разработке.
как показано на рисунке,a
,b
,c
,d
,e
пять элементовслева направосформировалупорядоченный список, каждая строка в списке называетсяэлемент(element
), список может хранить до2 ^ 32 - 1
элементы.
- списоквставлятьинеожиданно возникнутьдействовать
- списокПолучать,перехватыватьиУдалитьдействовать
Другие статьи
-
Углубленный анализ серии Redis (1) — введение в Redis и построение master-slave
-
Углубленный анализ серии Redis (2) — контрольный режим Redis и кластер высокой доступности
-
Углубленный анализ серии Redis (4) — Обзор структуры данных Redis и глобальных команд
-
Углубленный анализ серии Redis (5) — Строка структуры данных Redis
-
Углубленный анализ серии Redis (6) — хэш структуры данных Redis
-
Углубленный анализ серии Redis (7) — Список структур данных Redis
-
Углубленный анализ серии Redis (8) — коллекции структур данных Redis.
текст
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
Эта учетная запись будет продолжать делиться сухими продуктами серверных технологий, включая основы виртуальных машин, многопоточное программирование, высокопроизводительные фреймворки, асинхронное ПО, промежуточное ПО для кэширования и обмена сообщениями, распределенные и микросервисы, материалы для обучения архитектуре и расширенные учебные материалы и статьи.