您的位置:首页 > 数据库 > Redis

利用Redis BitMap 统计用户活跃指标

2015-07-22 16:00 656 查看
bitMap原理 :

如下: index 从 0 到 9 ,依次对应到一个bit位上,如果index 代表用户id,bit位上的0 1分表 代表用户是否登录;

1 0 1 1 0 1 1 0 1 1

0 1 2 3 4 5 6 7 8 9

复制代码

redis数据结构中 string 类型,包含了对bitmap的实现;在redis-cli中,可以通过setbit getbit 来对bit进行操作;本文通过jedis来对redis进行操作;

BitSet工具类:实现对通过jedis.get(key)取出的byte[]值与BitSet的转换

public class BitSetUtils {

/**

* 将BitSet对象转化为ByteArray

* @param bitSet

* @return

*/

public static byte[] bitSet2ByteArray(BitSet bitSet) {

byte[] bytes = new byte[bitSet.size() / 8];

for (int i = 0; i < bitSet.size(); i++) {

int index = i / 8;

int offset = 7 - i % 8;

bytes[index] |= (bitSet.get(i) ? 1 : 0) << offset;

}

return bytes;

}

/**

*

* @param bytes

* @return

*/

public static BitSet byteArray2BitSet(byte[] bytes) {

BitSet bitSet = new BitSet(bytes.length * 8);

int index = 0;

for (int i = 0; i < bytes.length; i++) {

for (int j = 7; j >= 0; j--) {

bitSet.set(index++, (bytes[i] & (1 << j)) >> j == 1 ? true

: false);

}

}

return bitSet;

}

}

复制代码

具体对java中BitSet操作,见/article/2176198.html ,该篇对bitSet用法介绍很详细;

redis工具类:

public class RedisUtil {

static {

initPool();

}

private static volatile JedisPool jedisPool;

private static ResourceBundle resourceBundle;

public static Jedis getResource() {

return jedisPool.getResource();

}

public static void returnResource(Jedis jedis) {

jedisPool.returnResource(jedis);

}

public static void initPool() {

if(jedisPool != null){

return;

}

loadProperties();

String host = resourceBundle.getString("redis.host");

String passwd= resourceBundle.getString("redis.passwd");

int port = Integer.parseInt(resourceBundle.getString("redis.port"));

JedisPoolConfig config = config();

jedisPool = new JedisPool(config,host,port,60,passwd);

}

private static void loadProperties() {

resourceBundle = ResourceBundle.getBundle("config/redis-config");

}

private static JedisPoolConfig config() {

JedisPoolConfig config = new JedisPoolConfig();

return config;

}

public static void main(String[]args){

Jedis jedis= RedisUtil.getResource();

RedisUtil.returnResource(jedis);

}

}

复制代码

1 统计系统中某天用户登录的情况:以当天日期做为key ,比如 ‘20150410’ ,对应的 bitMap 的 index 用userId来标示,UserId这里用 long 型表示,如果id不是以0开头,可以加上相应的偏移量就OK了;如果该天用户登录,调用activeUser方法,来更改bitMap相应index上的标示;

public void activeUser(long userId, String dateKey) {

Jedis jedis= RedisUtil.getResource();

try{

jedis.setbit(dateKey,userId,true);

}finally {

RedisUtil.returnResource(jedis);

}

}

复制代码

如果我们想统计该天用户登录的数量,及登录的用户id,可以通过如下方法实现:

//该天用户总数

public long totalCount(String dateKey) {

Jedis jedis= RedisUtil.getResource();

try{

return jedis.bitcount(dateKey);

}finally {

RedisUtil.returnResource(jedis);

}

}

复制代码

//该天登录所有的用户id

public List<Long> activeUserIds(String dateKey) {

Jedis jedis= RedisUtil.getResource();

try{

if(jedis.get(key)==null){

return null;

}

BitSet set= BitSetUtils.byteArray2BitSet(jedis.get(key).getBytes());

List<Long>list=new ArrayList<Long>();

for (long i=0;i<set.size();i++){

if(set.get(i)){

list.add(i);

}

}

return list;

}finally {

RedisUtil.returnResource(jedis);

}

}

复制代码

2 如果我们想统计n天,连续登录的用户数,及UserId:

public List<Long> continueActiveUserCount(String... dateKeys) {

Jedis jedis= RedisUtil.getResource();

try{

BitSet all = null;

for (String key:dateKeys){

if(jedis.get(key)==null){

continue;

}

BitSet set= BitSetUtils.byteArray2BitSet(jedis.get(key).getBytes());

if(all==null){

all=set;

}

System.out.println(set.size());

all.and(set);

}

List<Long>list=new ArrayList<Long>();

for (long i=0;i<all.size();i++){

if(all.get(i)){

list.add(i);

}

}

return list;

}finally {

RedisUtil.returnResource(jedis);

}

}

复制代码
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: