Redis 那些事( 一 )

Redis 是什么?

REmote Dictionary Server (Redis) 是由Salavtore Safilippo 编写的Key-Value 存储系统,它是一个开源的使用ANIS C 编写,遵守PSD协议,支持网络,可基于内存,分布式,可选持久性的存储数据库,并提供多种语言API。
Redis 通常被称为数据结构服务器,因为值(Value)可以是字符串(String)、哈希(Hash),列表(List),集合(sets)和有序集合等类型。

为什么要用Redis

  • 性能高:Redis 以其极高的性能而著称,能够支持每秒数十万次的读写操作,使得Redis 成为处理高并发的理想选择,尤其是在需要快速响应的场景中,如:缓存,会话管理,排行榜等
  • 丰富的数据类型:Redis 不仅支持基本的键值存储,还提供了丰富的数据类型,包含字符串,哈希表,集合,有序集合等
  • 原子性操作:Redis的所有操作都是原子性的,这意味着操作要么完全执行,要么完全不执行,这种特性对于确保数据的一致性和完整性至关重要。
  • 持久化:Redis 支持数据的持久化,可以i将内存中的数据保存到磁盘中,以便系统重启后恢复数据,这位Redis提供了数据安全性,确保数据不会因为系统故障丢失。
  • 支持发布/订阅模式:Redis 内置了发布订阅模式(Pub/Sub),允许客户端之间通过消息传递进行通讯,这使得Redis可以作为消息队列和实时数据传输平台。
  • 单线程模型:尽管Redis 是单线程的,但它通过高效的事件驱动模型来处理并发请求,确保了高性能和低延迟,单线程模型也简化了并发控制的复杂性。
  • 主从复制:Redis 支持主从复制,可以通过从节点来备份数据或分担读请求。同哈皮手机壳i的可用性和系统的伸缩性。
  • 应用场景广泛:Redis 被广泛应用于各种场景,包括但不限于缓存系统,会话存储,排行榜,实时分析,地理空间数据索引等等。
  • 社区支持:Redis 拥有一个活跃的开发者社区,提供了大量的文档,教程和三方库,这为开发者提供了强大的支持和丰富的资源。
  • 跨平台兼容性:Redis 可以在多种操作系统上运行,包括Linux,Mac OS和Windows ,这使得它能够在不同的技术栈中灵活部署。

Redis在Linux上的安装

下载地址 http://redis.io/download
安装步骤:

yum install gcc

下载Redis 源码文件

wget http://download.redis.io/releases/redis-5.0.3.tar.gz
tar -zxvf redis-5.0.3.tar.gz
cd redis-5.0.3

进入到解压好的redis-5.0.3目录下,进行编译与安装

make

进入conf 目录修改配置文件

daemonize yes  #后台启动
protected-mode no  #关闭保护模式,开启的话,只有本机才可以访问redis
# 需要注释掉bind
#bind 127.0.0.1(bind绑定的是自己机器网卡的ip,如果有多块网卡可以配多个ip,代表允许客户端通过机器的哪些网卡ip去访问,内网一般可以不配置bind,注释掉即可)

启动服务:

src/redis-server redis.conf

验证是否启动成功

ps -ef | grep redis

进入Redis客户端

src/redis-cli

退出客户端

quit

退出Redis服务

pkill redis-server 
kill 进程号                       
src/redis-cli shutdown 

