redis源码阅读之bitops

2070阅读 0评论2019-05-02 stolennnxb
分类:NOSQL

今天5.1第二天,来讲讲redis当中的bit操作,首先,先简单介绍以下redis当中的位操作的命令
命令 解释
SETBIT key offset 0|1 将key存储的值的对应的二进制位设置为0或者1
GETBIT key offset 将key存储的值的对应的二进制位的值返回
BITCOUNT key 统计key存储的值当中,二进制位当中1的个数
BITOP AND|OR|XOR|NOT destkey srckey1 srckey2 ... srckeyn 将多组key中存储的值按照选项操作,操作的结果存储在destkey当中

其中key对应的值的存储方式是redis当中的sds字符串
在实际操作当中,redis会把存储的sds字符串当做二进制数组,但是实际保存位数组的顺序和书写数组的顺序是相反的,如下

所以根据输入的offset在相应的sds当中找到对应的位的计算方式也就出来了
idx_of_byte = [offset / 8]
idx_of_bit = [offset mod 8] + 1
这里仅列出set操作的代码:

点击(此处)折叠或打开

  1. /* SETBIT key offset bitvalue */
  2. void setbitCommand(client *c) {
  3.     robj *o;
  4.     char *err = "bit is not an integer or out of range";
  5.     size_t bitoffset;
  6.     ssize_t byte, bit;
  7.     int byteval, bitval;
  8.     long on;

  9.     if (getBitOffsetFromArgument(c,c->argv[2],&bitoffset,0,0) != C_OK)
  10.         return;

  11.     if (getLongFromObjectOrReply(c,c->argv[3],&on,err) != C_OK)
  12.         return;

  13.     /* Bits can only be set or cleared... */
  14.     if (on & ~1) {
  15.         addReplyError(c,err);
  16.         return;
  17.     }

  18.     if ((o = lookupStringForBitCommand(c,bitoffset)) == NULL) return;

  19.     /* Get current values */
  20.     byte = bitoffset >> 3;
  21.     byteval = ((uint8_t*)o->ptr)[byte];
  22.     bit = 7 - (bitoffset & 0x7);
  23.     bitval = byteval & (1 << bit);

  24.     /* Update byte with new bit value and return original value */
  25.     byteval &= ~(1 << bit);
  26.     byteval |= ((on & 0x1) << bit);
  27.     ((uint8_t*)o->ptr)[byte] = byteval;
  28.     signalModifiedKey(c->db,c->argv[1]);
  29.     notifyKeyspaceEvent(NOTIFY_STRING,"setbit",c->argv[1],c->db->id);
  30.     server.dirty++;
  31.     addReply(c, bitval ? shared.cone : shared.czero);
  32. }

其余的操作就非常类似了,就不再贴出来了~
上一篇:redis源码阅读之bio
下一篇:redis源码阅读之bitfieldop