Redis基础

  Redis 是一个开源的,内存中的数据结构存储系统,可以用作 Nosql 数据库、高速缓存和消息队列。它是一个高性能的 key-value 数据库,运行在内存中,但是可以持久化到磁盘。

1. 特点

  • 速度快(内存读取)

  • 支持多种数据结构(字符串、哈希、列表、集合、有序集合)

  • 支持数据备份(master-slave)

  • 支持数据持久化(RDB,AOF)

  • 支持高可用(Redis-Sentinel)和集群(Redis-Cluster)

2. 数据结构

  • 字符串: set 和 get,做最常用的的 K/V 缓存,一个键最大能存储 512MB。还可以用作计数器。

  • 哈希: 将结构化的数据放入缓存。读写缓存时,可以操作 Hash 里的某个字段。

  • 列表: 存储一些列表型的数据结构,比如文章列表、数据分页、消息队列。

  • 集合: 自动去重数据,交集、并集、差集等操作。

  • 有序集合: 去重数据并排序,比如排行榜应用。

3. 线程模型

  redis 是单线程的。它采用 I/O 多路复用机制同时监听多个 socket,将 socket 产生的事件放入队列,事件分派器每次从队列中取出一个事件,并交给对应的事件处理器进行处理。

  redis 使用文件事件处理器,包含 4 个部分:

  • 多个 socket

  • I/O 多路复用程序

  • 文件事件分派器

  • 事件处理器(包括:连接应答处理器、命令请求处理器、命令回复处理器)

redis支持高并发

  • 基于内存操作,读写速度快

  • 单线程省去了线程切换的消耗

  • I/O多路复用机制

4. 安装启动

$ tar -xzf redis-5.0.8.tar.gz
$ cd redis-5.0.8
$ make
$ src/redis-server redis.conf

5. 连接服务器

$ redis-cli -h 127.0.0.1 -p 6379 -a password 
127.0.0.1:6379> AUTH password  #验证密码是否正确
OK
127.0.0.1:6379> PING
PONG
127.0.0.1:6379> SELECT index    #切换数据库,默认使用0号库(0-15)
OK
127.0.0.1:6379[index]> QUIT    #关闭当前连接

6. 持久化机制

(1)RDB 持久化:将某个时间点的内存快照保存到一个 RDB 文件中,该文件是一个经过压缩的二进制文件,通过它可以恢复内存数据。

  RDB 是 Redis 默认的持久化方式,在指定目录下生成一个 dump.rdb 文件。持久化过程是由服务器进程 fork 一个子进程,先将内存数据写入临时文件,完成后再替换旧文件。

  • 通过 SAVE 和 BGSAVE 命令对数据进行持久化,生成 RDB 文件。

  Redis 是单线程的,SAVE 命令会阻塞 redis 主进程,阻塞期间服务器不能处理用户请求。

  BGSAVE 命令不会阻塞主进程,会 fork 一个子进程,由子进程负责持久化数据,服务器进程继续处理用户请求。

  • 通过配置文件

  redis.conf 配置文件中的 save 配置项,让服务器每隔一段时间自动执行 BGSAVE。

save 900 1    #服务器在900秒之内,对数据库进行了至少1次修改。
save 300 10    #服务器在300秒之内,对数据库进行了至少10次修改。
save 60 10000    #服务器在60秒之内,对数据库进行了至少10000次修改。

(2)AOF持久化:服务器在执行完一个写命令后,以协议格式将写命令追加到服务器的AOF缓冲区的末尾,然后定期将缓冲区的数据写入 AOF 文件,保存到磁盘。

  AOF 默认是不开启的,可以修改 redis.conf 来开启。

appendonly yes    #开启AOF持久化
appendfsync everysec    #每秒钟同步一次,默认策略

AOF重写

  AOF重写是为了解决AOF文件过大的问题。重写过程是服务器进程 fork 一个子进程,保存服务器当前的数据库状态。

子进程重写期间,服务器进程需要执行以下三个工作:

  • 处理用户请求

  • 将写命令追加到现有的AOF文件

  • 将写命令追加到AOF重写缓冲区(保证数据的一致性)

当子进程完成AOF重写后,向服务器进程发送一个信号。服务器进程将AOF重写缓冲区中的内容全部写入到新的AOF文件,并替换旧的文件。

  • 通过rewriteaof命令重写AOF

  • 通过配置文件参数 auto_aof_rewrite_min_size,auto_aof_rewrite_percent

选择 RDB 还是 AOF?

  • RDB 非常适合大规模的数据恢复,如果业务对数据一致性要求不高,RDB 是很好的选择,否则使用 AOF 方式。

  • 如果想保证数据一致性,同时又希望保持高效率,可以同时使用 RDB 和 AOF 两种方式。启动服务时会优先加载 AOF 文件。 

7. 内存淘汰策略

  通过 redis.conf 中 maxmemory <bytes> 设置 Redis 的最大内存,或者 config set 命令在运行时动态配置 Redis 的内存。

