为什么使用redis

  • 高流量访问配置
  • 分布式锁

    数据结构

  1. 字符串String
  2. 字典Hash
  3. 列表list
  4. 集合set
  5. 有序集合SortedSet
  6. HyperLogLog
  7. Geo
  8. Pub/Sub | 数据结构 | 简单说明 | 使用场景举例 | 其他补充 | | —- | —- | —- | —- | | String | key:value的存储方式 | | | | hash | hash的存储空间分为field和value | 购物车中商品,每个商品的数量也不同,可以考虑存储:
    key是用户id, field是商品id,value就是对应商品的数量 | String考虑存储的整体性,要么一次性更新,要么一次性读取;
    hash可以把属性隔离开来,讲究更新操作的灵活性;hash是一个群组的概念,把一系列数据包装起来,产生对外的唯一key。 | | list |
    - 存储多个数据,并对数据进入存储空间的顺序进行访问
    - 双向链表的结构
    |
    - 微信朋友圈点赞
    - 阻塞数据获取blpop
    |
    - list存储的数据都是String类型的,最多2^32-1个元素
    - 有索引概念
    lrange key start stop
    - 可以进行分页操作
    | | set |
    - 存储大量数据,便于查询
    - 结构和hash一样,本质仅存储键field,value为null, 且值是不允许重复的
    |
    - 今日头条对用户推送的新闻
    |
    - 不允许数据重复
    - 不能当hash用,不能启用hash值存储空间
    | | zset |
    - 展示的时候有序
    - 存储空间是:value score
    |
    - 实现排行榜
    - 任务消息权重
    |
    - score是双精度的double值,可能会丢失精度
    - 底层是基于set,数据不能重复
    |

大量key设置同一时间过期,一般需要注意什么?

缓存雪崩。
解决: 一般需要在时间上加一个随机值,使得过期时间分散一点

Redis分布式锁

先拿setnx来争抢锁,抢到之后,再给expire给锁一个过期时间防止锁忘记释放。
setnx和expire合并成一条指令使用。

1亿个key, 有10W个key以某个固定的已知的前缀开头,怎么把他们都找出来?

keys 指令。

redis正在给线上的业务提供服务,那么keys指定会有什么问题?

redis单线程。keys指定会导致线程阻塞一段时间,线上服务会停顿,直到指令执行完毕。这个时候可以使用scan执行,scan指令可以无阻塞的提取出指定模式的key列表,但是会有一定的重复概率,在客户端做一次去重就好了,但是整体回避直接从keys指令长。
scan增量类命令,增量迭代的过程中,键可能会被修改。

redis做异步队列吗?

可以使用list作为队列,rpush生产消息,lpop消费消息。lpop没有消息的时候,需要sleep一会再重试。

可以不用sleep吗? list还有一个指令叫blpop,没有消息的时候,会阻塞直到消息到来

能不能生产一次消费多次呢? pub/sub主题订阅者模式,可以实现1:N的消息队列。 有啥缺点? 消费者下线,生产的消息会丢失。可以用专业的Rocketmq

Redis实现延迟队列

使用sortedSet,拿时间戳作为score,消息内容作为key, zadd来生产消息,消费者zrangebyscore指令获取N秒之前的数据轮询进行处理。

redis是怎么持久化的?服务主从数据怎么交互的?

RDB做镜像全量持久化,AOF做增量持久化。因为RDB会耗费较长时间,不够实时,在停机的时候会丢失数据。所以需要配合AOF来使用。在redis实例重启时,会使用RDB持久化文件重新构建内存,再使用AOF重放近期操作的指令来实现完成恢复之前的状态。

AOF日志有sync属性,如果不要求性能,可以每条写指令都sync一下磁盘,就不会丢失数据。高性能要求的时候,一般都使用定时sync, 比如1s 1 次。这个时候最多丢失1秒的数据。

RDB的原理是什么?

bgsave: redis通过fork创建子进程来进行RDB的操作,子进程创建后,父子进程共享数据段,父进程继续提供读写服务,写脏的页面数据会逐渐和子进程分离开来。

  • RDB是一个压缩的二进制文件,存储效率比较高
  • 恢复速度快
  • 基于快照的思想,每次读写的都是全部的数据,数据量较大时,效率较低
  • fork子进程,消耗内存
  • 宕机可能丢失数据

    AOF的原理

    当有操作指令过来的时候,redis将命令刷新到缓存区,达到一定量的时候,再将命令写入.aof的文件中去。
    三种写数据策略:

  • always 每次

  • everysec 每秒 — 推荐
  • no 交由系统控制

    AOF重写

    bgrewriteaof:重写机制压缩文件体积
    重写的时候会有一个aof重写缓存区,重写后的文件会替换掉原来老的aof文件

    Pipeline有什么好处?

    多次IO往返缩减为一次。前提是执行pipeline的指令之间没有因果相关性。

    redis的事务

    开启事务: multi 执行事务: exec 与multi成对出现 取消事务: discard

watch

watch key
对key添加监视锁,在指定exec前如果key发生变化,终止事务执行。

setnx

监控一个key不够,需要监控到具体的数据

Redis同步机制

主从同步、从从同步。
第一次同步,主节点做一次bgsave,并同时将后续修改操作记录在内存buffer,待完成后,将RDB文件全量同步给复制节点,复制节点接受完成后将RDB镜像加载到内存。加载完成后,再通知主节点将期间修改的操作记录同步到复制节点进行重放就完成了同步过程。后续的增量数据通过AOF日志同步即可,有点类似mysql的binlog.

Redis集群的高可用,怎么保证的

Redis Sentinel 着眼于高可用,master宕机之后会自动将slave提升为master,继续提供服务。
Redis Cluster 着眼于扩展性,单个redis内存不足的时候,使用cluster进行分片存储。