利用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);
}
}
复制代码
如下: 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);
}
}
复制代码
相关文章推荐
- Redis 3.0官方文档翻译计划(2) ——从入门到精通(上)
- Redis 3.0官方文档翻译计划(3) ——从入门到精通(中)
- Redis 3.0官方文档翻译计划(4) ——从入门到精通(下)
- Redis 3.0官方文档翻译计划(1) ——Redis介绍
- redis + Jedis
- 基于zookeeper的redis高可用
- redis删除数据后内存释放问题
- Windows下安装并设置Redis
- shell 例程 —— 解决redis读取稳定性
- 为Symfony2和Redis正名,基于PHP的10亿请求/周网站打造
- redis加mybatis,org.apache.commons.pool2.impl.GenericObjectPoolConfig记住这个是pool2!!
- Redis 集群解决方案 Codis
- 基于Redis实现分布式锁
- redis数据丢失及解决
- Redis命令小细节
- Redis学习笔记---安装
- redis 五种数据类型的使用场景
- Redis缓存
- Redis基本认识
- windows下安装php5.5的redis扩展