Redis简介
redis是一个开源的使用 C 语言编写,支持网络,基于内存并且可持久化的日志 K-V 非关系型数据库。支持多种语言的API。支持多种数据类型(String、List、Set等)
Redis应用场景
- 缓存: 当系统接口比较慢时,可以把系统数据接口的数据缓存起来,下次可直接从缓存中读取。
- 数据存储: redis有两种持久化机制【AOF和RDB】,可以将数据持久化到硬盘中,保证数据的完整性,安全性。
为什么使用Redis
- 高性能共享: 当数据需要被多个线程/进程/节点频繁读取时,redis基于内存读写效率高。
- 并发缓存: 当多个写请求需要连接其他数据库时,使用redis做一个缓存,将多个并发连接转化为一次连接。
Redis原理
数据结构
String: 最基本的数据类型,可以包含任何数据。一个 redis 字符串 value 最多可以是 512M
hash: 散列,是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对
象。
list: 单键多值,就是一个简单的字符串列表。底层是一个双向链表,对两端的操作性能很高,通过索引下标的操作中间的节点性能会较差。
set: 自动去重
zset: 有序无重复集合
持久化
RDB持久化: 在指定时间间隔内 redis 会将内存中所有数据以二进制方式生成一份副本存储到硬盘上(相当于快照), redis 重启时可以通过该副本恢复数据,生成快照时 redis 进入阻塞状态。默认开启。
AOF持久化: redis将日志追加到磁盘文件中,redis 启动时优先选择从 AOF 文件恢复数据。由于每次写操作都会记录日志,因此 AOF 会降低性能,但比起RDB的一次性阻塞式备份数据, AOF 消耗的内存和资源更少。 AOF 文件达到阈值时,会重写一次 AOF 文件,将每个 Key 之保留最新的 value 的日志。
混合持久化: 开启混合持久化后,redis 按照正常RDB快照文件,在两次快照期间通过AOF追加日志到 RDB 数据后面,因此最终生成的 AOF 文件是以 RDB 数据开头、多个日志操作结尾的文本文件,新文件的AOF文件会直接覆盖旧的AOF。
redis4之前的版本不识别混合 AOF 文件。
优点:兼具RDB加载快、数据量小的AOF数据安全性,不需要重写过程。
过期策略
采用定期删除 + 懒惰删除的方式清理过期数据
定期删除:每100ms随机抽取部分 key 检查,如果过期就删除
惰性删除:使用某个 key 时检查,过期删除
redis有可能产生过期内存不被清理的情况,采用内存淘汰机制,将maxmemory设置为allkeys-lru,当内存不足时,删除最近使用的key。
Redis缓存击穿问题
由于高并发请求刚好失效的key或黑客攻击导致,后端大量请求 redis 不存在的 key ,一般业务程序在 redis 不存在缓存时回到数据库中查询,导致数据库瞬间并发大量连接而崩溃。
解决方案:
- 为mysql各种表的 key 设置布隆过滤器,请求 mysql 前先用布隆过滤器确认一遍,存在才申请(防黑客)
- 使用互斥锁,缓存不存在时向数据库发起带锁的读取请求,其他并发请求获取不到锁则休眠重试读取。
缓存雪崩
缓存在同一时间大面积失效,此时大量请求失效key,造成数据库高并发连接而崩溃。
解决方案:
- 缓存预热
- 采用互斥锁
- 过期时间追加随机数
双写一致性问题
对数据库进行写操作时会产生的redis缓存与数据库数据不一致的问题。目前流行的是先更新数据库+删除缓存+补偿机制的方案
线程A写数据库->线程A写完之后删除缓存->删除失败时将key放入消息队列->外部某个程序定时重试删除
线程B读缓存,读不到->线程B读数据库->线程B将读到的数据放入缓存
单线程redis为什么快
- 纯内存操作
- 单线程操作,避免了频繁的上下文切换
- 采用了非阻塞I/O多路复用机制
Redis 主从复制
主从简介
配置多台 redis 服务器,以主机和备机的身份分开。主机数据更新后,根据配置和策略,自动同步到备机的 master/salver 机制,master以写为主,slave以读为主,二者之间自动同步数据。
目的: 一是读写分离提高 Redis 性能;二是避免单点故障,容灾快速恢复
原理:
每次备机联通后,都会给主机发送sync指令,主机立刻进行存盘操作,发送RDB文件给备机。备机收到RDB文件后,进行全盘加载。之后每次主机的写操作,都会立刻发送给备机,备机执行相同的命令。
主从准备
除非是不同的主机配置不同的 Redis 服务,否则在一台机器上面跑多个 Redis 服务,需
要配置多个 Redis 配置文件。
主从建立
临时建立
原则:配从不配主
配置:从服务器上执行 SLAVEOF ip:port命令;
查看:执行 info replication 命令
永久建立
在备机的配置文件中,编写 slaveof 属性配置
恢复身份
执行命令 slaveof no one 恢复自由身
主从常见问题
- 从机是从头开始复制主机的信息,还是只复制切入后的信息?
从头开始复制,即完全复制。实际是读取主机的RDB - 从机是否可以写?
不可以 - 主机宕机后,从机是上位还是原地等待?
原地等待 - 主机恢复后,主机新增记录,从机还能否顺利复制?
可以 - 从机宕机后重启,宕机期间主机的新增记录,从机是否顺利复制?
可以 - 其中一台从机宕机后重启,能否重认旧主?
不一定,看配置文件中是否配置了 slaveof - 如果两台从机都从主机同步数据,此时主机 I/O 压力会增大,如何解决?
按照主 – 从(主) – 从 模式配置
哨兵模式
反客为主的自动版,能够后台监控主机是否故障,如果故障了根据投票数自动将从库变成主库。
作用: Master 状态检测;如果 master 异常,进行 Master-Slave 切换,将其中一个Slave作为 Master ,将之前的master作为 Slave。
主机宕机后
Redis集群
写入数据
客户端重定向
- 在redis-cli 每次录入、查询键值,redis 都会计算出该 key 应该送往的插槽,如果不是该顾客对应服务器插槽,redis会报错,并告知应前往的redis实例地址和端口。
- redis-cli 客户端提供了 -c 参数实现自动重定向。
- 每个slot 可以存储一批键值对。
如何多键操作
采用哈希算法后,会自动地分配 slot,不在一个 slot 下的键值,是不能使用 mget,mset等等多键操作。
如果有需求,需要将一批业务数据一起插入呢?
解决:可以通过{}来定义组的概念,从而使key中{}内相同内容的键值对放到一个 slot 中去。
集群中故障恢复
当主节点宕机,从机上位;若主节点恢复,则变为从节点。
集群优缺点
优点
- 实现扩容
- 分摊压力
- 无中心配置相对简单
缺点
- 不支持多键操作
- 多键的 redis 事务不被支持。lua脚本不被支持