Redis 指令

  1. keys
    1. 全量遍历键:用来列出所有满足正则字符串规则的keys,当Redis 中的数据量比较大时,需要避免使用。因为它这时的性能比较差,会造成Redis 卡顿。
  2. scan 渐进式遍历键
    1. 语法如下:Scan cursor [Match pattert] [Count count]
    2. scan 指令提供了三个参数,第一个是Cursur整数值(hash 桶的索引值)。第二个是正则模式,第三个是一次遍历的key的数量。(注意,这里是一个参考值,底层不一定遍历了这么次。)并不会返回符合条件结果的数量。比如:第一次遍历时,cursur 为 0 ,然后将返回结果中第一个整数值作为下一次遍历的cursor ,一直遍历到返回的cursor 的值为0时结束。
    3. 特别注意:scan 并非完美无暇,如果在Scan 的过程中如果有键的变化(增加,删除,修改),那么遍历的效果可能会碰到如下的问题:新增的键可能没有被遍历到,遍历出了重复的键等问题,也就是说scan 并不能保证完整的遍历出来所有的键。
  3. info 查看Redis 服务运行的信息,分为9快,每块的都有非常多的参数,这9块分别时
    1. Server 服务器运行的环境参数
    2. Clients 客户端相关信息
    3. Memory 服务器运行内存统计数据
    4. Persistence 持久化信息
    5. Stats 通用统计数据
    6. Replication 主从复制相关信息
    7. CPU CPU 使用情况
    8. Cluster 集群信息
    9. KeySpace 键值对统计数量信息

Redis的单线程和高性能

Redis 是单线程吗 ?

Redis 的单线程主要是指Redis 的网络IO 和键值对的读写是由一个线程来完成的,这也是Redis对外提供键值存储服务的主要流程。但是Redis的其他功能,比如持久化,异步删除,集群数据同步等等,其实都是由额外的线程执行的。

Redis单线程为什么还能那么快?

因为它的所有数据都在内存中,所有的运算都是内存级别的运算,而且单线程避免了因切换线程所带来的性能损耗,正因为Redis 是单线程,所以要小心使用Redis指令。对于那些耗时的指令(比如Keys),一定要谨慎使用,一不小心就可能会导致Redis 卡顿。

Redis 单线程是如何处理那么多的并发客户端连接

Redis 的IO 多路复用:Redis 利用Epoll 来时先IO的多路复用,将连接信息和事件放在队列中,依次放到文件事件分派器,由事件分发器分发给事件处理器。
下图为处理并发客户端链接的示例流程图
image.png

这里需要注意的时,在Redis.conf 文中修改,maxclients

Config get maxClients

Redis持久化

RDB 快照(Snapshot)

默认情况下,Redis 会将内存数据库保存到一个名为dump.rdb的二进制文件中。在默认情况下是在60s内修改1000次时会触发这个保存条件。
当然也可以通过对Redis 进行设置,让它可以满足在 “N 秒内数据集中至少由M个改动”这一条件被满足时,自动保存数据库
举例说明:

 save  60 1000  #表示在60S 内,至少由1000个键值被改动就会触发保存

当然还可以手动执行生成RDB 快照,进入Redis 客户端执行命令save 或者bgsave 可以生成dump.rdb 文件,每次命令执行都会将所有redis内存快照到一个新的rdb文件中,并覆盖原有的rdb文件。

bgsave 的写时复制机制(COW)

redis 借助操作系统提供的写时复制机制(Copy-On-Write).生成快照的同时,依然可以正常处理命令。简单来说,bgsave 子进程是由主进程fork 生成的,可以共享主进程的所有内存数据。bgsave 子进程运行后,开始读取主线程的内存数据,并把它们写入到RDB文件,此时,如果主线程对这些数据也都是度的操作,那么主线程和bgsave 的子进程互不影响,但是,如果主进程一定要修改数据,那么这块儿数据就会被复制一份出来,生成该数据的副本数据。然后,bgsave 子进程会把这个副本数据写入RDB文件按,而在这个过程中,主线程仍然可以直接修改原来的数据。
save 和 bgsave的对比

命令savebgsave
IO 类型同步异步
是否阻塞Redis 命令阻塞否(在线程的子进程中调用fork函数是会有短暂的阻塞)
复杂度O(n)O(n)
优点不会额外消耗内存不会阻塞客户端命令
缺点阻塞客户端命令需要在Fork 子进程,消耗内存

配置自动生成的RDB 文件后台配合的是bgsave

AOF (Append-only-file)

AOF 功能模式是不开启的,需要在配置文件中打开AOF 功能

# appendonly yes  //放开这个注释

这里有三个选项:

  1. appendfsync always :表示每次有命令就追加到AOF 文件中,非常慢,但是非常安全
  2. appendfsync everysec:表示每秒fsync一次,足够快,并且故障时只会丢失1秒钟的数据
  3. appendfsync no : 表示从不Fsync,将数据交给操作系统来处理,更快,也更不安全。

