Redis基础和原理|青训营笔记(三)

109 阅读6分钟

Redis单线程的高效性

Redis是单线程,效率依然很高。因为其在内存上进行读取速度很快,而多线程场景下进行CPU上下文切换会非常耗时。

1. 五种基本数据类型

String

使用场景:除了字符串,也可以设置为数字

  • 计数器
  • 统计多单位的数量
  • 对象缓存存储

List

Hash

Set

Zset

2. 三种特殊数据类型

geospatial

hyperloglog

bitmaps

3. 事务

Redis单条命令保证原子性,但是事务不保证原子性,和Mysql不一样。

Redis事务不支持回滚,而是执行余下代码,因此内部可保证简单与快速。

Redis事务本质:

  • 一次性:一组命令的集合,执行前会被放入队列缓存,事务命令集都会被序列化
  • 顺序性:收到执行请求后,事务命令顺序执行,任意命令失败,不影响其余命令执行;
  • 排他性:事务执行时,其他命令请求无法插入当前事务。

Redis事务执行:先入队再执行

  • 开启事务(multi)
  • 命令入队(…)
  • 执行事务(exec)
  • 放弃事务(discard)

放弃事务:事务队列中所有命令均不执行 编译型异常:命令有错时,编译出错,事务所有命令均不执行 运行时异常:编译可通过但有语义错误,正确命令正常执行,错误命令抛出异常。

4. Redis乐观锁

执行时不加锁,更新数据时再判断是否被改动过。可判断版本号version

  • 获取version
  • 执行命令
  • 数据写入时比较version

Redis监视

  • watch监视一个或多个key,若事务执行期间key改动,则必执行失败(所有命令均不执行)
  • 事务exec或discard后会自动unwatch。
  • 事务执行失败后,可再次监视获取最新version,重新执行事务。

Redis持久化

RDB方式

概述: Redis database,默认持久化方式。在指定时间间隔内将内存中的数据集快照写入磁盘。redis会将数据存在内存中,满足一定条件时会对数据进行快照操作并生成临时RDB文件,之后持久化到硬盘中(替换旧的RDB文件)。

存储文件名: dump.rdb

快照触发时机:

  1. 自定义配置save

    save m秒 n改键,若注释掉则不进行持久化

    满足要求自动触发bgsave

  2. 执行save

    该命令期间redis服务器被阻塞,无法处理其他命令,直到RDB完成。完成后若有旧RDB则替换。

  3. 执行bgsave

    该命令首先使redis进程fork子进程(阻塞),之后主进程保持响应客户端请求,子进程后台异步进行RDB持久化。

image.png

RDB特征:

  1. 快照时不修改原RDB文件,因此任何时候RDB文件均完整。可定时备份RDB实现redis数据库备份。
  2. 子进程会处理保存工作,父进程无需执行磁盘I/O。
  3. 全量备份,RDB恢复大数据集速度优于AOF
  4. 快照持久化期间无法感知redis内存数据被修改,因此可能丢失数据。因此持久化重要数据可以考虑AOF

AOF方式

概述: append only file,默认不开启。每执行一条更改redis数据的命令,Redis就会将其写入磁盘中的AOF文件,以此同步数据库状态。这对redis性能会有一点影响,使用较快磁盘可改善AOF性能。

存储文件名:appendonly.aof

redis客户端执行命令时,先通过网络将resp协议文本发送给redis服务器,AOF文件使用网络通讯协议格式来保存命令。

命令同步至AOF文件

  1. 命令传播

    redis客户端以resp协议发送命令,服务器将字符串文本转换为redis字符串对象。命令执行完后,将命令信息传播至AOF程序

  2. 缓存追加

    AOF将redis字符串对象还原回resp协议格式,追加至服务器AOF缓存redis.h/struct redisServer{sds aof_buf}

    redis.h
    struct redisServer {
    	sds aof_buf;       //追加至aof缓存
    };
    
  3. 文件写入和保存

    WRITE:aof_buf缓存内容写入AOF临时文件末尾。

    SAVE:若满足设定的AOF保存条件,则调用fsync函数,将AOF文件持久化到磁盘。

AOF保护模式

  • 不保存

    只在redis被关闭、AOF功能关闭、写缓存刷新时,会由主进程执行SAVE持久化操作,主进程期间被阻塞。

  • 每秒保存

    SAVE操作由后台子进程调用,不引起服务器主进程阻塞,但SAVE速度影响WRITE操作的阻塞时长(进程切换或硬件有关)。

  • 每条命令保存

    每执行一次,WRITE与SAVE被执行,SAVE由主进程执行,期间主进程被阻塞。

Redis发布订阅

Redis主从复制

主从复制方式

① 全量复制

首次同步

  1. 建立连接、协商同步

    从server执行replicaof命令,请求主server同步,主server返回FULLRESYNC,表征全量复制

  2. 主server同步数据至从server

    主server执行bgsave,fork子进程生成RDB文件,并发送给从server,从server清空当前数据后载入该RDB文件。期间主server收到新的写命令会存入replication buffer。

  3. 主server发送新写命令至从server

    主server将replication buffer记录的写命令发送至从server,从server执行写命令。

    首次同步即完成。

② 命令传播(基于长连接)

首次同步会传输数据。之后不用再传输数据,双方只需维持一个TCP连接,主server不断传输新的写命令至从server,由从server执行即可。

基于长连接的命令传播来保证首次同步后的主从server数据一致性。

image.png ③ 增量复制

若slave与master断开连接后又恢复,此时slave会发送psync{runId}{offset}命令给master,master根据slave_repl_offset与master_repl_offset作差判定期间丢失命令是否全部在缓冲区中:

  1. 若在,则在repl_backlog_buffer中查找增量写入replication buffer,并通过增量复制传播给slave
  2. 否则重新进行全量复制。为降低全量概率,可以适当调整repl_backlog_size大小。

image.png

主从复制key过期

Redis处理key过期有惰性删除和定期删除两种方式。配置主从复制后slave无权处理过期key,master累积过期key到一定量后,发送del至slave,删除slave的key。slave变为master后重获处理过期key的权限。

分摊Master server压力

Master server生成并传输RDB文件很耗时,slave server数量过多时master压力会很大,可以将master生成并传输RDB的压力分摊到充当经理的slave server。

实现方法为:slave server执行replicaof指向经理server。

image.png

Redis缓存穿透 击穿 雪崩

Redis底层数据结构

Redis配置文件

基本配置

bind 127.0.0.1
port 6379
protected-mod yes   #保护模式

unit配置  # unit对大小写不敏感

daemonize yes #守护进程方式运行,默认no关闭
pidfile /var/run/redis_6379.pid  #若后台执行,需要指定pid文件

loglevel notice    #日志级别  debug/verbose/notice/warning
logfile ""   #日志的文件位置

database 16  #默认16个数据库

持久化配置