2

我对 Node.js 和 Redis 很陌生。我读了这篇文章,并想使用 bitset 来存储我的 Express.js 应用程序的所有用户信息,如本文所述:http: //blog.getspool.com/2011/11/29/fast-easy-实时指标使用redis位图/

我有点麻烦。在我的函数中,我获取当前的年、月和日期,然后使用 client.setbit() 设置适当的键和值。但是我怎么能数出所有的钥匙呢?我在 Redis 2.4* 上,BITCOUNT 命令在 2.6 中。还有其他方法吗?这篇文章使用了 Java 位集,所以这是另一回事。我不太明白。

例如,我如何使用 for 循环来计算所有设置为 1 的位?是否有任何操作来计算位集的大小,所以我可以这样做:

for (var i = initial_offset; i < bitset_length; i++){
    if (i == 1){
        total_users++;
    }
}

还是我以完全错误的方式去做?

4

1 回答 1

2

您需要计算存储在 Redis 中的给定字符串的位数。基本上有两种方法可以做到这一点:

  • 您可以尝试使用 Redis 2.6 和新的 BITCOUNT/BITOP 操作在服务器端执行此操作。

  • 您可以检索整个字符串(包含所有位)并在客户端处理数据。在原始文章中,作者检索 Redis 字符串并将其转换为可以应用位级算法的 Java 位集。相同的策略可以应用于任何客户端、任何语言:您只需要找到一个好的库来处理位数组,或者自己实现一个(这并不难)。它适用于 Redis 2.2 或更高版本。

一个不太有效的策略是在客户端迭代并通过执行 GETBIT 命令检查每个单独的位。这将是非常低效的。

使用 node.js,您可能希望使用以下一些资源来实现第二个选项:

Node.js 不是一个很好的环境来实现 CPU 消耗操作,但在最坏的情况下,如果你有非常大的位集,你仍然可以依赖从 Node.js 调用的高效 C++ 实现。你有一个很好的boost::dynamic_bitset

这是一个 Node.js 示例,其中包含一个非常简单(并且可能效率低下)的计数算法:

var redis = require('redis')
var rc = redis.createClient(6379, 'localhost', {return_buffers:true} );

var bitcnt = [ 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8]

function count(b)
{
  var cnt = 0
  for (i=0; i<b.length; ++i ) {
    cnt += bitcnt[ b[i] ]
  }
  return cnt
}

function fetch( callback )
{
  rc.get( 'mybitset', function(err,reply) {
     callback(reply)
  });
}

function fill( callback )
{
   rc.setbit( 'mybitset', 0, 1 )
   rc.setbit( 'mybitset', 10, 1 )
   rc.setbit( 'mybitset', 20, 1 )
   rc.setbit( 'mybitset', 60, 1, function(err,reply) {
      callback()
   });
}

rc.flushall( function(err,rr) {
   fill( function() {
      fetch( function(b) {
        console.log( "Count = ",count(b) );
      });
   })
})

请注意 {return_buffers:true} 选项用于确保 Redis 输出被处理为二进制数据(忽略可能的字符转换)。

于 2012-06-25T17:25:31.653 回答