Redis 学习笔记系列一

一.什么是Redis单线程?

大家都知道Redis是单线程运行,那到底Redis为什么要设计成单线程模式?具体的单线程模式是什么样子的?
Redis 采用C语言编写,是一种key-value形式的内存数据库,可用于缓存,消息中间件,分布式锁等业务场景。

Redis为什么采用单线程

  1. redis 直接与内存交互速度上很快,官方提供的数据可达到10000+QPS(query per second)
  2. redis 的快主要归功于他的数据结构,这方面另外写篇文章学习一下。
  3. redis 采用单线程,避免了因为线程上下文切换和竞争带来的CPU消耗,不存在加锁解锁带来的消耗
  4. redis 采用I/O多路复用技术

什么是I/O多路复用

I/O多路复用(事件驱动),是指采用系统提供的select/epoll/poll等方法同时监听多个描述符的读写状态(当状态未就绪时则进行阻塞,就绪后再进行读写操作避免了无用操作),这些描述符的I/O状态能在一个线程内交替并发顺序的进行。
这里的多路是指多个网络连接, 复用指复用一个同一个线程。这样就尽量避免了多个连接的网络I/O消耗

在这里插入图片描述

单线程的缺点

  1. 因为使用单线程操作,在执行操作时间长的命令时会导致并发的下降
  2. 使用单个CPU,可以打开多个实例使用master-slave模式,会cluster模式等

二. Redis支持事务么?

redis是支持事务的,但redis的事务并非严格意义上符合ACID原则上的事务。
如果有一组命令是需要同时成功或者失效的redis事务可以支持。
redis事务的用法,涉及到四个命令: multi(开启事务),exec(执行事务),discard(取消事务),watch(监听)

multi
set k1 2
set k2 3
set k3 4
exec

当开启multi,后面运行的命令并不会立即执行,而是放入执行队列中。等运行exec命令时才会从队列中取出逐一执行。如果不想执行了可以使用discard命令,清楚队列中的命令。
redis还提供watch方法,监听事务队列中的key,它会采用CAS方式去比较在执行exec命令前是否key值有被修改过,如果有的话就取消此次事务。

事务中的错误一般有两种:

  1. 在exec执行之前,由于命令存在语法错误,这种情况事务会失效。
  2. 在exec执行之后,这种情况一般发生在比如使用了错误的数据类型操作。发生错误之前的命令是可以被正常执行的。这就不符合事务的原子性了。但redis为了保证运行的速度,且认为这些错误都是可以在开发过程中规避的。

三. 什么是Redis的pipelining

pipeline是流水线的概念,在redis里面可以理解为批量的命令请求,降低了服务端的性能消耗。
客户端可以进行批量命令的传输和批量命令的返回。

二.Redis持久化策略

redis是基于内存的数据库,那如何将数据持久化到硬盘中呢?主要有两种方式,一种是基于RDB的快照方式。一种是基于AOF的命令集方式。接下来看看下两种命令方式有和不同:

RDB

就是将内存已快照的形式保存在磁盘中,redis会在指定的时间间隔内把内存中的数据已二进制文件的形式写入到磁盘内。这是redis默认的持久化模式生成的文件是dump.rdb,那redis什么时候会触发RDB呢?

  1. save命令,当前命令会阻塞redis服务器,使其不能执行其他的命令。
  2. dgsave(backgroud save) ,redis进程会fork出一个子进程用于RDB持久化操作,操作完整之后进程退出。一般都采用此中方式进行持久化。
  3. 自动触发,这里有一些配置项目
配置项含义默认值
save m n表示m秒内数据存在n此修改时触发bgsave例如:save 30 3表示30s内数据发生3次修改时则触发
stop-writes-on-bgsave-error当bgsave发生错误时默认停止数据的写入,防止更坏情况的发生yes
rdbcompression是否对缓存的数据进行压缩yes
rdbchecksum是否对缓存数据进行CRC64校验(数据在计算机各部件中进行传输时一般使用校验码来判断传输数据是否错误),redis采用CRC64-16进行校验,但这会造成性能的消耗。建议关闭yes
dbfile设置文件名dump.drb
dir文件存储的目录

RDB主从同步的实现:
(1)第一个slave向master发送同步请求时,master想将rdb文件全部dump下来传送到slave,然后再将缓存中的数据传到slave
(2)后面master将快照直接传给slave,当网络断开会重新连接时又会重复以上两各步骤r

