HTML Diff
0 added 0 removed
Original 2026-01-01
Modified 2026-03-10
1 <p>Работаете со Spring, но ни разу не касались<strong>Redis</strong>? Давайте рассмотрим, что такое NoSQL базы данных, в частности Key-Value NoSQL БД, и что представляет собой одна из самых популярных NoSQL БД - Redis.</p>
1 <p>Работаете со Spring, но ни разу не касались<strong>Redis</strong>? Давайте рассмотрим, что такое NoSQL базы данных, в частности Key-Value NoSQL БД, и что представляет собой одна из самых популярных NoSQL БД - Redis.</p>
2 <h2>NoSQL DB (нереляционные БД)</h2>
2 <h2>NoSQL DB (нереляционные БД)</h2>
3 <p>Термин NoSQL (обозначение нереляционных БД) стал примерно таким же многозначным, как и "облако". NoSQL базами данных сейчас называют то, что раньше даже базами данных и не являлось. Например, кэши! Как ни странно, некоторые NoSQL БД имеют SQL-интерфейс. Поэтому саму аббревиатуру NoSQL сейчас расшифровывают как "Not Only SQL".</p>
3 <p>Термин NoSQL (обозначение нереляционных БД) стал примерно таким же многозначным, как и "облако". NoSQL базами данных сейчас называют то, что раньше даже базами данных и не являлось. Например, кэши! Как ни странно, некоторые NoSQL БД имеют SQL-интерфейс. Поэтому саму аббревиатуру NoSQL сейчас расшифровывают как "Not Only SQL".</p>
4 <p>NoSQL базы данных могут показаться совсем "нечеловеческими": в некоторых данные могут пропадать, ACID-транзакции могут отсутствуют как класс, долговременного хранения (durability в ACID) может в принципе не быть. Поэтому решая вопрос о применении той или иной NoSQL БД в проекте, необходимо абсолютно точно понимать, что вы делаете и какую задачу решаете.</p>
4 <p>NoSQL базы данных могут показаться совсем "нечеловеческими": в некоторых данные могут пропадать, ACID-транзакции могут отсутствуют как класс, долговременного хранения (durability в ACID) может в принципе не быть. Поэтому решая вопрос о применении той или иной NoSQL БД в проекте, необходимо абсолютно точно понимать, что вы делаете и какую задачу решаете.</p>
5 <p>NoSQL базы данных можно условно (условно!) разделить на четыре типа:</p>
5 <p>NoSQL базы данных можно условно (условно!) разделить на четыре типа:</p>
6 <p><strong>Key-Value базы данных</strong>хранят данные в виде ключ-значение, самый просто пример in-memory non-clustered non persistent DB - это HashMap. В, действительности, они не так просто устроены, но некоторое представление HashMap может дать</p>
6 <p><strong>Key-Value базы данных</strong>хранят данные в виде ключ-значение, самый просто пример in-memory non-clustered non persistent DB - это HashMap. В, действительности, они не так просто устроены, но некоторое представление HashMap может дать</p>
7 <p><strong>Семейства столбцов или "столбчатые" БД</strong>Их стоит один раз увидеть, чтобы понять, чем они отличаются от реляционных (табличных). В действительности они похожи на школьный журнал - с различными предметами, разделами, но не с идеальной посещаемостью и зафиксированными классами, а с пропусками и новыми учениками, иначе это был бы отличный пример реляционных данных.</p>
7 <p><strong>Семейства столбцов или "столбчатые" БД</strong>Их стоит один раз увидеть, чтобы понять, чем они отличаются от реляционных (табличных). В действительности они похожи на школьный журнал - с различными предметами, разделами, но не с идеальной посещаемостью и зафиксированными классами, а с пропусками и новыми учениками, иначе это был бы отличный пример реляционных данных.</p>
8 <p><strong>Документ-ориентированные</strong>БД хранит документы, допустим для простоты - JSON-ы. Самый простой пример - описание товаров в каком-нибудь интернет-магазине. Описания двух разных телефонов могут разниться очень сильно (у одного телефона описание камеры - может быть полем, а у другого - массив). А теперь сравним описания утюга и телефона. А теперь представим, если мы хотим найти все устройства c зарядкой на 110 V, или найти информацию о всех производителях SSD-дисков. Вот такие задачи можно решить с помощью документ-ориентированные БД.</p>
8 <p><strong>Документ-ориентированные</strong>БД хранит документы, допустим для простоты - JSON-ы. Самый простой пример - описание товаров в каком-нибудь интернет-магазине. Описания двух разных телефонов могут разниться очень сильно (у одного телефона описание камеры - может быть полем, а у другого - массив). А теперь сравним описания утюга и телефона. А теперь представим, если мы хотим найти все устройства c зарядкой на 110 V, или найти информацию о всех производителях SSD-дисков. Вот такие задачи можно решить с помощью документ-ориентированные БД.</p>
9 <p><strong>Графовые БД</strong>Предназначены для хранения графов. Хранить граф в реляционной БД - это тот ещё квест (с разными вариантами решения) и отличная задача на собеседование</p>
9 <p><strong>Графовые БД</strong>Предназначены для хранения графов. Хранить граф в реляционной БД - это тот ещё квест (с разными вариантами решения) и отличная задача на собеседование</p>
10 <p>Иногда выделяют ещё Time Series БД для хранения временных рядов, например, значений котировок акций, серию измерений.</p>
10 <p>Иногда выделяют ещё Time Series БД для хранения временных рядов, например, значений котировок акций, серию измерений.</p>
11 <p>Это деление, повторюсь, достаточно условное. Key-Value БД Redis можно, в частности, отнести и к документ-ориентированным. А ещё если взять две похожих Key-Value БД, например, Redis или<strong>Memcached</strong>, то принципы, на которых они построены, и их возможности могут кардинально отличаться. Например, Memcached является чисто in-memory БД, а вот Redis умеет записывать данные на диск.</p>
11 <p>Это деление, повторюсь, достаточно условное. Key-Value БД Redis можно, в частности, отнести и к документ-ориентированным. А ещё если взять две похожих Key-Value БД, например, Redis или<strong>Memcached</strong>, то принципы, на которых они построены, и их возможности могут кардинально отличаться. Например, Memcached является чисто in-memory БД, а вот Redis умеет записывать данные на диск.</p>
12 <p>Key-Value БД ещё делятся на RAM и не RAM - в любой момент времени можно быстро получить любой элемент или нет. Некоторые Key-Value БД позволяют хранить только массивы байт, какие-то поддерживают различные структуры данных, а какие-то построены на достаточно хитрых<strong>CRDT</strong>. Таким образом, существует большое множество Key-Value баз данных.</p>
12 <p>Key-Value БД ещё делятся на RAM и не RAM - в любой момент времени можно быстро получить любой элемент или нет. Некоторые Key-Value БД позволяют хранить только массивы байт, какие-то поддерживают различные структуры данных, а какие-то построены на достаточно хитрых<strong>CRDT</strong>. Таким образом, существует большое множество Key-Value баз данных.</p>
13 <h2>Redis</h2>
13 <h2>Redis</h2>
14 <p>Это<strong>Redistributable Dictionary Server</strong>- одна из известных Key-Value БД и одна из самых производительных in-memory баз данных. Есть возможность работать не только в режиме in-memory, но и записывать данные на диск, причём достаточно гибко. Поддерживает различные структуры данных - строки, хэш-таблицы, списки и множества этих же объектов, упорядоченные множества и т.д.</p>
14 <p>Это<strong>Redistributable Dictionary Server</strong>- одна из известных Key-Value БД и одна из самых производительных in-memory баз данных. Есть возможность работать не только в режиме in-memory, но и записывать данные на диск, причём достаточно гибко. Поддерживает различные структуры данных - строки, хэш-таблицы, списки и множества этих же объектов, упорядоченные множества и т.д.</p>
15 <h3>Познакомимся с Redis поближе</h3>
15 <h3>Познакомимся с Redis поближе</h3>
16 <p>Для начала развернём Redis в Docker-контейнере: docker run --name our-redis -p 6379:6379 redis</p>
16 <p>Для начала развернём Redis в Docker-контейнере: docker run --name our-redis -p 6379:6379 redis</p>
17 <p>Подключимся к Redis c помощью консольного клиента, тоже завёрнутого в Docker-контейнер: docker run -it --network container:our-redis redis redis-cli -h 127.0.0.1</p>
17 <p>Подключимся к Redis c помощью консольного клиента, тоже завёрнутого в Docker-контейнер: docker run -it --network container:our-redis redis redis-cli -h 127.0.0.1</p>
18 <h3>Основные команды в Redis</h3>
18 <h3>Основные команды в Redis</h3>
19 <p>Итак, если вы увидели приглашение, то можно попробовать положить строчку по ключу:</p>
19 <p>Итак, если вы увидели приглашение, то можно попробовать положить строчку по ключу:</p>
20 127.0.0.1:6379&gt; SET key value OK<p>Синтаксис команд Redis достаточно прост: &lt;имя команды&gt; &lt;аргументы&gt;. Список всех команд можно посмотреть по<a>ссылке</a>, рекомендую держать эту вкладку открытой при изучении Redis.</p>
20 127.0.0.1:6379&gt; SET key value OK<p>Синтаксис команд Redis достаточно прост: &lt;имя команды&gt; &lt;аргументы&gt;. Список всех команд можно посмотреть по<a>ссылке</a>, рекомендую держать эту вкладку открытой при изучении Redis.</p>
21 <p>Мы можем получить список всех ключей в БД:</p>
21 <p>Мы можем получить список всех ключей в БД:</p>
22 127.0.0.1:6379&gt; KEYS * 1) "key"<p>В действительности все команды можно писать строчными буквами, поэтому давайте перестанем использовать заглавные. Redis поддерживает различные типы данных. Попробуем получить тип значения, лежащего по этому ключу:</p>
22 127.0.0.1:6379&gt; KEYS * 1) "key"<p>В действительности все команды можно писать строчными буквами, поэтому давайте перестанем использовать заглавные. Redis поддерживает различные типы данных. Попробуем получить тип значения, лежащего по этому ключу:</p>
23 127.0.0.1:6379&gt; type key string<p>А потом получим значение по этому ключу:</p>
23 127.0.0.1:6379&gt; type key string<p>А потом получим значение по этому ключу:</p>
24 127.0.0.1:6379&gt; get key "value"<p>Также можно посмотреть, как хранится эта строчка в Redis. Для этого используется команда<strong>Dump</strong>:</p>
24 127.0.0.1:6379&gt; get key "value"<p>Также можно посмотреть, как хранится эта строчка в Redis. Для этого используется команда<strong>Dump</strong>:</p>
25 127.0.0.1:6379&gt; dump key "\x00\x05value\t\x00Q\x04\x90\xf4\x95,\xf8\xdf"<p>Оставлю вам удовольствие разобраться в этом формате самостоятельно.</p>
25 127.0.0.1:6379&gt; dump key "\x00\x05value\t\x00Q\x04\x90\xf4\x95,\xf8\xdf"<p>Оставлю вам удовольствие разобраться в этом формате самостоятельно.</p>
26 <h2>Множества (Set) в Redis</h2>
26 <h2>Множества (Set) в Redis</h2>
27 <p>Попробуем создать ключ и положить в него множество (Set) значений. Это можно сделать одной командой:</p>
27 <p>Попробуем создать ключ и положить в него множество (Set) значений. Это можно сделать одной командой:</p>
28 127.0.0.1:6379&gt; sadd ourset value1 value2 (integer) 2<p>Проверим, что по этому ключу действительно лежит множество:</p>
28 127.0.0.1:6379&gt; sadd ourset value1 value2 (integer) 2<p>Проверим, что по этому ключу действительно лежит множество:</p>
29 127.0.0.1:6379&gt; type ourset set<p>Посмотрим значения, лежащие в этом множестве:</p>
29 127.0.0.1:6379&gt; type ourset set<p>Посмотрим значения, лежащие в этом множестве:</p>
30 127.0.0.1:6379&gt; smembers ourset 1) "value2" 2) "value1"<p>И опять же можем посмотреть, как Redis хранит множество:</p>
30 127.0.0.1:6379&gt; smembers ourset 1) "value2" 2) "value1"<p>И опять же можем посмотреть, как Redis хранит множество:</p>
31 127.0.0.1:6379&gt; dump ourset "\x02\x02\x06value2\x06value1\t\x00\xf5C\x86\b\xe05\xef\xa4"<p>И, попробуем удалить одно из значений:</p>
31 127.0.0.1:6379&gt; dump ourset "\x02\x02\x06value2\x06value1\t\x00\xf5C\x86\b\xe05\xef\xa4"<p>И, попробуем удалить одно из значений:</p>
32 127.0.0.1:6379&gt; srem ourset value1 (integer) 1 127.0.0.1:6379&gt; smembers ourset 1) "value2"<p>Множества могут быть очень большими в Redis. Многие операции с множествами, например, объединение<strong>SUNION</strong>, - реализованы отдельными командами. А ещё можно очистить то, что мы добавили:</p>
32 127.0.0.1:6379&gt; srem ourset value1 (integer) 1 127.0.0.1:6379&gt; smembers ourset 1) "value2"<p>Множества могут быть очень большими в Redis. Многие операции с множествами, например, объединение<strong>SUNION</strong>, - реализованы отдельными командами. А ещё можно очистить то, что мы добавили:</p>
33 127.0.0.1:6379&gt; del key ourset (integer) 2 127.0.0.1:6379&gt; type ourset none<h2>Хэш-таблицы (hash) в Redis</h2>
33 127.0.0.1:6379&gt; del key ourset (integer) 2 127.0.0.1:6379&gt; type ourset none<h2>Хэш-таблицы (hash) в Redis</h2>
34 <p>Более сложная структура данных - хэш-таблица (hash). Давайте попробуем создать что-то вроде JSON-документа на основе хэш таблиц. Представим, что у нас есть некий "адрес", представим его в табличном виде:</p>
34 <p>Более сложная структура данных - хэш-таблица (hash). Давайте попробуем создать что-то вроде JSON-документа на основе хэш таблиц. Представим, что у нас есть некий "адрес", представим его в табличном виде:</p>
35 Поле Значение City Omsk Street Lenina number 2<p>Запишем этот объект в хэш по полям и сразу увидим, что собой представляет хэш. Воспользуемся сначала командой добавления поля в хэш:</p>
35 Поле Значение City Omsk Street Lenina number 2<p>Запишем этот объект в хэш по полям и сразу увидим, что собой представляет хэш. Воспользуемся сначала командой добавления поля в хэш:</p>
36 127.0.0.1:6379&gt; hset address city Omsk (integer) 1<p>Посмотрим, какого типа у нас получилось значение по ключу address:</p>
36 127.0.0.1:6379&gt; hset address city Omsk (integer) 1<p>Посмотрим, какого типа у нас получилось значение по ключу address:</p>
37 127.0.0.1:6379&gt; type address hash<p>Вот мы и получили хэш-таблицу состоящую из пар field-value. Посмотреть список всех полей можно так:</p>
37 127.0.0.1:6379&gt; type address hash<p>Вот мы и получили хэш-таблицу состоящую из пар field-value. Посмотреть список всех полей можно так:</p>
38 127.0.0.1:6379&gt; hkeys address 1) "city"<p>А все значения можно посмотреть с помощью команды:</p>
38 127.0.0.1:6379&gt; hkeys address 1) "city"<p>А все значения можно посмотреть с помощью команды:</p>
39 127.0.0.1:6379&gt; hvals address 1) "Omsk"<p>Добавим другие поля с помощью множественного<em>"задания"</em>полей:</p>
39 127.0.0.1:6379&gt; hvals address 1) "Omsk"<p>Добавим другие поля с помощью множественного<em>"задания"</em>полей:</p>
40 127.0.0.1:6379&gt; hmset address street Lenina number 2 OK<p>Посмотрим, что получилось с помощью другой команды:</p>
40 127.0.0.1:6379&gt; hmset address street Lenina number 2 OK<p>Посмотрим, что получилось с помощью другой команды:</p>
41 127.0.0.1:6379&gt; hgetall address 1) "city" 2) "Omsk" 3) "street" 4) "Lenina" 5) "number" 6) "2"<p>Да, здесь имя поля и его значение следуют друг за другом. Вот таким образом можно хранить более привычные объекты в Redis. Примерно таким образом и будут храниться объекты репозиториев Spring Data Redis.</p>
41 127.0.0.1:6379&gt; hgetall address 1) "city" 2) "Omsk" 3) "street" 4) "Lenina" 5) "number" 6) "2"<p>Да, здесь имя поля и его значение следуют друг за другом. Вот таким образом можно хранить более привычные объекты в Redis. Примерно таким образом и будут храниться объекты репозиториев Spring Data Redis.</p>
42 <p>Вот мы и познакомились с консольным интерфейсом. В следующей части изучим, как подключаться к Redis с помощью Spring Data.</p>
42 <p>Вот мы и познакомились с консольным интерфейсом. В следующей части изучим, как подключаться к Redis с помощью Spring Data.</p>
43 <p><em>Есть вопрос? Напишите в комментариях!</em></p>
43 <p><em>Есть вопрос? Напишите в комментариях!</em></p>
44  
44