1、需求:我们需要生成一个产品对应商品的二维码,并且每个商品的二维码不一样
比如可以是 :http://xxx.xx.xx.com?param=aaa_bbb_random(number)
; 然后扫码请求后,可以获取一定的奖励,但是这个奖励只有一次。
2、redis bitmap 数据结构解决问题
如1中,所述的param参数,如果你要用数据库进行记录,比如一个产品,生成100万个商品的二维码,首先,数据库肯定是可以实现的。但是时间成本非常高。
因为我们的这个param参数,只需要确认是否存在于我们自己生成的,而且是否被扫过。这个时候,bitMap的作用就非常方便了。
3、展示下工具类
pom文件
<!-- SpringBoot Boot Redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
工具类
public class RedisService
{
@Autowired
public RedisTemplate redisTemplate;
/**
* 设置位图数据
* @param key 键
* @param offset
* @param bool
*/
public Boolean setBit(String key, long offset, boolean bool){
return redisTemplate.opsForValue().setBit(key, offset, bool);
}
/**
* 返回位图数据
* @param key 键
* @param id
*/
public Boolean getBit(String key, long offset){
return redisTemplate.opsForValue().getBit(key, offset);
}
/**
* bitCount 统计值对应位为1的数量
* @param key redis key
*/
public Long bitCount(String key) {
return (Long) redisTemplate.execute((RedisCallback<Long>) con -> con.bitCount(key.getBytes()));
}
}
4、注意点
有朋友可能有疑问,这个bitmap操作,偏移量 offset 不能为负数,而我们的param又是字符串,怎么存储在bitmap数据结构中。
//目前的做法是 通过与运算处理:解决hashCode为负数时,而bitmap的偏移量offset必须大于0
offset = paramStr.hashCode() & Integer.MAX_VALUE
//初始化:未被扫码
redisService.setBit(cacheKey, offset , false);
//已扫码:
redisService.setBit(cacheKey, offset , true);
//统计被扫码个数 (值为true的个数)
redisService.bitCount(cacheKey);
5、小结
bitmap 这个数据结构,目前是解决当前场景,比较合适的数据结构,优点:存储空间,增长到256M,不会再变了。统计和读写速度非常快。因为不是设置为0就是1。 二进制存储。