Redis是什么
如何演化:互联网一开始只是一个简单的web server 结构为简单的server+数据库 但是随着互联网的发展 数据从单表演进出了分库分表(多个库多个表) MySQL从单机也演进出了集群 但是随着数据量的增长 读写压力不断增加 Redis应运而生
Redis本质:将数据分为冷热 也就是访问频率的多少 热数据就是经常被访问到的数据 冷数据反之 Redis将热数据存储到内存之中 读写速度大大提高 如果Redis读不到再去MySQL中找数据
基本工作原理:数据从内存中直接读写 对于关机内存丢失的问题 Redis会将数据保存到硬盘上防止数据丢失 (增量数据保存到AOF文件 假如服务器宕机了 Redis会在重启后读取AOF文件来保证宕机前的流程可以继续进行) Redis是单线程处理所有操作命令(线性执行 先到先执行)
Redis应用场景
- 连续签到:掘金每日签到(用到三个数据类型:1. user id 2. 连续签到天数 3. Redis的过期时间)
- 消息通知:用list作为消息队列(当文章更新后 将更新后的文章推送到ES 用户就能搜索到最新的文章数据) tips:List数据结构QuickList由一个双向链表和listpack实现
- 计数:如果一个用户有多项计数需求 可以通过hash结构来存储 tips:Hash数据结构dict有两种方法 rehash和渐进式rehash rehash的操作是将ht[0]中的数据全部迁移到ht[1]中 适用于数据量较小的场景 但是在数据量巨大的场景下速度很慢 所以就要用渐进式rehash 这种方法就是在用户每次访问的时候都迁移少量数据 积少成多 所有的数据循序渐进的迁移过来后再一次性更新
- 排行榜:积分变化时 排名要实时变更 结合数据结构dict后 可以实现通过操作key来跳表的功能 tips:zset数据结构zskiplist可以查找dict中的数字路径 如head,3,3,7 跟dict结合起来就能实现key操作跳表的功能
- 限流:要求1秒内放行的请求为N 超过N则禁止访问
- 分布式锁:并发场景 要求一次只能有一个协程执行 执行完成后 其他等待中的协程才能执行 可以使用redis的setnx来实现 利用了redis是单线程命令和setnx要未设置过才能成功的两个特性
大Key和热Key
大Key的危害:读取成本高 容易导致慢查询(过期 删除) 出从复制异常易导致服务阻塞无法正常响应请求 例子:请求Redis超时报错
消除大Key的方法:
- 拆分:将大Key拆分为小Key 例如一个String拆分成多个小String片段
- 压缩:将value压缩后写入redis 读取时解压后再使用 压缩算法有gzip snappy lz4等 通常情况下 一个算法压缩率高则解压耗时就长(大部分考虑解压所需时间) 需要对实际数据进行测试后选择一个合适的算法 吐过存储的是json字符串 则可以考虑使用算法MessagePack进行序列化(大部分可以达到50%的压缩率)