Redis

104 阅读7分钟

Redis

19063731-684743ff91121d5f

redis底层

redis是基于TCP协议的socket通信,首先要跟服务器内核通信(三次握手),用户态通过API调内核态,控制源语。

select poll epoll区别

image-20220314220909360

image-20220314220758784

数据结构

图片

image-20220320003915808

image-20220320004148754

主从模式

  • 一主二仆

    A master -- B slave
        |------ C slave
    

    从机自动复制主机数据

    主机可写可读,从机仅可读,配置文件配只读,写报错

    主机挂掉,从机还是slave

    主机重启,从机恢复主机内容

    从机挂了,再重启变为master,不保存其他master内容

    一台从机只能是一台master的slave

  • 薪火相传

    A master -- B slave(master) -- C slave
    

    A的内容,BC都能复制到

  • 反客为主

    A master -- B slave
        |------ C slave
    

    B 设置为slave of no one,C是B的slave,A挂之后BC成为一套体系,而A恢复后自成一套体系

哨兵机制

选举

image-20210408003241368

雪崩 击穿 穿透

雪崩

原因:某时刻大量数据集中失效,导致大量请求访问数据库

方案:互斥锁;加一个random时间,避免同时失效

击穿

原因:大量并发访问某一数据,而数据刚好过期

方案:加互斥锁,再查一遍缓存,如果不存在,访问数据库,查到写缓存

穿透

原因:恶意访问redis和mysql不存在数据,

方案:做数据库校验或布隆过滤器

redis数据淘汰策略

  • volatile-lru:使用LRU算法进行数据淘汰(淘汰上次使用时间最早的,且使用次数最少的key),只淘汰设定了有效期的key

  • allkeys-lru:使用LRU算法进行数据淘汰,所有的key都可以被淘汰

  • volatile-random:随机淘汰数据,只淘汰设定了有效期的key

  • allkeys-random:随机淘汰数据,所有的key都可以被淘汰

  • volatile-ttl:淘汰剩余有效期最短的key

    最好为Redis指定一种有效的数据淘汰策略以配合maxmemory设置,避免在内存使用满后发生写入失败的情况

具体回收算法 TTL(all,random)根据过期时间 LRU(最近少用)根据缓存命中率 不回收,满了就读不能写


不论是否设置有效期,内存不会立马回收

  1. 惰性回收,执行get命令时,如果key过期,自动清除
  2. 采用定时模式,例如:10次/s

redis底层特点or为什么快

  1. 存储在内存中
  2. io多路复用,worker线程是单线程

Redis的LUA脚本能不能保证原子性

Redis事务:脚本执行器,执行lua脚本过程中,有其他客户端请求,暂存起来,脚本执行完再执行暂存的请求。执行错误后不回滚,不影响后面指令执行

mysql事务:要么都成功 要么都不成功

Redis设计模式

追求可用性,分区容错性; 忽略一致性

Redis有哪些类型,适用场景

  • String:用户凭证信息,有int类型,分布式锁,验证码,(点赞,点踩,播放数量,文章阅读数), bitmap
  • hash:需要频繁修改信息,就可以采用这个结构,购物车,查询账户余额(非转账场景)
  • list:队列和栈,双向链表,信息流
  • set:集合,微信微博的点赞、收藏和标签
  • zset: 排序集合,关注模型,排行榜, 分数,可排序,定点提醒,排行榜

用处 1 分布式session+redis中 2 订单记录存在redis的list中

什么样数据适合放缓存

  • 低频修改
  • 常被访问
  • 非敏感

redis为什么快

  1. 纯内存操作
  2. 单线程操作,避免上下文切换
  3. 采用非阻塞IO多路复用机制
  4. c语言开发的

redis的持久化方式

RDB (Redis DataBase)

原理:指定时间间隔 数据集写入磁盘,俗称快照SnapShot,fork一个子进程,将数据写入临时文件,覆盖最后一次RDB文件

特点:大规模数据恢复,完整性不太敏感,恢复速度快,节省磁盘空间

缺点:最后一次持久化后数据可能丢失

save 900 1
save 300 10
save 60 10000

AOF (Append of FIle)

原理:以日志形式记录,将Redis执行操作记录下来,只许增加不许改,写指令从头到尾执行完成数据恢复工作

特点:备份机制更稳健,不易丢数据 可读日志文本,可处理误操作

缺点:费空间,恢复慢,性能消耗大

TIP: 冗余数据,对一个key连续写入

# 开启aof功能
appendonly yes
appendfilename "appendonly.aof"
# appendfsync always
appendfsync everysec
# appendfsync no

###混合方式

RDB——二进制 AOF——日志(持久化文件XXX.aof)

持久化步骤:1. 拍快照; 2. 删日志aof 导入步骤:

rewrite: 重写,对AOF文件压缩

#开启混合模式
aof-use-rdb-preamble yes

Redis

主从集群

master负责读写,slave负责读

master挂了,集群所有写请求失败,不提供容错和恢复功能

哨兵模式

哨兵监听集群的实例状态,一旦master挂掉,选举新的master

没有解决在线扩容方法

Redis Cluster

引入slot槽对数据进行分片,0~16383

image-20221205190639256

缺点:slave节点没法分担读写压力,只是冷备;

对redis批量操作指令有限制。

Redis缓存穿透、缓存击穿、缓存雪崩

缓存穿透

伪造一个不存在数据id进行查询,因此需要校验,如果用map来存哪些id有,对于上千万上亿数据来说,占用过多内存空间

布隆过滤器: bit数组,默认为0,对已有每个数据多个hash,并置为1。当请求到来时,如果多个hash值都为1,则请求缓存。若其中有0,则一定不存在。适合读多写少情况。 涉及到数据不一致的问题,比如新插入数据,还没更新布隆过滤器,因此请求被过滤掉。考虑到具体业务场景

缓存空值: 若缓存或mysql查不到数据,则放到缓存map中

image-20230118004053707

缓存击穿

如果大量请求同一个商品,而商品的缓存在此时失效,都打到数据库,导致数据库挂掉。

  • 需要我们对商品id进行加锁,请求到之后再写入缓存。
  • 在临近过期时,对缓存key进行续期

缓存雪崩

是多个热点数据同时过期

  • 为防止多个key同时过期,多个缓存过期时间+1~60s随机数
  • 为防止宕机故障,采用集群或哨兵模式
  • 高可用后,redis还是挂了,服务降级,采用兜底数据,从配置中心拿兜底数据

redis序列化

hash字符串序列化

使用redis的hash类型存储和使用string方式序列化

缺点:反序列化后是string格式,转化为对象十分麻烦

优点:耗时最短,string序列化后,可视化界面还是原样子

json序列化

使用redis的list类型存储和使用JSON方式序列化

缺点:比hash类型储存的耗时长点

优点:值经过json序列化,以键值对方式呈现,可读性好

jdk序列化

使用redis的list类型存储和使用jdk方式序列化

缺点:耗时长,值经过jdk序列化,会看着像乱码,可读性差

优点:默认序列化格式,不用配置就是这个