предисловие
список(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
Эта учетная запись будет продолжать делиться сухими продуктами серверных технологий, включая основы виртуальных машин, многопоточное программирование, высокопроизводительные фреймворки, асинхронное ПО, промежуточное ПО для кэширования и обмена сообщениями, распределенные и микросервисы, материалы для обучения архитектуре и расширенные учебные материалы и статьи.