看到比较早的一篇用redis bit来实现用户统计的文章,照着用C#实现了一下,记录一下过程。
关于bit操作的解释,请参考上面文章。
说明
Redis里关于bit操作有下面命令:
- BITCOUNT key [start end], Count set bits in a string
- BITOP operation destkey key [key …], Perform bitwise operations between strings
- BITPOS key bit [start] [end], Find first bit set or clear in a string
- GETBIT key offset, Returns the bit value at offset in the string value stored at key
- SETBIT key offset value, Sets or clears the bit at offset in the string value stored at key
这里主要依赖SETBIT/BITOP/BITCOUNT
几个命令来操作。
代码实现
直接上代码:class Program
{
static void Main(string[] args)
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
var random = new Random();
LogLogin(random.Next(1000, 999999)); // fake customer number
LogLogin(random.Next(1000, 999999)); // fake customer number
LogLogin(random.Next(1000, 999999));
Console.WriteLine("we totally have {0} actives users today.", getTodayActiveUserCount());
stopwatch.Stop();
Console.WriteLine("Time elapsed: {0}", stopwatch.Elapsed);
Console.ReadKey();
}
public static void LogLogin(int customerNumber)
{
using (var client = new PooledRedisClientManager("192.168.1.181"))
using (var redis = (RedisNativeClient)client.GetClient())
{
redis.SetBit(string.Format("user-logon-activities:{0:yyyy-MM-dd}", DateTime.Now), customerNumber, 1);
}
}
public static int getTodayActiveUserCount()
{
using (var client = new PooledRedisClientManager("192.168.1.181"))
using (var redis = (RedisNativeClient)client.GetClient())
{
return (int)redis.BitCount(string.Format("user-logon-activities:{0:yyyy-MM-dd}", DateTime.Now));
}
}
}
这里,代码使用了servicestack.redis
类库,请通过nuget添加引用。
在redis里定义了一组以格式为user-logon-activities:{yyyy-MM-dd}
定义的key,如:'user-logon-activities:2016-01-26'
, 在id为1234的customer登陆时,会执行redis命令`setbit ‘user-logon-activities:2016-01-26’ 1234 1`来标示这个customer在2016-01-26登陆过。
在统计具体2016-01-26日多少个客人登陆过,可以简单使用bitcount 'user-logon-activities:2016-01-26'
即可。
同样,可以通过redis的bitop来进行位操作来统计来对多日的数据进行统计,如:
连续两天内总的登陆用户数:
bitop or 'user-logon-activities:2016-01:25-26' 'user-logon-activities:2016-01-26' 'user-logon-activities:2016-01-25' bitcount 'user-logon-activities:2016-01:25-26'
连续两天内都登陆过的用户数:
bitop and 'user-logon-activities:2016-01:25-26' 'user-logon-activities:2016-01-26' 'user-logon-activities:2016-01-25' bitcount 'user-logon-activities:2016-01:25-26'
PS: ServiceStack.Redis 的RedisNativeClient暂时不支持bitop操作,不过可以通过在后端通过redis command预处理数据的方式来操作。