redis的主从复制是建立在RDB的基础上的

RDB的优劣

优势:

  1. rdb能进行全量的数据存储,磁盘空间紧凑非常适合容灾和数据备份
  2. 备份时会fork子进行进行操作,主进程没有io操作
  3. 在进行大数据量的恢复时rdb比aof快
    劣势:
    在数据快照期间修改的数据不会保存,容易造成数据的丢失
    全量数据备份消耗的时间比较多

AOF

Redis将操作的每一条命令进行记录追加到AOF文件中。AOF可以理解为操作的日志。
这些写入的操作是已redis协议的格式保存的,当不小心执行了flushall删除了所有数据后,可以删除aof最后一条命令,重启redis用已恢复数据。
AOF的持久化触发有三种方式:

  • always 每次命令直接将命令写入磁盘中
  • everysec 每秒写入,错误时会丢失一秒的数据。在everysec未触发之间命令是卸载redis的缓存中的
  • no 不记录AOF

AOF会涉及到一个重写原理调用bgrewriteaof命令,是当AOF文件过大时用于压缩文件:
当AOF文件过大时,redis会模范RDB,将redis内存中的所有数据用命令的方式写入新的AOF文件。
这里首先redis会fork出一个子进程用已将已经存在内存中的数据写入新的AOF文件,同时将新的命令记录一边记录到缓存中,一边追加到旧的AOF文件末尾。这样如果bgrewriteaof失败,也不会影响。等新的AOF文件写完时,在将缓存中记录的新的命令追加到新AOF文件中,同时删除旧的文件。将缓存中数据追加到AOF和rename AOF文件主进程都是阻塞的

AOF文件的损坏:
当redis在对AOF文件进行写入时如果断电之类的造成写入失败可能会损坏aof文件,这时候redis重启时就不能进行数据的恢复。这时候可以按下列方法修复aof文件:

  1. 能做到对aof文件进行备份
  2. 使用redis-check-aof 对文件进行修复
redis-check-aof –fix
  1. 可使用diff -u对修复前后的数据进行对比
  2. 重启redis等待aof文件载入修复

从RDB转到AOF:
(1) 复制dump.rdb文件
(2)执行下列两条命令

// 开启AOF,此时redis会进入阻塞至到aof文件写入文件,开始正常的追加
redis-cli config set appendonly yes
// 关闭rdb,也可以不执行使两种模式都存在
redis-cli config set save “”

(3)配置redis.conf 文件已免重启后配置丢失。

结下来来实际实试验以下redis的持久化机制。
这里先采用单机模式下的redis,使用rdb方式进行数据备份:
先编写配置文件:

port 6379 #端口
bind 127.0.0.1 #绑定地址
save 10 1 #表示10s内发生1次key修改则进行rdb记录
rdbcompression yes #开启压缩
dir /data #rdb文件存储的路径

使用docker启动redis挂在配置文件

docker run -p 6739:6379 -v /Users/heroschool/workspace/applications/redis/redis.conf:/etc/redis/redis.conf -v /Users/heroschool/workspace/data:/data -d redis redis-server /etc/redis/redis.conf
set key1 1
set key2 2
set key3 3

往redis中添加三条数据,后关闭redis,可以看到data目录下生成了dump.rdb文件。这里因为我们是用docker启动的,所以将整个docker容器删除,看看数据能不能恢复?

root@68f281d50939:/data# redis-cli
127.0.0.1:6379>
127.0.0.1:6379> get key1
"1"

运行命令后可以看到数据已经恢复了。
再来试下AOF方式,先修改配置文件

port 6379
bind 127.0.0.1
appendonly yes
dir /data

修改appendonly 命令,然后重新启动redis容器,重新运行插入命令,这时候可以看到存储文件已经变成appendonly.aof了

-rw-r--r--  1 heroschool  staff   127B  5 20 22:26 appendonly.aof
➜  data git:(master) ✗ pwd
/Users/heroschool/workspace/data

然后我们同样删除容器,再恢复

root@fcfef7f44c30:/data# redis-cli
127.0.0.1:6379>
127.0.0.1:6379>
127.0.0.1:6379> get key1
"1"
127.0.0.1:6379> get key2
"ttt"
127.0.0.1:6379> get key3
"this is test"
127.0.0.1:6379>

可以看到数据也正常恢复了。

参考资料

详解Redis中两种持久化机制RDB和AOF
深入理解redis持久化
深入理解Redis

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值