Redis是什么?

  1. 是一个完全开源免费的key-value内存数据库
  2. 通常被认为是一个数据结构服务器,主要是因为其有着丰富的数据结构 strings、map、 list、sets、 sorted sets

Redis数据库

​ 通常局限点来说,Redis也以消息队列的形式存在,作为内嵌的List存在,满足实时的高并发需求。在使用缓存的时候,redis比memcached具有更多的优势,并且支持更多的数据类型,把redis当作一个中间存储系统,用来处理高并发的数据库操作

redis特点

  • 持久化:将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用
  • 支持多种数据类型:String, list, set, zset, hash
  • 数据备份:master(主) - slave(从) 模式的数据备份
  • 高性能:读速度110000次/s,写速度81000次/s
  • 原子性:所有操作都是原子性的

    Redis缺点

  • 是数据库容量受到物理内存的限制,不能用作海量数据的高性能读写,因此Redis适合的场景主要局限在较小数据量的高性能操作和运算上。
  • Redis较难支持在线扩容,在集群容量达到上限时在线扩容会变得很复杂。为避免这一问题,运维人员在系统上线时必须确保有足够的空间,这对资源造成了很大的浪费。

什么是Redis持久化?Redis有哪几种持久化方式?优缺点是什么?

持久化就是把内存的数据写到磁盘中去,防止服务宕机了内存数据丢失。

Redis 提供了两种持久化方式:RDB(默认) 和AOF 

RDB

RDB的持久化方式是通过快照方式完成的,当符合某种规则时,会将内存中的数据全量生成一份副本存到硬盘行,这个过程称为“快照”。

快照执行原理

(1) Redis使用fork函数复制一份当前进程(父进程)的副本(子进程)

(2) 父进程继续处理来自客户端的请求,子进程开始将内存中的数据写入硬盘中的临时文件

(3) 当子进程写完所有的数据后,用该临时文件替换旧的RDB文件,至此,一次快照操作完成

(4) 注意:在执行fork的时候操作系统(类Unix操作系统)会使用写时复制(copy-on-write)策略,即fork函数发生的一刻,父进程和子进程共享同一块内存数据,当父进程需要修改其中的某片数据(如执行写命令)时,操作系统会将该片数据复制一份以保证子进程不受影响,所以RDB文件存储的是执行fork操作那一刻的内存数据。所以RDB方式理论上是会存在丢数据的情况的(fork之后修改的的那些没有写进RDB文件)

快照备份规则

(1) 根据配置规则进行自动快照:在配置文件redis/etc/redis.conf内,进行自定义快照条件。在快照条件缺省的条件下,快照会存放在简介中介绍的dump.rdb文件中。自定义快照条件则是通过「save time(时长, 单位s) num(变化key的个数) 」对进行快照备份的频率进行设置,例如「 save 900 1 」表示15分钟内1个key发生变化,进行快照备份。每个快照条件单独占一行,条件之间是‘or '或的关系,满足任何一个就进行自动快照备份

(2) 用户执行SAVE,BGSAVE命令:除了让Redis自动进行快照外,当我们需要重启,迁移,备份Redis时,我们也可以手动执行SAVE或BGSAVE命令主动进行快照操作。

  • SAVE命令当执行SAVE命令时,Redis同步进行快照操作,期间会阻塞所有来自客户端的请求,所以放数据库数据较多时,应该避免使用该命令;
  • BGSAVE命令从命令名字就能看出来,这个命令与SAVE命令的区别就在于该命令的快照操作是在后台异步进行的,进行快照操作的同时还能处理来自客户端的请求。执行BGSAVE命令后Redis会马上返回OK表示开始进行快照操作,如果想知道快照操作是否已经完成,可以使用LASTSAVE命令返回最近一次成功执行快照的时间,返回结果是一个Unix时间戳。

(3) 执行FLUSHALL命令:当执行FLUSHALL命令时,Redis会清除数据库中的所有数据。需要注意的是:不论清空数据库的过程是否触发了自动快照的条件,只要自动快照条件不为空,Redis就会执行一次快照操作,当没有定义自动快照条件时,执行FLUSHALL命令不会进行快照操作。

