redis-bitmap redis位图
实现原理:
就是字符串,字符数组
优点
1.节省空间,按位存的,比如记录用户登录次数,只需要365/8≈40多byte
2.设置时候时间复杂度O(1)、读取时候时间复杂度O(n),操作是非常快的。只要长度不长,读取是很快的.
注意事项
bitmap有位数限制,512m以内,on的读取复杂度,太长效率太差了.
bitcount key 0 0 这种情况只返回前8位的统计结果.
思考
使用方法(BITPOS 2.8.7可用,代码里面有使用例子)
127.0.0.1:6379> setbit test 100 1
(integer) 0
127.0.0.1:6379> setbit test 99 1
(integer) 0
127.0.0.1:6379> setbit test 98 0
(integer) 0
127.0.0.1:6379> setbit test 97 0
(integer) 0
127.0.0.1:6379> setbit test 96 1
(integer) 0
127.0.0.1:6379> getbit test 96
(integer) 1
127.0.0.1:6379> getbit test 95
(integer) 0
127.0.0.1:6379> getbit test 97
(integer) 0
127.0.0.1:6379> getbit test 98
(integer) 0
127.0.0.1:6379> getbit test 99
(integer) 1
127.0.0.1:6379> getbit test 100
(integer) 1
127.0.0.1:6379> bitcount test 0 -1
(integer) 3
案例:
1.用户签到
用户id作为key,value为签到的情况,1代表签到,0代表未签到.
//用户uid
String uid = "1";
String cacheKey = "sign_" + Integer.valueOf(uid);
//记录有uid的key
// $cacheKey = sprintf("sign_%d", $uid);
//开始有签到功能的日期
String startDate = "2017-01-01";
//今天的日期
String todayDate = "2017-01-21";
//计算offset(时间搓)
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
long startTime = format.parse(startDate).getTime();
long todayTime = format.parse(startDate).getTime();
long offset = (long) Math.floor((todayTime - startTime) / 86400);
System.out.println("今天是第" + offset + "天");
//签到
//一年一个用户会占用多少空间呢?大约365/8=45.625个字节,好小,有木有被惊呆?
jedis.setbit(cacheKey, offset, "1");
//查询签到情况
boolean bitStatus = jedis.getbit(cacheKey, offset);
//判断是否已经签到
//计算总签到次数
long qdCount = jedis.bitcount(cacheKey);
2.统计活跃用户数:
每天当天的日期作为key,当天的活跃用户作为offset,value设置成1,为bitcount做准备.
通过bitcount 统计value的数量,就可以知道当天活跃用户数了.
如果 是几天的活跃用户数,那么 可以用bittop 命令 合并结果.
Map>dateActiveuser = new HashMap<>();
Integer[] temp01 = {1,2,3,4,5,6,7,8,9,10};
Listtemp01List = new ArrayList<>();
Collections.addAll(temp01List,temp01);
dateActiveuser.put("2017-01-10",temp01List);
Integer[] temp02 = {1,2,3,4,5,6,7,8};
Listtemp02List = new ArrayList<>();
Collections.addAll(temp02List,temp02);
dateActiveuser.put("2017-01-11",temp02List);
Integer[] temp03 = {1,2,3,4,5,6};
Listtemp03List = new ArrayList<>();
Collections.addAll(temp03List,temp03);
dateActiveuser.put("2017-01-12",temp03List);
Integer[] temp04 = {1,4,5,6};
Listtemp04List = new ArrayList<>();
Collections.addAll(temp04List,temp04);
dateActiveuser.put("2017-01-13",temp04List);
Integer[] temp05 = {1,4,5,6};
Listtemp05List = new ArrayList<>();
Collections.addAll(temp05List,temp05);
dateActiveuser.put("2017-01-14",temp05List);
String date[] = {"2017-01-10","2017-01-11","2017-01-12","2017-01-13","2017-01-14"};
//测试数据放入redis中
for (int i=0;i