Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can someone explain redis setbit command?

Tags:

c

redis

> setbit mykey 1 1
> setbit mykey 7 1

When I store string value 1 and 7 into "mykey", what was exactly stored in redis? And how the getbit works inside redis?

Does anyone try to loop the bit inside this value? I know bitcount will give me number 2, but I also want to get the exact string value 1 and 7 from it, is it possible?

--

I doing some experiment by using erlang redis client to read the output.

> setbit mykey 1 1

erlang output:

<<"@">>

Then I delete this entry:

> del mykey

I do the same thing to offset 2 4 8, here you can see the mapping:

When offset is 1, the output is <<"@">>;
When offset is 2, the output is <<" ">>;
When offset is 4, the output is <<"\b">>;
When offset is 8, the output is <<0,128>>;

Honestly, I am more confused now.

Or someone can explain this "bitops.c"

-- updates ---

Maybe I should mention the reason why I want to do this to make the question more clear. We all know it will be cool to use bitmap to store online users. What I am trying to do is get the exactly user id who is online from what redis stored.

Just finished a quick version to extract offsets from redis. Please feel free to improve it.

like image 975
Joshua Avatar asked Dec 19 '13 03:12

Joshua


1 Answers

As its name implies, SETBIT allows you to perform bit operations - namely set a given bit to 0 or 1, at a given bit offset, for a given key.

What is important to understand is that the result not always includes only printable characters. This is why Redis uses a custom function sdscatrepr to format the CLI output:

Append to the sds string "s" an escaped string representation where all the non-printable characters (tested with isprint()) are turned into escapes in the form "\n\r\a...." or "\x".

That being said let's start with a simple example. If you consider the hex number 0x7F (= 127) its binary representation on 8-bit is:

pos: 0 1 2 3 4 5 6 7
bit: 0 1 1 1 1 1 1 1
     ^             ^
     |             |
     MSB           LSB

You can typically use SETBIT to store this value, keeping in mind that offset 0 is MSB and offset 7 is LSB:

redis> SETBIT myval 0 0
(integer) 0
redis> SETBIT myval 1 1
(integer) 0
redis> SETBIT myval 2 1
(integer) 0
redis> SETBIT myval 3 1
(integer) 0
redis> SETBIT myval 4 1
(integer) 0
redis> SETBIT myval 5 1
(integer) 0
redis> SETBIT myval 6 1
(integer) 0
redis> SETBIT myval 7 1
(integer) 0

The get your value to inspect if:

redis> GET myval
"\x7f"

Now what happens with multi bytes? Let's say you want to store 0x52 (= 82) which corresponds to character R in ASCII. The 8-bit representation is 01010010 with bit positions (8, 9, ..., 15) since we want it to be stored right after the first value:

redis> SETBIT myval 8 0
(integer) 0
redis> SETBIT myval 9 1
(integer) 0
redis> SETBIT myval 10 0
(integer) 0
redis> SETBIT myval 11 1
(integer) 0
redis> SETBIT myval 12 0
(integer) 0
redis> SETBIT myval 13 0
(integer) 0
redis> SETBIT myval 14 1
(integer) 0
redis> SETBIT myval 15 0
(integer) 0

And you get:

redis> GET myval
"\x7fR"

Here Redis CLI is able to represent the printable character R.

When I store string value 1 and 7 into "mykey"

It corresponds to 01000001 which is equal to 65 and 0x41 in hex. It corresponds to ASCII character A. So doing:

redis> SETBIT mykey 1 1
(integer) 0
redis> SETBIT mykey 7 1
(integer) 0

Gives:

redis> GET mykey
"A"

how the getbit works inside redis?

It simply returns the value of the bit at the given position. Here:

redis> GETBIT mykey 1
(integer) 1

But bit 0 has not been set (it is 0 by default) thus:

redis> GETBIT mykey 0
(integer) 0
like image 147
deltheil Avatar answered Sep 30 '22 01:09

deltheil