(4) 执行复制(replication)操作:当设置了主从模式时,Redis会在复制初始化时进行自动快照。

数据迁移

问题:有三个Redis,分别命名为Redis1、Redis2、Redis3;现在希望将Redis1和Redis2中的数据迁移到Redis3中,同时不希望Reds3中rdb的数据丢失,那么如何将三个rdb文件融合为一个呢?

解决方式一:将Rdeis3先设置为Redis1的从数据库,进行数据同步;然后在将Redis3设置为Redis2的从数据库,进行数据同步。

解决方式二:(注意该方法适合用于临时恢复和导出数据,且需要关闭AOF持久化功能)

(1) 复制RDB文件:将Redis1的dump1.rdb、Redis2的dump2.rdb复制到Redis3的data目录下

(2) 获取RDB文件大小:dump1.rdb大小 = 27441041、dump2.rdb大小 = 37、dump3.rd大小 = 570214520

(3) 按照文件合并顺序截取文件:dump1.rdb为文件头,去掉尾部的9个字节:「dd bs=1 if=dump1.rdb of=dump.rdb count=27441032」

      dump2.rdb为中间文件,去掉头部的11个字节,去掉尾部的9个字节:「dd bs=1 if=dump2.rdb of=res2.rdb count=17」

      dump3.rdb为尾部文件,去掉头部的11个字节,去掉北部的8个字节:「dd bs=1 if=dump3.rdb of=res3.rdb count=570214501」

(4) 合并截取文件:cat res2.rdb >> dump.rdb

cat res3.rdb >> dump.rdb

(5) 验证备份文件:执行命令「redis-check-rdb dump.rdb 」

(6) 修改配置文件:将redis.conf中的rdbchecksum设置为no

(7) 重启Redis3,所有备份数据在数据库内生效

AOF

AOF的持久化方式是将Redsi执行的每一条命令追加写到硬盘文件中,这一过程坑你会降低Redis的性能,但大部分情况这个影响是可以接收的,默认情况下,AOF的持计划功能是关闭的,可以通过修改redis.conf文件的配置进行功能开启,本分文件的存储路径与dump.rdb是一致的。

实现过程

(1) 概述:AOF以纯文本的形式记录Redis执行的写命令,将Redis按照上面提到的配置打开AOF持久化功能,执行命令「set test ceshi」,打开/home/map/mapcontent-odp_lihan/redis/key-redis/data/appendonly.aof 查看持久化内容信息,其文本中记录命令的规则这里不展开细说,感兴趣可以深入学习一下

Python面试汇总——redis

(2) AOF文件重写:AOF记录用户操作Redis的命令行,但如果每一条命令行都记录,那appendonly.aof文件会变的特别大,所以Redis设计了AOF文件重写机制。重写机制就是重新生成一份AOF文件,新的AOF文件中一条记录的操作只会有一次,而不像老文件中存在对同一数值进行多次操作的现象。重写的实现过程与RDB备份快照的过程类似,也是fork一个进程,直接遍历数据,写入新的AOF临时文件。在写入新文件的过程中,所有的写操作日志还是会写到原来老的AOF文件中,同时还会记录在内存缓冲区中。当重完操作完成后,会将所有缓冲区中的日志一次性写入到临时文件中。然后调用原子性的rename命令用新的 AOF文件取代老的AOF文件。

如下图中的操作,重写后的AOF文件只会记录最后一条命令「set test ceshi3」

Python面试汇总——redis

AOF文件重写规则

(1) 根据配置规则进行自动重写:在配置文件redis/etc/redis.conf内,进行自定义重写条件。

  • auto-aof-rewrite-percentage:目前AOF文件的大小超出上一次重写时AOF文件大小的百分之多少时进行重写,如果没有重写过就以启动时AOF文件的大小为标准
  • auto-aof-rewrite-min-size:当AOF文件的大小超过设定的数字时进行重写

通常以上两个配置是一起使用

(2) 用户执行BGREWRITEAOF命令进行重写:执行BGREWRITEAOF命令后,AOF文件中仅保留了「set test ceshi3」命令

同步硬盘