当 Redis 使用内存达到 maxmemory,根据 maxmemory-policy 策略来淘汰数据,回收内存。

  • volatile-lru
  • allkeys-lru
  • volatile-random
  • allkeys-random
  • volatile-ttl
  • no-envicition   不淘汰 key,默认算法

8. 过期删除策略

  key 的过期时间可以通过 set 设置 key 的时候指定,也可以通过 expire 命令指定。persist key 命令设置 key 永不过期。

  • 定时删除:对于每一个设置了过期时间的 key 都会创建一个定时器,一旦到达过期时间就立即删除。
  • 惰性删除:当访问一个 key 时,判断该 key 是否过期,过期则删除。
  • 定期删除:每隔一段时间,扫描 Redis 中过期时间的 key,并清除部分过期的 key。

  Redis 同时使用了定期删除和惰性删除。

9. redis-sentinel架构

(1)redis Master-Slave主从复制模式下,如果 Master 节点出现故障,Slave 节点无法自动切换成 Master,需要人工干预。redis-sentinel 是redis官方推荐的高可用性解决方案,它是一个独立运行的进程。多个 sentinel 进程协同工作,组成一套分布式的架构。监视相同 Master,Slave 的 Sentinel 通过 master 的发布/订阅消息机制来相互发现。

Sentinel 的作用:

  • Master 状态检测。

  • 如果 Master 异常,则会进行 Master-Slave 切换,将其中一个 Slave 作为 Master,将之前的 Master 作为 Slave。

  • Master-Slave 切换后,master_redis.conf、slave_redis.conf 和 sentinel.conf 的内容都会发生改变,即 master_redis.conf 中会多一行 slaveof 的配置,sentinel.conf 的监控目标会随之调换。

(2)Sentinel 工作方式:

  • 每个 Sentinel 以每秒一次的频率向 Master,Slave 以及其他 Sentinel 实例发送一个 PING 命令。

  • 如果一个实例距离最后一次有效回复 PING 命令的时间超过 down-after-milliseconds 选项所指定的值, 则这个实例会被 Sentinel 标记为主观下线。

  • 如果 Master 被标记为主观下线,则正在监视 Master 的所有 Sentinel 要以每秒一次的频率确认 Master 进入了主观下线状态。

  • 当有足够数量的 Sentinel 在指定的时间范围内确认 Master 进入了主观下线状态, 则 Master 会被标记为客观下线。

  • 在一般情况下, 每个 Sentinel 会以 10 秒一次的频率向 Master,Slave 发送 INFO 命令。当 Master 被标记为客观下线时,Sentinel 向 Master,Slave 发送 INFO 命令的频率变为每秒一次。

  • 若没有足够数量的 Sentinel 同意 Master 已经下线, Master 的客观下线状态就会被移除。若 Master 重新向 Sentinel 的 PING 命令返回有效回复, Master 的主观下线状态就会被移除。

  主观下线(Subjectively Down,SDOWN),指的是单个 Sentinel 实例对某个 redis 服务器做出的下线判断。sentinel down-after-milliseconds <masterName> <timeout>

  客观下线(Objectively Down, ODOWN),指的是多个 Sentinel 实例对 Master 做出 SDOWN 判断,并且通过 SENTINEL is-master-down-by-addr 命令互相交流之后,得出的 Master 下线判断,然后开启 failover。sentinel monitor <masterName> <ip> <port> <quorum>

  故障转移的触发条件是 Master 处于 ODOWN 状态。选举出一个 Sentinel 作为 leader,根据 Slave 与 Master 断开连接时长、优先级、复制量、run id等选出一个 Slave 来完成 failover。leader 发送 slaveof no one 命令到选出的 Slave,升级为 Master,并向其他 Slave 发送 slaveof  <masterIP> <masterPort命令重新配置 Master。

  客户端通过 Sentinel 获取 redis Master 地址:

(1)获取所有的 Sentinel 节点,遍历得到一个可用的 Sentinel 节点;

(2)在可用的 Sentinel 节点上执行 sentinel get-master-addr-by-name <MasterName> 命令来获取 Master 地址和端口号;

(3)获取到 Master 节点信息,执行 role 或者 info replication 命令验证节点;

(4)客户端订阅 Sentinel 频道,Master 节点变化后,Sentinel 发布频道消息通知客户端。

10. redis-cluster

  • 无中心结构,所有节点彼此互联。

  • 任一节点的fail是通过集群中超过半数的节点检测失效时才生效,最少需要三个节点。

  • 任一节点失效,集群就不可用了,所以每个节点必须至少有一个 Slave 节点,故障转移时使用。
  • 客户端连接集群任一可用节点即可。

  • 集群把所有的物理节点映射到 [0-16383] 哈希槽上。

  集群内置了 16384 个哈希槽,当需要存储一个 key/value 时,redis 先对 key 使用 CRC16 算法得到一个数值,再把这个数值对 16384 求余运算。这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽,redis 将哈希槽映射到不同的节点。

posted @ 2020-04-25 17:38  PIPO2  阅读(163)  评论(0编辑  收藏  举报