Значение или состояние, соответствующее элементу, представлено битом, а ключ — это сам соответствующий элемент. Битмапы сами по себе не являются структурой данных, на самом деле это строка (значение, соответствующее ключу, является последней строкой двоичного кода на приведенном выше рисунке), но он может работать с битами строки. Растровые изображения предоставляют отдельный набор команд, поэтому использование растровых изображений в Redis отличается от использования строк. Растровые изображения можно представить как массив битов.Каждая единица массива может хранить только 0 и 1. Нижний индекс массива называется смещением в растровых изображениях.
Растровые команды
SETBIT
Синтаксис: значение смещения ключа SETBIT
инструкция:
правильноkey
Сохраненное строковое значение, которое устанавливает или очищает бит по указанному смещению.
бит устанавливается или сбрасывается в зависимости отvalue
параметр, который может быть0
так же может быть1
.
когдаkey
Если он отсутствует, автоматически создается новое строковое значение.
Строка выращена, чтобы убедиться, что она можетvalue
Сохранить с указанным смещением. Когда строковое значение растягивается, пустая позиция начинается с0
заполнение.
offset
Аргумент должен быть больше или равен0
, менее 2^32 (битовая карта ограничена 512 МБ).
использовать большиеoffset
изSETBIT
С точки зрения эксплуатации выделение памяти может привести к блокировке сервера Redis.
возвращаемое значение:
Строковое значение указывает бит по смещению, которое было изначально сохранено.
Пример:
# SETBIT 会返回之前位的值(默认是 0)这里会生成 126 个位
coderknock> SETBIT testBit 125 1
(integer) 0
coderknock> SETBIT testBit 125 0
(integer) 1
coderknock> SETBIT testBit 125 1
(integer) 0
coderknock> GETBIT testBit 125
(integer) 1
coderknock> GETBIT testBit 100
(integer) 0
# SETBIT value 只能是 0 或者 1 二进制只能是0或者1
coderknock> SETBIT testBit 618 2
(error) ERR bit is not an integer or out of range
получить значение
GETBIT
Синтаксис: смещение ключа GETBIT
инструкция:
правильноkey
Сохраненное строковое значение получает бит с указанным смещением.
когдаoffset
больше, чем длина строкового значения, илиkey
Если он не существует, верните0
.
возвращаемое значение:
Строковое значение указывает бит по смещению.
Пример:
coderknock> EXISTS bit
(integer) 0
coderknock> SETBIT bit 125 1
(integer) 0
coderknock> GETBIT bit 125
(integer) 1
# 偏移量如果不存在则是0
coderknock> GETBIT bit 126
(integer) 0
# 可以看到 bit 本身也是个字符串
coderknock> GET bit
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 "
Получить количество битов в указанном диапазоне растровых изображений со значением 1
BITCOUNT
Синтаксис: запуск ключа BITCOUNT
инструкция:
Вычисляет заданную строку, для которой задано значение1
количество бит.
Как правило, будет учитываться вся заданная строка, если указать дополнительныеstart
илиend
параметр, который позволяет выполнять подсчет только определенных битов.
start
иend
установка параметров иGETRANGE
Команды аналогичны, и могут использоваться отрицательные значения: например-1
представляет последний байт,-2
Представляет собой второй на последний байт, и так далее.
несуществующийkey
рассматривается как пустая строка, поэтому для несуществующегоkey
провестиBITCOUNT
операция, результат0
.
возвращаемое значение:
установить как1
количество бит.
Пример:
# 此处的 bit 基于 GETBIT 示例的命令中的
coderknock> BITCOUNT bit
(integer) 1
# 计算 bit 中所有值为 1 的位的个数
coderknock> BITCOUNT bit
(integer) 1
coderknock> SETBIT bit 0 1
(integer) 0
coderknock> BITCOUNT bit
(integer) 2
# 计算指定位置 bit 中所有值为 1 的位的个数
coderknock> BITCOUNT bit 10 126
(integer) 1
Несколько операций с растровыми изображениями
BITOP
Синтаксис: BITOP-операция destkey key [key ...]
инструкция:
для одной или нескольких строк, содержащих двоичные битыkey
выполнить побитовую операцию и сохранить результат вdestkey
начальство.
operation
возможноAND
,OR
,NOT
,XOR
Любая из этих четырех операций:
BITOP AND destkey key [key ...]
, для одного или несколькихkey
Возьмите логическое объединение и сохраните результат вdestkey
.BITOP OR destkey key [key ...]
, для одного или несколькихkey
Выполните логическое ИЛИ и сохраните результат вdestkey
.BITOP XOR destkey key [key ...]
, для одного или несколькихkey
Возьмите логическое XOR и сохраните результат вdestkey
.BITOP NOT destkey key
, для данногоkey
Возьмите логическое отрицание и сохраните результат вdestkey
.
КромеNOT
В дополнение к операции, другие операции могут принимать один или несколькоkey
в качестве ввода.
Работа со строками разной длины
когдаBITOP
При работе с строками разных длин отсутствующая часть более короткой строки обрабатывается как0
.
пустойkey
Также рассматривается как содержащий0
последовательность строк.
возвращаемое значение:
Сохранить вdestkey
длина строки и вводkey
Он равен наибольшей длине строки.
Пример:
coderknock> SETBIT bits-1 0 1
(integer) 0
coderknock> SETBIT bits-1 3 1
(integer) 0
# bits-1 为 1001
coderknock> SETBIT bits-2 0 1
(integer) 0
coderknock> SETBIT bits-2 1 1
(integer) 0
coderknock> SETBIT bits-2 3 1
(integer) 0
# bits-2 为 1011
#bits-1 bits-2 做 并 操作
coderknock> BITOP AND and-result bits-1 bits-2
(integer) 1
coderknock> GETBIT and-result 0
(integer) 1
coderknock> GETBIT and-result 1
(integer) 0
coderknock> GETBIT and-result 2
(integer) 0
coderknock> GETBIT and-result 3
(integer) 1
#and-result 1001
#bits-1 bits-2 做 或 操作
coderknock> BITOP OR or-result bits-1 bits-2
(integer) 1
coderknock> GETBIT and-result 0
(integer) 1
coderknock> GETBIT and-result 1
(integer) 0
coderknock> GETBIT and-result 2
(integer) 0
coderknock> GETBIT and-result 3
(integer) 1
#or-result 1011
# 非 操作只能针对一个 key
coderknock> BITOP NOT not-result bits-1 bits-2
(error) ERR BITOP NOT must be called with a single source key.
coderknock> BITOP NOT not-result bits-1
(integer) 1
coderknock> GETBIT not-result 0
(integer) 0
coderknock> GETBIT not-result 1
(integer) 1
coderknock> GETBIT not-result 2
(integer) 1
coderknock> GETBIT not-result 3
(integer) 0
# not-result 0110
# 异或操作
coderknock> BITOP XOR xor-result bits-1 bits-2
(integer) 1
coderknock> GETBIT xor-result 0
(integer) 0
coderknock> GETBIT xor-result 1
(integer) 1
coderknock> GETBIT xor-result 2
(integer) 0
coderknock> GETBIT xor-result 3
(integer) 0
# xor-result 0010
BITOP
Сложность O (N).При работе с большими матрицами или статистикой больших объемов данных лучше всего назначать задачи подчиненным узлам, чтобы избежать блокировки главного узла.
Вычислить смещение первого значения в растровых изображениях
BITPOS
Доступно с версии 2.8.7.
временная сложность:НА).
Синтаксис: бит ключа BITPOS [начало][конец]
инструкция:
Возвращает первый бит в строке, для которой установлено значение 1 или 0.
Возвращает позицию, обрабатывая строку как массив байтов слева направо, причем первый подходящий элемент находится в позиции 0, второй — в позиции 8 и т. д.
GETBIT
иSETBIT
Аналогичная команда для управления байтовыми битами.
По умолчанию вся строка извлекается один раз, и только когда указаны начальный и конечный параметры (возможно указание начального и конечного битов), диапазон интерпретируется как диапазон байтов, а не последовательность битов. такstart=0
иend=2
Это относится к поиску в первых трех байтах.
Обратите внимание, что возвращаемые битовые позиции всегда отсчитываются от 0, даже если start используется для указания начального байта.
иGETRANGE
Как и команды, start и end также могут содержать отрицательные значения.Отрицательные значения будут отсчитываться от конца строки, -1 — это последний байт строки, -2 — предпоследний и так далее.
Несуществующий ключ будет рассматриваться как пустая строка.
возвращаемое значение:
Команда возвращает первый бит строки, для которой установлено значение 1 или 0.
Если мы ищем что-то, чей бит равен 1, в пустой строке или в 0-байтовой строке, результат вернет -1.
Если мы ищем значение в строке, где бит равен 0, а строка содержит только 1, возвращается первый пустой бит в крайнем правом углу строки. Если есть строка, значение которой равно трем байтам0xff
строка, затем командаBITPOS key 0
вернет 24, потому что биты 0-23 равны 1.
По сути, мы можем думать о строках как о бесконечном числе нулей справа.
Однако если вы используете указанные начальный и конечный диапазоны для поиска указанного значения, если в диапазоне нет соответствующего значения, результатом будет -1.
Пример:
redis> SET mykey "\xff\xf0\x00"
OK
redis> BITPOS mykey 0 # 查找字符串里面bit值为0的位置
(integer) 12
redis> SET mykey "\x00\xff\xf0"
OK
redis> BITPOS mykey 1 0 # 查找字符串里面bit值为1从第0个字节开始的位置
(integer) 8
redis> BITPOS mykey 1 2 # 查找字符串里面bit值为1从第2个字节(12)开始的位置
(integer) 16
redis> set mykey "\x00\x00\x00"
OK
redis> BITPOS mykey 1 # 查找字符串里面bit值为1的位置
(integer) -1
BITFIELD
Доступно с версии 3.2.0.
временная сложность:Сложность каждой подкоманды составляет O(1).
Синтаксис: ключ BITFIELD [смещение типа GET][значение смещения типа SET][приращение смещения типа INCRBY][OVERFLOW WRAP|SAT|FAIL]
инструкция:
BITFIELD key GET type offset INCRBY type offset increment
`BITFIELD` 命令可以将一个 Redis 字符串看作是一个由二进制位组成的数组, 并对这个数组中储存的长度不同的整数进行访问 (被储存的整数无需进行对齐)。 换句话说, 通过这个命令, 用户可以执行诸如 “对偏移量 1234 上的 5 位长有符号整数进行设置”、 “获取偏移量 4567 上的 31 位长无符号整数”等操作。 此外, `BITFIELD` 命令还可以对指定的整数执行加法操作和减法操作, 并且这些操作可以通过设置妥善地处理计算时出现的溢出情况。
BITFIELD
Команда может работать с несколькими битовыми диапазонами одновременно в одном вызове: она принимает последовательность операций для выполнения в качестве параметров и возвращает массив в качестве ответа, где каждый элемент массива является результатом соответствующей операции.
Например, следующая команда показывает, как добавить 8-разрядное целое число со знаком по смещению 100 и получить 4-разрядное целое число без знака по смещению 0:
coderknock> BITFIELD mykey INCRBY i8 100 1 GET u4 0
1) (integer) 1
2) (integer) 0
Уведомление:
использовать
GET
Подкоманда обращается к битам за пределами текущего диапазона строки (включая случай, когда ключ не существует), и значение дополнительных битов будет обработано как 0 .использовать
SET
подкоманда илиINCRBY
Доступ подкоманды к битам за пределами текущего диапазона строки приведет к расширению строки, а расширенная часть будет заполнена битами со значением 0. При расширении строки команда вычисляет минимальную длину, необходимую для выполнения операции, на основе самого дальнего двоичного разряда, доступного в данный момент в строке.
Поддерживаемые подкоманды и числовые типы
Ниже приведеныBITFIELD
Подкоманды, поддерживаемые командой:
GET <type> <offset>
-- Возвращает указанный диапазон двоичных битов.SET <type> <offset> <value>
- Устанавливает указанный диапазон двоичных разрядов и возвращает его старое значение.INCRBY <type> <offset> <increment>
- Выполняет операцию сложения в указанном диапазоне битов и возвращает его старое значение. Пользователи могутincrement
Отрицательные значения передаются в качестве параметров для реализации соответствующей операции вычитания.
В дополнение к вышеуказанным трем подкомандам есть также подкоманда, которая может изменитьINCRBY
Поведение подкоманд при возникновении условий переполнения:
OVERFLOW [WRAP|SAT|FAIL]
Когда установленное значение диапазона двоичных битов является целым числом, пользователь может добавить перед параметром типаi
для представления целых чисел со знаком или использованияu
для представления целых чисел без знака. Например, мы можем использоватьu8
для представления 8-битного целого числа без знака вы также можете использоватьi16
для представления 16-битного целого числа со знаком.
BITFIELD
Команда поддерживает максимум 64-битные целые числа со знаком и 63-битные целые числа без знака.Ограничение 63-битной длины целых чисел без знака вызвано тем, что протокол Redis в настоящее время не может возвращать 64-битные целые числа без знака.
Биты и смещения позиций
В команде битового диапазона у пользователя есть два способа установить смещение:
Если пользователь дает число без префикса, то это число указывает на смещение строки от нуля.
С другой стороны, если пользователь дает
#
Смещение префикса, затем команда будет использовать это смещение для умножения битовой длины числового типа, установленного для вычисления реального смещения.
Например, для следующей команды:
BITFIELD mystring SET i8 #0 100 i8 #1 200
команда будетmystring
внутри ключа, первыйi8
Значение длины в битах установлено равным100
, и поставить второйi8
Значение длины в битах установлено равным200
. Когда мы используем строковый ключ в качестве массива, и массив хранит все целые числа одинаковой длины, используйте#
Префиксы избавляют нас от необходимости вручную вычислять, где установлены биты.
контроль переполнения
Пользователи могут проходитьOVERFLOW
команду, наряду с тремя параметрами, показанными ниже, укажитеBITFIELD
Поведение команды при возникновении состояния переполнения или потери значимости при выполнении операции автоинкремента или автодекремента:
WRAP
: Используйте циклический метод для обработки условий переполнения для целых чисел со знаком и без знака. Для целых чисел без знака перенос похож на выполнение вычисления по модулю с использованием самого значения и наибольшего целого числа без знака, которое можно сохранить, что также является стандартным поведением в C. Для целых чисел со знаком переполнение приведет к пересчету числа из наименьшего отрицательного числа, а потеря значимости приведет к пересчету числа из наибольшего положительного числа. Например, если мы127
изi8
Добавьте единицу к целому числу, и вы получите результат-128
.SAT
: Используйте арифметику насыщения для обработки переполнения, то есть результатом вычисления потери значимости является наименьшее целочисленное значение, а результатом вычисления переполнения является наибольшее целочисленное значение. Например, если мы возьмем значение120
изi8
Целое выполняет сложение10
расчет, то результатом команды будетi8
Наибольшее целочисленное значение, которое может хранить тип127
. Напротив, еслиi8
Вычисление значения вызвало потерю значимости, то этоi8
значение будет установлено на-127
.FAIL
: в этом режиме команда откажется выполнять вычисления, которые могут привести к состоянию переполнения или потери значимости, и вернет пользователю нулевое значение, чтобы указать, что вычисление не было выполнено.
должны знать о том,OVERFLOW
Подкоманда будет выполнена только для той, которая выполняется сразу после нее.INCRBY
Команда имеет эффект, который длится до тех пор, пока с ней не будет выполнена следующая команда.OVERFLOW
до команды. По умолчанию,INCRBY
использование командыWRAP
Расчетные способы обработки переполнения.
Следующее является использованиемOVERFLOW
Примеры подкоманд для управления поведением при переполнении:
coderknock> BITFIELD mykey incrby u2 100 1 OVERFLOW SAT incrby u2 102 1
1) (integer) 1
2) (integer) 1
coderknock> BITFIELD mykey incrby u2 100 1 OVERFLOW SAT incrby u2 102 1
1) (integer) 2
2) (integer) 2
coderknock> BITFIELD mykey incrby u2 100 1 OVERFLOW SAT incrby u2 102 1
1) (integer) 3
2) (integer) 3
coderknock> BITFIELD mykey incrby u2 100 1 OVERFLOW SAT incrby u2 102 1
1) (integer) 0 -- 使用默认的 WRAP 方式处理溢出
2) (integer) 3 -- 使用 SAT 方式处理溢出
И следующее потому, чтоOVERFLOW FAIL
Пример поведения, при котором подкоманда возвращает нулевое значение:
coderknock> BITFIELD mykey OVERFLOW FAIL incrby u2 102 1
1) (nil)
эффект
BITFIELD
Роль команды заключается в том, что она может хранить множество небольших целых чисел в растровом изображении большой длины или делить очень большой ключ на несколько меньших ключей для хранения, чтобы очень эффективно использовать память, благодаря чему Redis можно использовать для многих различных целей. приложений — особенно в аналитике в реальном времени:BITFIELD
Возможность управления вычислительным переполнением заданным образом позволяет использовать его в этой области.
Вопросы производительности
BITFIELD
В общем, это быстрая команда, но следует отметить, что доступ к дальним битам короткой строки вызовет операцию выделения памяти, которая может занять больше времени, чем команда, выполняющая доступ к существующей строке.
расположение бит
BITFIELD
Считать бит со смещением 0 первого байта растрового изображения старшим битом и так далее. Например, если мы устанавливаем растровое изображение, которое было предварительно установлено на все 0, установите его значение по смещению 7 на 5-битное целое число без знака 23 (двоичные биты10111
), то команда создаст следующее растровое представление:
+--------+--------+
|00000001|01110000|
+--------+--------+
Когда смещение и целочисленная длина выравниваются по границам байтов,BITFIELD
Биты представлены так же, как и с обратным порядком байтов, но также важно понимать, как располагаются биты при отсутствии выравнивания.
возвращаемое значение:
еслиmember
элементы являются членами коллекции, возврат1
.
еслиmember
элемент не является членом множества, илиkey
не существует, верните0
.
Пример:
coderknock> SISMEMBER saddTest add1
(integer) 1
# add7 元素不存在
coderknock> SISMEMBER saddTest add7
(integer) 0
# key 不存在
coderknock> SISMEMBER nonSet a
(integer) 0
# key 类型不是集合
coderknock> SISMEMBER embstrKey a
(error) WRONGTYPE Operation against a key holding the wrong kind of value
кейс
Сценарий 1. Вход пользователя
Jedis redis = new Jedis("192.168.31.89",6379,100000);
//用户uid
String uid = "1";
String cacheKey = "sign_"+Integer.valueOf(uid);
//记录有uid的key
// $cacheKey = sprintf("sign_%d", $uid);
//开始有签到功能的日期
String startDate = "2017-01-01";
//今天的日期
String todayDate = "2017-01-21";
//计算offset(时间搓)
long startTime = dateParase(startDate,"yyyy-MM-dd").getTime();
long todayTime = dateParase(todayDate,"yyyy-MM-dd").getTime();
long offset = (long) Math.floor((todayTime - startTime) / 86400);
System.out.println("今天是第"+offset+"天");
//签到
//一年一个用户会占用多少空间呢?大约365/8=45.625个字节,好小,有木有被惊呆?
redis.setbit(cacheKey,offset,"1");
//查询签到情况
boolean bitStatus = redis.getbit(cacheKey, offset);
//判断是否已经签到
//计算总签到次数
long qdCount = redis.bitcount(cacheKey);
Сценарий 2: подсчет активных пользователей
Используйте время как cacheKey, тогда идентификатор пользователя смещается, если он был активен в этот день, установите его на 1
Поэтому, если я вычисляю активных пользователей определенного дня/месяца/года (на данный момент только один день в сети в течение статистического периода называется активным), пожалуйста, дайте следующую команду redis
Команда BITOP операция destkey key [клавиша ...]
Описание: выполнить побитовую операцию над одним или несколькими строковыми ключами, содержащими двоичные биты, и сохранить результат в destkey.
Описание: Команда BITOP поддерживает любую из четырех операций AND, OR, NOT, XOR.
Map<String,List<Integer>>dateActiveuser = new HashMap<>();
Jedis redis = new Jedis("192.168.31.89",6379,100000);
Integer[] temp01 = {1,2,3,4,5,6,7,8,9,10};
List<Integer>temp01List = new ArrayList<>();
Collections.addAll(temp01List,temp01);
dateActiveuser.put("2017-01-10",temp01List);
Integer[] temp02 = {1,2,3,4,5,6,7,8};
List<Integer>temp02List = new ArrayList<>();
Collections.addAll(temp02List,temp02);
dateActiveuser.put("2017-01-11",temp02List);
Integer[] temp03 = {1,2,3,4,5,6};
List<Integer>temp03List = new ArrayList<>();
Collections.addAll(temp03List,temp03);
dateActiveuser.put("2017-01-12",temp03List);
Integer[] temp04 = {1,4,5,6};
List<Integer>temp04List = new ArrayList<>();
Collections.addAll(temp04List,temp04);
dateActiveuser.put("2017-01-13",temp04List);
Integer[] temp05 = {1,4,5,6};
List<Integer>temp05List = new ArrayList<>();
Collections.addAll(temp05List,temp05);
dateActiveuser.put("2017-01-14",temp05List);
String date[] = {"2017-01-10","2017-01-11","2017-01-12","2017-01-13","2017-01-14"};
//测试数据放入redis中
for (int i=0;i<date.length;i++){
for (int j=0;j<dateActiveuser.get(date[i]).size();j++){
redis.setbit(date[i], dateActiveuser.get(date[i]).get(j), "1");
}
}
//bitOp
redis.bitop(BitOP.AND, "stat", "stat_2017-01-10", "stat_2017-01-11","stat_2017-01-12");
System.out.println("总活跃用户:"+redis.bitcount("stat"));
redis.bitop(BitOP.AND, "stat1", "stat_2017-01-10", "stat_2017-01-11","stat_2017-01-14");
System.out.println("总活跃用户:"+redis.bitcount("stat1"));
redis.bitop(BitOP.AND, "stat2", "stat_2017-01-10", "stat_2017-01-11");
System.out.println("总活跃用户:"+redis.bitcount("stat2"));