这是我参与「第五届青训营 」伴学笔记创作活动的第 15 天
学习到了Redis的基本数据类型,以及对应数据类型的底层实现如SDS,QuickList,SkipList等都是Redis在C语言的基础上进行优化而得到的数据结构.并学习到了Redis的应用场景,例如签到,计数,排行榜和分布式锁等等,最后了解到了Redis保证高可用的方式,以及真实环境中可能产生的问题以及解决方式
一、Redis是什么
为什么需要Redis
Redis基本工作原理
- Redis实现数据持久化的原理:AOF/RDB
RDB持久化是把当前进程数据生成快照保存到硬盘的过程,触发RDB持久化过程分为手动触发和自动触发。
RDB⽂件是⼀个压缩的⼆进制⽂件,通过它可以还原某个时刻数据库的状态。由于RDB⽂件是保存在硬盘上的,所以即使Redis崩溃或者退出,只要RDB⽂件存在,就可以⽤它来恢复还原数据库的状态。
AOF(append only file)持久化:以独立日志的方式记录每次写命令, 重启时再重新执行AOF文件中的命令达到恢复数据的目的。AOF的主要作用是解决了数据持久化的实时性,目前已经是Redis持久化的主流方式。
- Redis单线程处理命令的概念
众所周知,redis非常快,而且是单线程的,这里说的单线程是指单线程处理命令,而实际上redis是多线程的,很多异步操作都是给后台线程进行操作的。 高效的原因:
- 内存级,读写速度快,不受磁盘IO限制
- 数据结构设计简单以及高效,很多结构操作都是O(1)
- 单线程 (1)没有竞争,不需要锁 (2)没有线程切换,不需要上下文切换 (3)串行执行,保证每个操作都是原子性的
- IO多路复用架构,非阻塞IO
二、Redis应用案例
Redis底层数据结构
Redis有动态字符串(sds) 、链表(list) 、字典(ht) 、跳跃表(skiplist) 、整数集合(intset) 、压缩列表(ziplist) 等底层数据结构。
Redis并没有使用这些数据结构来直接实现键值对数据库,而是基于这些数据结构创建了一个对象系统,来表示所有的key-value。
我们常用的数据类型和编码对应的映射关系:
redis没有直接使⽤C语⾔传统的字符串表示,⽽是⾃⼰实现的叫做简单动态字符串SDS的抽象类型。
C语⾔的字符串不记录⾃身的⻓度信息,⽽SDS则保存了⻓度信息,这样将获取字符串⻓度的时间由O(N)降低到了O(1),同时可以避免缓冲区溢出和减少修改字符串⻓度时所需的内存重分配次数。
List数据结构QuickList是由一个双向链表和listpack实现的
Listpack
Hash数据结构Dict
zset数据结构skiplist
Redis应用
- 连续签到,需要了解GET/SET,Key过期
- 消息队列
- 用户计数,使用到HASH
- 排行榜ZSET
- 使用SETNX实现分布式锁
三、Redis使用注意事项
- 大Key:Value大于10KB就是大Key,使用大Key将导致Redis系统不稳定
- 热Key:一个Key的QPS特别高,将导致Redis实例出现负载突增,负责均衡流量不均的情况。导致单实例故障
- 慢查询:大Key、热Key的读写;一次操作过多的Key(mset/hmset/sadd/zadd)
- 导致缓存穿透、缓存雪崩的场景及避免方案