虽然每次执行更改数据库的内容时,AOF都会记录执行的命令,但是由于操作系统本身的硬盘缓存的缘故,AOF文件的内容并没有真正地写入硬盘,在默认情况下,操作系统会每隔30s将硬盘缓存中的数据同步到硬盘,但是为了防止系统异常退出而导致丢数据的情况发生,我们还可以在Redis的配置文件中配置这个同步的频率

RDB与AOF的优劣势

二者选择的标准,就是看系统是愿意牺牲一些性能,换取更高的缓存一致性(AOF),还是愿意写操作频繁的时候,不启用备份来换取更高的性能,待手动运行save的时候,再做备份(RDB)

RDB的优势:(1) 数据可移植性好:仅存在一个数据备份文件,对数据压缩后可以轻松转移到其他存储介质上;(2) 性能最大化:RDB本分方式只需fork一个子进程,由子进程完成全部持久化工作,极大的避免了服务进程执行IO操作,当数据集很大时,其效率也高于AOF机制;

RDB的劣势:(1) 在数据未持久化之前出现宕机现象,那么未持久化的数据会丢失;(2) 当数据集较大时,fork子进程的备份工作会导致服务整体停止对外服务几百毫秒,甚至1秒

AOF的优势:(1) 数据安全性更高:写Redis命令采用append的模式记录,出现宕机,原有数据不会丢失,写入了一半数据就出现了系统崩溃问题,不用担心,在Redis下一次启动之前,我们可以通过redis-check-aof工具来帮助我们解决数据一致性的问题;

AOF的劣势:(1) 相同数据集,AOF文件大于RDB文件,且恢复速度慢于RDB;(2) 数据同步效率低于RDB

Redis主从复制原理

原理概述:一主多从 (1个master,多个slave) ;全量同步&增量同步。

一主多从:主数据库进行读写操作,当发生写操作时自动将数据同步到从数据库;从数据库一般只进行读操作,并接收主数据库同步过来的数据,一个主数据库可以有多个从数据库,但一个从数据库只能有一个主数据库。通过这种架构能够很好的实现读写分离,从而提高服务器的负载能力。

全量同步:

    • 当数据库启动时,会向主数据库发送sync命令
    • 主数据库接收到sync命令会开始在后台保存快照(执行rdb操作),并用缓存区记录后续的所有写操作
    • 当主服务器的快照保存完成后,redis会将快照文件发送给从数据库
    • 从数据库接收快照文件后,会丢弃所有的旧数据,载入收到的快照
    • 主服务器的快照发送完毕后,开始向从服务器发送缓冲区中的写命令
    • 从服务器完成对快照对载入,开始接收命令请求,并执行来自主服务器缓冲区的写命令

增量同步:

    • 从数据库初始化工作完成后,主数据库发生的写操作同步到从数据库到过程为增量同步
    • 增量复制的过程主要是主服务器每执行一个写命令就会向从服务器发送相同的写命令,从服务器接收并执行收到的写命令。

全量&增量同步选择:

    • 主数据库启动创建链接时,采用全量同步
    • 全量同步结束后,采用增量同步
    • 如果需要,slave在任何时候都可以发起全量同步,redis的策略是首先尝试增量同步,如果失败,进行全量同步

redis主从配置:

(1)在slave的redis.conf中修改配置信息,ip : port对应master的ip : port,masterauth参数对应master的密码,有则配置,没有则不用关

Python面试汇总——redis

(2)启动slave:./bin/redis-server etc/redis.conf

(3)登录master:./redis-cli -p 10108,输入info,查看slave是否配置成功;

Python面试汇总——redis      

(4)登录slave也可以查看:./redis-cli -p 10101,输入info

Python面试汇总——redis

(5)如果master挂了,需要将slave切换成master登录slave:./redis-cli -p 10101,执行:SLAVEOF NO ONE,执行:info

Python面试汇总——redis

(6)master修复后,可在slave上执行:SLAVEOF 127.0.0.1 10108(SLAVEOF master_ip master_port),重新将其挂接在master上

(六) Redis的原子性

原子性概念:一个事务中的所有操作,要么全部完成,要不全部不完成,不会结束在之间某个环节,Redis的原子性就是指其操作命令要么执行,要么不执行

Redis操作原子性的原因:Redis是单线程的,线程是操作系统运算调度的最小单元

相关文章: