SETBIT key offset value

    Time complexity: O(1)

    Sets or clears the bit at offset in the string value stored at key.

    The bit is either set or cleared depending on value, which can be either 0 or 1.

    When key does not exist, a new string value is created. The string is grown to make sure it can hold a bit at offset. The offset argument is required to be greater than or equal to 0, and smaller than 232 (this limits bitmaps to 512MB). When the string at key is grown, added bits are set to 0.

    Warning: When setting the last possible bit (offset equal to 232 -1) and the string value stored at key does not yet hold a string value, or holds a small string value, Redis needs to allocate all intermediate memory which can block the server for some time. On a 2010 MacBook Pro, setting bit number 232 -1 (512MB allocation) takes ~300ms, setting bit number 230 -1 (128MB allocation) takes ~80ms, setting bit number 228 -1 (32MB allocation) takes ~30ms and setting bit number 226 -1 (8MB allocation) takes ~8ms. Note that once this first allocation is done, subsequent calls to SETBIT for the same key will not have the allocation overhead.

    redis> SETBIT mykey 7 1

    redis> SETBIT mykey 7 0

    1. (integer) 1

    redis> GET mykey

    redis>

    There are cases when you need to set all the bits of single bitmap at once, for example when initializing it to a default non-zero value. It is possible to do this with multiple calls to the command, one for each bit that needs to be set. However, so as an optimization you can use a single SET command to set the entire bitmap.

    Bitmaps are not an actual data type, but a set of bit-oriented operations defined on the String type (for more information refer to the ). This means that bitmaps can be used with string commands, and most importantly with SET and .

    For example, after setting a few bits, getting the string value of the bitmap would look like this:

    1. > SETBIT bitmapsarestrings 3 1
    2. > SETBIT bitmapsarestrings 5 1
    3. > SETBIT bitmapsarestrings 10 1
    4. > SETBIT bitmapsarestrings 11 1
    5. > SETBIT bitmapsarestrings 14 1
    6. > GET bitmapsarestrings
    7. "42"

    By getting the string representation of a bitmap, the client can then parse the response's bytes by extracting the bit values using native bit operations in its native programming language. Symmetrically, it is also possible to set an entire bitmap by performing the bits-to-bytes encoding in the client and calling SET with the resultant string.

    excels at setting single bits, and can be called several times when multiple bits need to be set. To optimize this operation you can replace multiple SETBIT calls with a single call to the variadic command and the use of fields of type u1.

    For example, the example above could be replaced by:

    It is also possible to use the GETRANGE and string commands to efficiently access a range of bit offsets in a bitmap. Below is a sample implementation in idiomatic Redis Lua scripting that can be run with the EVAL command:

    1. --[[
    2. Sets a bitmap range
    3. Bitmaps are stored as Strings in Redis. A range spans one or more bytes,
    4. so we can call [SETRANGE](/commands/setrange) when entire bytes need to be set instead of flipping
    5. individual bits. Also, to avoid multiple internal memory allocations in
    6. Redis, we traverse in reverse.
    7. Expected input:
    8. KEYS[1] - bitfield key
    9. ARGV[1] - start offset (0-based, inclusive)
    10. ARGV[3] - value (should be 0 or 1, no error checking)
    11. ]]--
    12. local function tobits(str)
    13. local r = ''
    14. for i = 1, string.len(str) do
    15. local c = string.byte(str, i)
    16. local b = ' '
    17. for j = 0, 7 do
    18. b = tostring(bit.band(c, 1)) .. b
    19. c = bit.rshift(c, 1)
    20. end
    21. r = r .. b
    22. end
    23. return r
    24. end
    25. -- Main
    26. local k = KEYS[1]
    27. local s, e, v = tonumber(ARGV[1]), tonumber(ARGV[2]), tonumber(ARGV[3])
    28. -- First treat the dangling bits in the last byte
    29. local ms, me = s % 8, (e + 1) % 8
    30. local t = math.max(e - me + 1, s)
    31. redis.call('SETBIT', k, i, v)
    32. end
    33. e = t
    34. end
    35. -- Then the danglings in the first byte
    36. if ms > 0 then
    37. local t = math.min(s - ms + 7, e)
    38. for i = s, t, 1 do
    39. redis.call('SETBIT', k, i, v)
    40. end
    41. s = t + 1
    42. end
    43. -- Set a range accordingly, if at all
    44. local rs, re = s / 8, (e + 1) / 8
    45. local rl = re - rs
    46. if rl > 0 then
    47. local b = '\255'
    48. if 0 == v then
    49. b = '\0'
    50. end
    51. end