redis有哪些用途
- 键值对缓存,支持设置过期时间:
- 可以用来缓存跨进程session
- 可以缓存结果数据,例如查询结果,页面结果等
- …
- 排名: 通过无序集合实现
- 队列: 通过列表实现
- 分布式锁:setnx key value. 当键不存在时,才能成功,若键存在,什么也不做,成功返回1,失败返回0
- …
redis支持的数据结构, 以及常用命令
- 键值对: set [key] [val], get [key], del [key], expire [key]
- hash表: hset [mapname] [key] [val], hdel [mapname] [key], hget [mapname] [key], hkeys [mapname]
- list列表: rpush [key] [val], rpop [key], lpush [key] [val], lpop [key], llen [key]
- set无序集合: sadd [setname] [key], srem [setname] [key], sismember [setname] [key]
- sorted set有序集合: zadd [setname] [source] [key], zrang [setname] [sourcefrom] [sourceto] withscores, zrem [setname] [key]
- pub/sub消息通道:
- …
redis底层结构
- string:动态字符串
- ziplist:就是一个数组
- quicklist 链表,但是节点是 ziplist
- skiplist 跳表. 就是链表为了减少查找次数,向上产生多层,上一层一定比下一层小(每次随机决定是否向上加一层),这样就可以减少搜索次数,快速定位。且链表是有序的,所以一般用于有序结构。性能媲美红黑树
- zipmap 键值相邻,顺序查找。没什么用的结构
- dict 字典,也就是hashmap
redis的持久化策略
- rdb:
- bgsave命令: fork一个子进程写入文件
- save命令:当前进程写入磁盘,单线程阻塞请求
- aof: 以日志的形式记录服务器所处理的每一个写、删除操作
rdb备份快,恢复快,但是发生错误的时候丢失大。
aof丢失风险低,但是严重降低ops
redis分布式锁如何防止死锁
- 锁添加过期事件,因为添加一个命令后不再是原子操作,所以可以使用lua脚本进行原子化操作
redis分布式集群方案
- 主从复制模式:主机进程写入,复制(先尝试增量同步,不成功则全量同步)到从进程读取,读写分离。需要手动切换主从
- 哨兵模式:类似于守护进程,通过命令监控主进程是否正常,并通过发布订阅完成切换
- Cluster模式:数据分片,分布式存储
redis为什么快
- 单线程无锁
- 多路复用IO
内存淘汰机制
当Redis所用内存达到maxmeory上限时,会触发相应的溢出控制策略
- noeviction:当内存不足以容纳新写入数据时,新写入操作会报错。
- allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key。
- allkeys-lfu策略:使用LFU算法在所有数据中进行筛选并删除数据。
- allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个key。
- volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的key。
- volatile-lfu策略:使用LFU算法筛选设置了过期时间的键值对,进行删除。
- volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个key。
- volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的key优先移除。
分布式缓存设计注意事项
- 阻塞问题: redis是单线程,如果某个命令执行时间过长,那么就必然造成其他命令的阻塞;避免一次行获取过多,操作过多
- 缓存穿透: 缓存穿透是指查询一个根本不存在的数据,直接全部打到了数据库。解决:缓存空对象,布隆过滤器拦截(hash过滤)
- 缓存击穿: 底层数据库有数据而缓存内没有数据。也就说在数据加载过程或者恰好失效的时候中请求大量到来。解决:延长热点key的过期时间或者设置永不过期,或者逻辑上加锁,顺序访问
- 缓存雪崩: 大面积失效,导致全部走到了db。解决: 设置随机过期时间,热点设置永不过期
- 缓存一致性: 根据业务,单方面信任一方数据,然后优先更新这部分的数据。
redis ZRANK 底层涉及到哪些结构
主要依赖结构:
1. 跳跃表:维护有序集合中成员的有序排列
2. 哈希表: 存储成员到分值的映射关系
这种双结构设计既保证了O(1)的成员存在性检查,又实现了O(logN)的排名查询效率。
排名计算:在查找过程中累加各层的跨度值, 注意是通过跨度值进行的获取排名