Раздел 37 · Redis с нуля

Bitmaps: биты как данные

junior~20 мин

без входаВойди, чтобы отмечать прогресс, вести заметки и решать задачи в редакторе. войти

В прошлом уроке мы смотрели на Redis со стороны эксплуатации и считали память. Теперь возвращаемся к специальным структурам из обзора и разбираем их по одной. Первая из них самая экономная. Магазин хочет знать, сколько покупателей заходило сегодня, и кто из них был и вчера, и сегодня. Покупателей миллион. Хранить множество из миллиона идентификаторов на каждый день дорого, а ответ нужен простой: «был» или «не был».

Журнал посещаемости

Вспомни школьный журнал. По вертикали фамилии, по горизонтали дни. Учитель не пишет «Иванов присутствовал на уроке», он ставит точку в клетку. Строка Иванова всегда одна и та же, и чтобы узнать, был ли он в среду, достаточно найти нужную клетку.

Теперь переверни журнал: пусть на каждый день будет своя полоска клеток, а номер клетки совпадает с номером ученика. В клетке либо точка, либо пусто. Чтобы посчитать, сколько учеников было в среду, считаешь точки в полоске. Чтобы узнать, кто был и в среду, и в четверг, кладёшь две полоски рядом и смотришь, где точки стоят в обеих.

Каждая клетка такой полоски это один бит. Полоску бит, где номер бита что-то означает, называют битовой картой.

Строка как полоска бит

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

Пользователи 7, 3 и 12 зашли в магазин 10 октября:

127.0.0.1:6379> SETBIT active:2026-10-10 7 1
(integer) 0
127.0.0.1:6379> SETBIT active:2026-10-10 3 1
(integer) 0
127.0.0.1:6379> SETBIT active:2026-10-10 12 1
(integer) 0
127.0.0.1:6379> SETBIT active:2026-10-10 7 1
(integer) 1

SETBIT возвращает старое значение бита. Первые три раза там был 0. Когда пользователь 7 зашёл второй раз, команда ответила 1: он уже отмечен, ничего не изменилось. Если ключа не было, Redis создал его сам и заполнил нулями.

GETBIT читает один бит:

127.0.0.1:6379> GETBIT active:2026-10-10 7
(integer) 1
127.0.0.1:6379> GETBIT active:2026-10-10 5
(integer) 0
127.0.0.1:6379> GETBIT active:2026-10-10 100000
(integer) 0

Бит за пределами строки считается нулём, ошибки нет. Значение бита только 0 или 1: на SETBIT active:2026-10-10 7 2 Redis ответит (error) ERR bit is not an integer or out of range.

Раз это строка, её можно прочитать целиком:

127.0.0.1:6379> TYPE active:2026-10-10
string
127.0.0.1:6379> STRLEN active:2026-10-10
(integer) 2
127.0.0.1:6379> GET active:2026-10-10
"\x11\b"

Бит 12 лежит во втором байте, поэтому строка длиной 2 байта. redis-cli показывает байты так же, как кириллицу в уроке 4: первый байт 00010001 превратился в \x11, второй 00001000 в \b. Нумерация идёт слева направо: бит 0 это самый левый бит первого байта, поэтому биты 3 и 7 дали 00010001.

урок из курса

Урок из курса «Redis с нуля». Курс покупается один раз и остаётся навсегда: 500 ₽.

Оплата пока не подключена: премиум и курсы открываются промокодом.