这里推荐的是:appendfsync everysec ,并且也是默认措施,一秒钟执行一次fsync的策略,可以兼顾速度和安全性。
快照功能并不是非常耐久(durabler):如果Redis因为某些原因而造成的宕机,那么服务器将丢失最新写入,且仍未保存的数据。所以从Redis 1.1 开始,Redis 增加了一种完全耐久的持久化方式:AOF 持久化。将修改的每条指令记录进文件appendonly.aof 中,(先写入OS cache 中,每隔一段时间fsync到磁盘。)
举例说明一下:

set moran 666

*3
set
$5
zhuge
$3
666

这是一样Resp 协议的数据格式,*号后面的数字表示命令有多少个参数,$后面的数字表示这个参数有几个字符。
注意:如果执行带过期时间的set命令,aof文件里面记录的并不是原始命令,而是记录key 过期的时间戳

set zhangsan 888 ex 1000
*3
$3
set
$8
zhangsan
$3 
666
*3
$9
PEXPTIREAT
zhangsan
$13
1604249786301

AOF 重写

AOF 文件中可能会有太多没用的指令,所以AOF 会定期根据内存的最新数据生成aof文件。
举例说明:

127.0.0.1:6379> incr readcount
 (integer) 1
 127.0.0.1:6379> incr readcount
 (integer) 2
 127.0.0.1:6379> incr readcount
 (integer) 3
 127.0.0.1:6379> incr readcount
 (integer) 4
 127.0.0.1:6379> incr readcount
 (integer) 5

这时在redis中,aof 重写后的内容会变成

*3
set
$2
readCount
$1
5

在配置文件中可以配置AOF 自动重写的频率

 # auto‐aof‐rewrite‐min‐size 64mb //aof文件至少要达到64M才会自动重写,文件太小恢复速度本来就很快,重写的意义不大
2 # auto‐aof‐rewrite‐percentage 100 //aof文件自上一次重写后文件大小增长了100%则再次触发重写
手动重写AOF

进入redis 客户端,执行

bgrewriteof #进行AOF 重写

这里AOF 重写是在Redis fork出来的子进程中(与bgsave 的命令类似)。不会对redis正常处理命令有太多的影响。

RDB 与 AOF 对比

命令RDBAOF
启动优先级
体积
恢复速度
数据安全性容易丢失数据根据策略决定

Redis 4.0 混合持久化

重启 Redis 时,我们很少使用 RDB来恢复内存状态,因为会丢失大量数据。我们通常使用 AOF 日志重放,但是重放 AOF 日志性能相对 RDB来说要慢很多,这样在 Redis 实例很大的情况下,启动需要花费很长的时间。 Redis 4.0 为了解决这个问题,带来了一个新的持久化选项——混合持久化
通过如下配置可以开启混合持久化(必须先开启aof)

# aof‐use‐rdb‐preamble yes

如果开启了混合持久化,AOF在重写时,不再是单纯将内存数据转换为RESP命令写入AOF文件,而是将
重写这一刻之前的内存做RDB快照处理,并且将RDB快照内容和增量的AOF修改内存数据的命令存在一
起,都写入新的AOF文件,新的文件一开始不叫appendonly.aof,等到重写完新的AOF文件才会进行改
名,覆盖原有的AOF文件,完成新旧两个AOF文件的替换。
于是在 Redis 重启的时候,可以先加载 RDB 的内容,然后再重放增量 AOF 日志就可以完全替代之前的
AOF 全量文件重放,因此重启效率大幅得到提升。
image.png
Redis 数据备份策略

  1. 写crontab定时调度脚本,每小时都copy一份rdb或aof的备份到一个目录中去,仅仅保留最近48小时的备份
  2. 每天都保留一份当日的数据备份到一个目录中去,可以保留最近1个月的备份
  3. 每次copy备份的时候,都把太旧的备份给删了
  4. 每天晚上将当前机器上的备份复制一份到其他机器上,以防机器损坏
  • 23
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Monkey@

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值