快
- 纯内存操作。
- 核心是基于非阻塞的 IO 多路复用机制。是linux 多路复用机制 反应器模式 单线程的一个典型案例.
- 单线程反而避免了多线程的频繁上下文切换问题,预防了多线程可能产生的竞争问题。
- C 语言实现,一般来说,C 语言实现的程序“距离”操作系统更近,执行速度相对会更快。
官方网站也有,普通笔记本轻松处理每秒几十万的请求。 - 而且单线程并不代表就慢, nginx 和 node.js 也都是高性能单线程的代表。
数据类型
字符串类型 string
不仅是String, 也可以是数字:比如封锁一个IP地址(访问超过几次)。
INCRBY命令让这些变得很容易,通过原子递增保持计数。散列类型 hash
key.a key.b
一般用string,value
存json就可以满足了。此类型,key少,会有压缩,内存节省。集合类型
自动去重 交集(共同好友) 并集(全部朋友)
自动去重 集合的概念 实现交集并集 差集 都很方便有序集合类型
自动排序,value
指定score
进行排序。
跳表实现,空间换时间,大于128,或者单数据大于64,会转为跳表,提高查询效率。1/4概率加层,最高32层。
跳表比平衡二叉树,实现简单,改操作实现简单。
redis中的跳表,支持重复,根据key,value来确定排序,底层是双向链表。
https://juejin.cn/post/6844903446475177998队列 阻塞队列
双向链表,rpush
生产消息,lpop
消费消息。
异步队列
list还有个指令叫blpop,brpush
,在没有消息的时候,它会阻塞住直到消息到来。
相当于 java的 阻塞队列的 take方法。发布/订阅
1多对多发消息,订阅者没有ack。stream
redis5.0
维护一个有序队列,消费组里的消费者去挨个消费。
消费组里的消费者消费互斥。
消费者有ack,意味着可以在消费时,重复消费。geospatial
经纬度,提供一些方法,计算半径内满足的经纬度,两个经纬度之间的距离等等。bitmap
二进制方式去存数据,占用内存小,可以实现布隆过滤。hyperloglog
基数计算,用于大数据的统计,有一定的误差,比起bitmap还能较少内存占用。
转结构条件 | |||
---|---|---|---|
string | int | 字符串 | sds(raw embstr) |
hash | ziplist | 数量大于512,单个大于64字节 | 哈希表 |
list | ziplist | 数量大于512,单个大于64字节 | 双向链表 |
set | inset | 数量大于512,有非整数 | 哈希表 |
zset | ziplist | 数量大于128,单个大于64字节 | 跳表 |
持久化
-
AOF
可以秒级恢复。
RDB
是分钟级的(save
和bgsave
)。 -
RDB
方便备份 全量AOF
增量。 -
RDB
压缩二进制,不用父线程做什么 都是fork出来的子进程做的,之后写时复制。
(没有写过的数据是共享的,写入的数据会复制一份到内存。)
而AOF
在写入是得写入系统缓存。定期压缩机制,会剔除无效的命令,对命令进行合并。
淘汰策略
- 写入失败
- 移除最少使用 (设过期or全部)
- 随机移除 (设过期or全部)
- 设过期-快过期
删除策略
定期删除+惰性删除
-
定期删除
对cpu不友好,对内存友好。 -
惰性删除
对cpu友好,对内存不友好。
集群
场景1:10wqps,写入。可以主从,从读主写,压力分担,基于redis快照。
场景2:几十wqps,写入,分片。多台机器,hash分流(去中心化,链接哪个客户端都可以)。
哨兵模式:在主从基础上加入哨兵检测,主挂掉之后,重新选主。
哨兵也是一个redis服务,一般是单数,有监控,通知,故障迁移等功能。
大致分为1.主观下线。2.客观下线。3.选哨兵集群代表。4进行换主。
分布式锁
setnx
设置过期时间。
在finally
中 解锁,避免出现异常是死锁情况。
秒杀
https://blog.csdn.net/qq_35190492/article/details/103105780
https://blog.csdn.net/qq_37909508/article/details/100023443
-
服务高可用
前端页面图片都cdn缓存,全国各地就近访问,减少流量压力。
url隐藏到时间才返回到前端。
tomcat,qps每秒几百,可以集群,提前多买点流量机器。
可以做接口限流,保证服务的正常运行。
针对ip多次访问,进行限制。
服务要做到和其他的业务隔离,互不影响。
可以先走redis,活动结束,异步到数据库落盘。 -
redis流程
提前把商品数加载到内存,2个集合,分别存抢到和没抢到的(最后有没卖完的,可以检查)。秒杀时判断,两个集合都不存在,才可以抢。
lua脚本去控制,保持原子性和有序性,防止超卖。
阻塞可能
https://mp.weixin.qq.com/s/DBN6j9kJS41wz2ijO6LzJg
-
命令 key太多用keys,可以用scan替换。(分次执行,支持limit,但得手动去重-渐进式rehash机制,新旧两个版本)
value太大,几万的数据放入hash,或者set。 - 持久化,快照fork系统处理比较慢,会阻塞主线程。aop在硬盘压力比较大,出现问题会阻塞主线程。
- 虚拟内存,swap时。redis内存不够了,一般会分片存,或者虚拟内存(硬盘)存一部分数据。虚拟内存,会把冷数据的value放到硬盘上。