Spec-Zone.ru › Redis

УСТАНОВИТЬ_БИТ

SETBIT
Синтаксис
SETBIT key offset value
Доступно с версии:
2.2.0
Сложность по времени:
O(1)
Категории ACL:
@write, @bitmap, @slow,

Устанавливает или сбрасывает бит по смещению в строковом значении, хранящемся по ключу.

Бит устанавливается или сбрасывается в зависимости от значения, которое может быть 0 или 1.

Если ключ не существует, создаётся новое строковое значение. Строка увеличивается, чтобы гарантировать возможность хранения бита по смещению. Аргумент смещение должен быть больше или равен 0 и меньше 232 (это ограничивает битовые карты до 512 МБ). При увеличении строки добавленные биты устанавливаются в 0.

Предупреждение: При установке последнего возможного бита (смещение равно 232 - 1) и строковое значение, хранящееся по ключу, ещё не содержит значения строки или содержит небольшое строковое значение, Redis необходимо выделить всю промежуточную память, что может заблокировать сервер на некоторое время. На 2010 MacBook Pro установка бита номер 232 - 1 (выделение 512 МБ) занимает ~300 мс, установка бита номер 230 - 1 (выделение 128 МБ) занимает ~80 мс, установка бита номер 228 - 1 (выделение 32 МБ) занимает ~30 мс, а установка бита номер 226 - 1 (выделение 8 МБ) занимает ~8 мс. Обратите внимание, что после того, как это начальное выделение памяти выполнено, последующие вызовы SETBIT для того же ключа не будут иметь накладных расходов на выделение памяти.

Возврат

Целочисленный ответ: исходное значение бита, хранящееся по смещению.

Примеры

SETBIT mykey 7 1
SETBIT mykey 7 0
GET mykey

Шаблон: доступ к всей битовой карте

В некоторых случаях необходимо установить все биты единственной битовой карты сразу, например, при её инициализации по умолчанию ненулевым значением. Это можно сделать с помощью нескольких вызовов команды SETBIT, по одному для каждого бита, который нужно установить. Однако в качестве оптимизации можно использовать одну команду SET для установки всей битовой карты.

Битовые карты не являются фактическим типом данных, а представляют собой набор операций, ориентированных на биты, определённых для типа данных «Строка» (для получения дополнительной информации см. раздел «Битовые карты» в документе «Введение в типы данных» https://redis.io/topics/data-types-intro#bitmaps). Это означает, что битовые карты могут использоваться с командами для строк, и, что самое главное, с командами SET и GET.

Поскольку строки Redis являются безопасными для двоичных данных, битовая карта тривиально кодируется как поток байтов. Первый байт строки соответствует смещениям 0..7 битовой карты, второй байт — диапазону 8..15 и так далее.

Например, после установки нескольких битов получение строкового значения битовой карты будет выглядеть следующим образом:

> SETBIT bitmapsarestrings 2 1
> SETBIT bitmapsarestrings 3 1
> SETBIT bitmapsarestrings 5 1
> SETBIT bitmapsarestrings 10 1
> SETBIT bitmapsarestrings 11 1
> SETBIT bitmapsarestrings 14 1
> GET bitmapsarestrings
"42"

Получив строковое представление битовой карты, клиент может затем разобрать ответные байты, извлекая значения битов с помощью собственных битовых операций в своём собственном языке программирования. Аналогично, также возможно установить всю битовую карту, выполнив кодирование битов в байты в клиенте и вызвав SET со полученной строкой.

Шаблон: установка нескольких битов

SETBIT отлично подходит для установки отдельных битов и может вызываться несколько раз, когда нужно установить несколько битов. Для оптимизации этой операции можно заменить несколько вызовов SETBIT одним вызовом многоаргументной команды BITFIELD и использованием полей типа u1.

Например, пример выше можно заменить на:

> BITFIELD bitsinabitmap SET u1 2 1 SET u1 3 1 SET u1 5 1 SET u1 10 1 SET u1 11 1 SET u1 14 1

Расширенный шаблон: доступ к диапазонам битовой карты

Также можно использовать команды строк GETRANGE и SETRANGE для эффективного доступа к диапазону битовых смещений в битовой карте. Ниже приведён пример реализации на языке сценариев Lua для Redis, которая может быть запущена с помощью команды EVAL:

--[[
Sets a bitmap range

Bitmaps are stored as Strings in Redis. A range spans one or more bytes,
so we can call [`SETRANGE`](/commands/setrange) when entire bytes need to be set instead of flipping
individual bits. Also, to avoid multiple internal memory allocations in
Redis, we traverse in reverse.
Expected input:
  KEYS[1] - bitfield key
  ARGV[1] - start offset (0-based, inclusive)
  ARGV[2] - end offset (same, should be bigger than start, no error checking)
  ARGV[3] - value (should be 0 or 1, no error checking)
]]--

-- A helper function to stringify a binary string to semi-binary format
local function tobits(str)
  local r = ''
  for i = 1, string.len(str) do
    local c = string.byte(str, i)
    local b = ' '
    for j = 0, 7 do
      b = tostring(bit.band(c, 1)) .. b
      c = bit.rshift(c, 1)
    end
    r = r .. b
  end
  return r
end

-- Main
local k = KEYS[1]
local s, e, v = tonumber(ARGV[1]), tonumber(ARGV[2]), tonumber(ARGV[3])

-- First treat the dangling bits in the last byte
local ms, me = s % 8, (e + 1) % 8
if me > 0 then
  local t = math.max(e - me + 1, s)
  for i = e, t, -1 do
    redis.call('SETBIT', k, i, v)
  end
  e = t
end

-- Then the danglings in the first byte
if ms > 0 then
  local t = math.min(s - ms + 7, e)
  for i = s, t, 1 do
    redis.call('SETBIT', k, i, v)
  end
  s = t + 1
end

-- Set a range accordingly, if at all
local rs, re = s / 8, (e + 1) / 8
local rl = re - rs
if rl > 0 then
  local b = '\255'
  if 0 == v then
    b = '\0'
  end
  redis.call('SETRANGE', k, rs, string.rep(b, rl))
end

Примечание: реализация для получения диапазона битовых смещений из битовой карты оставлена как упражнение для читателя.

© 2006–2022 Salvatore Sanfilippo
Licensed under the Creative Commons Attribution-ShareAlike License 4.0.
https://redis.io/commands/setbit/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API