Redis基础和应用(二)
1.2 分布式锁
==原子操作==是指不回被线程调度机制打断的操作。这种操作一旦开始,就会一直运行到结束,中间不会有任何线程切换。
Redis的分布式锁不能解决超时问题,锁在任务执行结束前就释放了,另一个线程提前重新持有了这把锁,导致任务无法严格串行执行。为了避免这种问题,建议Redis分布式锁不用用于较长时间的任务。
如果客户端在处理请求时加锁失败怎么办?一般有以下三种策略:
- 直接抛出异常,通知用户稍后重试
- sleep一会儿,然后再重试
- 将请求转移至延时队列,过一会再试
1.3 延时队列
Redis的list数据结构常用来作为异步消息队列使用,用rpush
和lpush
操作入队列,用lpop
和rpop
操作出队列。它可以支持多个生产者和多个消费者并发进出消息,每个消费者拿的消息都是不同的列表元素。
延时队列可以通关Redis的zset来实现。
1.4 位图
位图的最小单位是比特(bit),每个bit的取值只能是0或1。
Redis的位数组是自动扩展的,如果设置了某个偏移位置超出了数组长度,就会自动将位数组进行零扩充。
Redis提供了位图统计指令bitcount和位图查找指令bitpos。bitcount用来统计指定位置范围内1的个数,bitpos用来查找指定范围内出现的第一个0或1。
1.5 HyperLogLog
Redis提供的HyperLogLog数据结构可用来解决UV统计问题。HyperLogLog提供不精确的去重技术方案,标准误差率0.81%。
HyperLogLog提供了两个指令pfadd
和pfcount
,pfadd
是增加计数,pfcount
获取计数。
pubclic class pfTest{
public static void main(String[] args){
Jedis jedis = new Jedis();
for (int i = 0; i < 1000; i++){
jedis.pfadd("holle", "user" + i);
long total = jedis.pfcount("holle");
if (total != i + 1){
System.out.printf("%d %d\n", total, i + 1);
break;
}
}
jedis.close();
}
}
HyperLogLog还提供了pfmerge
,用于将多个pf计数值累加在一起形成一个新的pf值。
HyperLogLog需要占据12KB的存储空间,所以不适合统计单个用户相关的数据。