【list】
- 栈:lpush + lpop
- 队列:lpush + rpop
- 消息队列:lpush + brpop
- 有限列表:lpush + ltrim
【list】List部分元素过期
在list中的每个元素用单独的kv存储,在kv上设置过期时间。list中只保存元素的key。
【set】
- 差集:sdiff
- 交集:sinter
- 并集:sunion
统计
【String,BitMap】使用 bitmap 实现用户上线次数统计
基于Redis位图实现系统用户登录统计 - BNDong - 博客园
【SETBIT/GETBIT/BITCOUNT/BITOP OR】
方法一【按人统计,一人一个key】
可求每个人的登录情况
设置用户1001,2017-10-25登录:SETBIT loginLog_2017-10_client_1001 25 1
获取用户1001,2017-10-25是否登录:GETBIT loginLog_2017-10_client_1001 25
获取用户1001,2017-10月是否登录:BITCOUNT loginLog_2017-10_client_1001
获取用户1001,2017-10/9/7月是否登录:BITOP OR stat loginLog_2017-10_client_1001 loginLog_2017-09_client_1001 loginLog_2017-07_client_1001…
方法二【按天统计,一天一个key】
可求按时间统计的人数
面试官: Redis 如何存储和计算一亿用户的活跃度 - V2EX
1 0000 0000/8/1024/1024=11.92M 每天
设置用户1001,2017-10-25登录:SETBIT 2017-10-25 1001 1
获取用户1001,2017-10-25是否登录:GETBIT 2017-10-25 1001
统计某一天的所有的活跃用户数:bitcount 2017-10-25
求出了 2019-01-01 到 2019-01-05 这段时间内的活跃用户数:bitop or result 2019-01-01 2019-01-02 2019-01-03 2019-01-04 2019-01-05
bitmap也可以做页面访问记录【做活动会用到】
【zset】使用 Redis 统计在线用户人数
使用 Redis 统计在线用户人数 - 笑笑别人 - 博客园
关于用 Redis 做在线人数统计 - V2EX
【HyperLogLog】大概统计页面访问
限流
【zset】简单限流
【zadd添加,zremrangebyscore 删除过期,zcard统计现存】
public class SimpleRateLimiter {
private Jedis jedis;
public SimpleRateLimiter(Jedis jedis) {
this.jedis = jedis;
}
public Boolean isActionAllowed(String userId, String actionKey, int period, int maxCount) {
String key = String.format("hist:%s:%s", userId, actionKey);
long nowTs = System.currentTimeMillis();
//pipeline就可以充当这种“批处理”的工具,主要是TCP连接中减少了“交互往返”的时间。
Pipeline pipe = jedis.pipelined();
pipe.multi();
pipe.zadd(key, nowTs, "" + nowTs);
//删除过期
//设置过期 还用删除么?
pipe.zremrangeByScore(key, 0, nowTs - period * 1000);
//删除之后统计数量
Response<long> count = pipe.zcard(key);
//设置过期时间
// 设置zset的过期时间,避免冷用户持续占用内存
//过期时间应该等于时间窗口长度,多宽限出1S
pipe.expire(key, period + 1);
pipe.exec();
pipe.close();
return count.get() <= maxCount;
}
public static void main(String[] args) {
Jedis jedis = new Jedis();
SimpleRateLimiter limiter = new SimpleRateLimiter(jedis);
for (int i=0;i<20;i++) {
System.out.println(limiter.isActionAllowed("laoqian", "reply", 60, 5));
}
}
}
【Redis-Cell】漏斗限流Redis-Cell
Redis 4.0 提供了一个限流 Redis 模块,它叫 redis-cell。
https://github.com/brandur/redis-cell
文章阅读量【同步数据库】
关于高并发下的阅读量,点赞量,评论量的实现方案总结 - 为何不可1995的个人空间 - OSCHINA - 中文开源技术交流社区
- 用缓存,定期同步
- 用hash,直接在hash上操作,定期同步
分布式锁
SET lock.foo 1 EXNX
1. 注意要设置过期时间
2. 解锁要验证value相等【要用lua脚本】
redisson
Redisson 分布式锁实现之源码篇 → 为什么推荐用 Redisson 客户端 - 云+社区 - 腾讯云redisson分布式锁为什么用hash
为了实现锁的可重入
续锁
定时任务实现锁续期订阅
普通情况:
获取锁失败就订阅锁channel,阻塞。锁释放会唤醒订阅线程。
意外终止,来不及发布订阅情况:
超时机制:
集群分布式锁算法RedLock
在各节点分别加锁,锁一半以上的获取锁。
问题:如果一个节点已经加锁,然后他挂了。他的slaveB被sentinel拉起当master。B中没有锁内容。怎么办。答:延迟重启。加入锁的有效时间是30s,那就30s之后再将slave变为master。
只能通过redlock解决。
redlock问题
redlock依赖时钟,时钟回拨,一个redis提前结束,会造成两个同时持有锁。
Redis RedLock 完美的分布式锁么? - 掘金