Redis缓存

目录

一·Redis缓存概念

二.Redis特性

三.Redis对比memcached

四.编译安装redis

五.redis的基本命令

六.redis 多实例

七.redis的配置优化

1.redis主要配置选项

2.config动态修改配置

3.慢查询

4.持久化

4.1  RDB模式

4.1.1 RDB模式工作原理

4.1.2  RDB相关配置

4.1.3  实际RDB备份操作

4.1.4  自动触发RDB

4.1.5  实现RDB方式

4.1.6  RDB优缺点

4.2  AOF模式

4.2.1  AOF相关配置

4.2.2  实例

4.2.3  AOF重写机制

4.2.4  AOF模式优缺点

4.3  总结

八.Redis的缓存问题和解决方案

1.redis的三大缓存问题

2.缓存雪崩的解决方案

3.缓存穿透的解决方案

4.缓存击穿的解决方案

九.如何保证MySQL和Redis的数据一致

十.Redis的优化有哪些


一·Redis缓存概念

  1. 内存存储: Redis 将数据存储在内存中,因此读取和写入操作非常快速。这使得 Redis 特别适合用作高性能缓存,可以显著减少应用程序从传统数据库中读取数据的次数,加快响应速度。

  2. 键值存储: Redis 使用键值对来存储数据,每个键都是唯一的,并且与一个值(可以是各种数据类型)关联。这种简单的数据模型使得 Redis 在存储和检索数据时非常高效。

  3. 数据结构支持: Redis 支持多种数据结构,如字符串(Strings)、哈希表(Hashes)、列表(Lists)、集合(Sets)、有序集合(Sorted Sets)等。这些数据结构能够满足不同的应用场景需求,例如,可以将复杂的对象序列化为字符串存储,或者使用列表来存储日志信息。

  4. 持久化: 虽然 Redis 主要是一个内存数据库,但它也可以通过将数据异步地持久化到磁盘上,以便在重启后恢复数据。Redis 提供了不同的持久化选项,如快照(snapshotting)和日志(append-only file),确保数据在重启或故障恢复时不会丢失。

  5. 缓存有效性: Redis 允许设置键的过期时间,一旦过期,Redis 将自动删除该键及其关联的值。这种机制使得 Redis 缓存可以自动管理数据的更新和失效,从而避免数据过时或者浪费内存。

  6. 分布式支持: Redis 提供了一些特性,如主从复制和分片(sharding),使得它可以水平扩展以处理更大的数据量和更高的并发请求。这些特性使 Redis 成为处理大规模数据和高并发访问的理想选择。

缓存实现流程

数据更新操作流程:

 数据读取操作流程:

二.Redis特性

  • 速度快: Redis 是基于内存的数据存储系统,因此访问速度非常快,可以处理高达 10 万次查询每秒(QPS)以上的请求。

  • 单线程: Redis 使用单线程模型来处理客户端请求,通过避免多线程的竞争和同步问题来简化实现并提高了性能。

  • 持久化: Redis 提供了多种持久化机制,可以将内存中的数据保存到磁盘上,确保数据不会因服务器重启而丢失。

  • 支持多种数据结构: Redis 不仅仅支持简单的键值对存储,还支持字符串、哈希、列表、集合、有序集合等复杂数据结构,每种数据结构都有对应的丰富操作。

  • 支持多种编程语言: Redis 提供了丰富的客户端库,支持多种编程语言(如 Python、Java、C#、Node.js 等),使得开发者可以方便地在各种环境下使用 Redis。

  • 功能丰富: Redis 提供了多种高级功能,如 Lua 脚本支持、发布与订阅、事务处理、流水线操作等,可以满足各种复杂应用场景的需求。

  • 简单: Redis 的核心代码非常精简,易于理解和维护。它不依赖外部库,安装和配置也相对简单。

  • 主从复制: Redis 支持主从复制机制,可以将数据从主节点复制到若干个从节点,用于提高读取性能和数据冗余。

  • 支持高可用和分布式: Redis 提供了 Sentinel 和 Redis Cluster 两种机制来实现高可用性和分布式部署,保证系统在节点故障或扩展时的稳定性和可靠性。

三.Redis对比memcached

  1. 数据结构支持

    Redis:支持丰富的数据结构,如字符串、哈希、列表、集合、有序集合等,每种数据结构都有专门的操作命令,能够进行更复杂的数据操作和计算。这使得 Redis 不仅仅是一个简单的键值存储,还可以用于更复杂的数据处理和计算场景。
    Memcached:主要支持键值对的存储和获取操作,没有像 Redis 那样的复杂数据结构支持,更适合简单的缓存场景。
  2. 数据持久化

    Redis:支持多种持久化方式,如 RDB(周期性快照)和 AOF(追加写日志),可以根据需求选择适合的持久化方式来保证数据安全。
    Memcached:不提供持久化功能,数据一般只存在于内存中,重启服务或断电后数据会丢失。
  3. 性能

    Redis:由于其复杂数据结构的支持、单线程模型的优化、异步非阻塞的 I/O 操作等设计,通常能够提供更高的性能和更低的延迟。
    Memcached:专注于简单的键值对存取操作,因此在这方面可能会有更低的延迟,但在复杂数据处理和计算场景下性能不如 Redis。
  4. 分布式支持

    Redis:通过 Redis Cluster 提供分布式支持,可以将数据分片存储到多个节点中,提高了数据的扩展性和容错性。
    Memcached:也支持分布式部署,但通常需要依赖客户端库来实现分片和负载均衡,相对 Redis Cluster 来说管理和配置相对复杂一些。
  5. 应用场景

    Redis:适合需要复杂数据结构支持、高速读写、持久化、分布式等需求的场景,如缓存、实时分析、计数器、队列等。
    Memcached:适合简单的键值对缓存场景,如页面缓存、会话存储等,对于只需要快速存取的应用来说是一个轻量级和高效的选择。

四.编译安装redis

下载当前最新的release版本redis源码包:Index of /releases/

1.安装包

yum -y install gcc jemalloc-devel systemd-devel
#安装依赖环境包
cd /data
wget http://download.redis.io/releases/redis-5.0.7.tar.gz
#下载依赖环境安装包
tar  xvf  redis-5.0.7.tar.gz
#解压

2.编译安装

mkdir -p /apps/redis/{etc,log,data,run}
#创建配置文件,日志,数据等目录
cd /data/redis-5.0.7
#切换到编译安装目录
make PREFIX=/apps/redis install 
#指定redis安装目录

3.配置变量

echo 'PATH=/apps/redis/bin:$PATH' > /etc/profile.d/redis.sh
#配置变量
. /etc/profile.d/redis.sh
#启用变量

4.将源码包中配置文件拷贝到创建的目录中

cp /data/redis-5.0.7/redis.conf /apps/redis/etc/

5.启动redis 

redis-server 是 redis 服务器程序
redis-server  --help

前台启动redis
指定配置文件启动
redis-server /apps/redis/etc/redis.conf

systemd 启动

准备用户修改权限

useradd  -r -s /sbin/nologin redis
#建立一个系统用户不允许登录
chown  -R redis.redis  /apps/redis/
#设置目录权限
ln -s /apps/redis/bin/redis-*  /usr/bin
#设置软链接

准备service文件

vim /usr/lib/systemd/system/redis.service
[Unit]
Description=Redis persistent key-value database
After=network.target


[Service]
ExecStart=/apps/redis/bin/redis-server /apps/redis/etc/redis.conf --supervised systemd
ExecStop=/bin/kill -s QUIT $MAINPID
#Type=notify 如果支持systemd可以启用此行
User=redis
Group=redis
RuntimeDirectory=redis
RuntimeDirectoryMode=0755


[Install]
WantedBy=multi-user.target

启动redis

[root@localhost ~]# systemctl daemon-reload
[root@localhost ~]# systemctl start  redis
[root@localhost ~]# systemctl status  redis

6.处理redis的warning信息

6.1  tcp backlog

backlog参数控制的是三次握手的时候server端收到client ack确认号之后的队列值,即全连接队列

vim /etc/sysctl.conf
net.core.somaxconn = 1024

sysctl -p

6.2  vm.overcommit_memory

内核参数说明:

0、表示内核将检查是否有足够的可用内存供应用进程使用;如果有足够的可用内存,内存申请允许;否则,内存申请失败,并把错误返回给应用进程。
1、表示内核允许分配所有的物理内存,而不管当前的内存状态如何
2、表示内核允许分配超过所有物理内存和交换空间总和的内存

vim /etc/sysctl.conf
vm.overcommit_memory = 1
sysctl -p

6.3  transparent hugepage

警告:您在内核中启用了透明大页面(THP,不同于一般内存页的4k为2M)支持。 这将在Redis中造成延迟和
内存使用问题。 要解决此问题,请以root 用户身份运行命令“echo never> /sys/kernel/mm/transparent_hugepage/enabled”,并将其添加到您的/etc/rc.local中,以便在重启后保留设置。禁用THP后,必须重新启动Redis。

echo never > /sys/kernel/mm/transparent_hugepage/enabled
#临时修改
echo 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' >> /etc/rc.d/rc.local
#永久修改
chmod +x /etc/rc.d/rc.local
systemctl restart redis
vim /apps/redis/log/redis.log

7.修改配置文件

将配置文件/apps/redis/etc/redis.conf 第69行bind 127.0.0.1 修改为bind 0.0.0.0 可以远程连接

将配置文件/apps/redis/etc/redis.conf 中第172行日志地址修改为/apps/redis/log/目录下

文件名为redis.log

 将配置文件/apps/redis/etc/redis.conf  264行备份地址修改为/apps/redis/data/目录下

修改完配置文件重启服务

查看日志文件下生成新的日志

五.redis的基本命令

1.info查看版本信息

redis-cli
#因为是免密登录可以直接登录
ping  #回应PONG
info   #查看版本信息

2.客户端连接redis

redis-cli  -p 端口号  -h 主机  -a 密码

redis-cli -h HOSTNAME/IP -p PORT -a PASSWORD

redis-cli -a <PASSWORD>

本机密码连接

3.支持直接加命令执行

redis-cli    info

4.select

切换数据库,相当于在MySQL的 USE DBNAME 指令

redis共有16个库 0-15

注意: 在 redis cluster 模式下不支持多个数据库,会出现下面错误

5.keys

查看当前库下的所有key,此命令慎用!

KEYS pattern

其中,pattern 是一个符合 Redis Glob 风格的模式,可以包含通配符 *(匹配任意多个字符)和 ?(匹配单个字符)。例如:

  • KEYS *:列出所有键。
  • KEYS user:*:列出所有以 user: 开头的键。
  • KEYS *cache*:列出包含 cache 字符串的所有键。
  • KEYS h?llo:列出以 h 开头,然后是一个任意字符,然后是 llo 的键,例如 hellohallo 等。

6.mset

一次性设置多个key

MSET one 1 two 2 three 3 four 4  # 一次设置 4 个 key OK

7.BGSAVE

手动在后台执行RDB持久化操作

执行bgsave会在数据文件中生成一个dump.rdb文件

8.DBSIZE

返回当前库下所有key数量

9.FIUSHDB

强制清空当前库中所有key ,此命令慎用

flushall 清空当前redis服务器所有库中的所有key,即删除所有数据,此命令慎用!

#生产建议修改配置 /etc/redis.conf 
rename-command FLUSHALL ""
#rename-command 在6.2.4版淘汰了

10.shutdown

# 停止所有客户端

如果有至少一个保存点在等待,执行 SAVE 命令

如果 AOF 选项被打开,更新 AOF 文件

关闭 redis 服务器(server)

如果持久化被打开的话, SHUTDOWN 命令会保证服务器正常关闭而不丢失任何数据。

另一方面,假如只是单纯地执行 SAVE 命令,然后再执行 QUIT 命令,则没有这一保证 —— 因为在执行SAVE 之后、执行 QUIT 之前的这段时间中间,其他客户端可能正在和服务器进行通讯,这时如果执行 QUIT 就会造成数据丢失。

六.redis 多实例

测试环境中经常使用多实例,需要指定不同实例的相应的端口,配置文件,日志文件等相关配置

范例: 以编译安装为例实现 redis 多实例

可以共同使用一个配置文件,建议分开各个文件

1.准备配置文件

首先将原来的redis关闭

[root@node2 etc]#cp  /apps/redis/etc/redis.conf   /apps/redis/etc/redis6379.conf 
[root@node2 etc]#cp  /apps/redis/etc/redis.conf   /apps/redis/etc/redis6380.conf
[root@node2 etc]#cp  /apps/redis/etc/redis.conf   /apps/redis/etc/redis6381.conf
#准备配置文件

2.修改备份文件日志文件pid文件名字和配置文件中端口号

修改备份文件名

[root@node2 etc]#grep dump.rdb redis6379.conf 
#修改 备份文件的名字
dbfilename dump.rdb
[root@node2 etc]#sed -i 's/dbfilename dump.rdb/dbfilename dump6379.rdb/'  redis6379.conf 
[root@node2 etc]#grep dump   redis6379.conf 
[root@node2 etc]#sed -i 's/dbfilename dump.rdb/dbfilename dump6380.rdb/'  redis6380.conf 
[root@node2 etc]#sed -i 's/dbfilename dump.rdb/dbfilename dump6381.rdb/'  redis6381.conf

修改日志文件名

[root@node2 etc]#grep   "logfile"  redis6379.conf 
logfile ""

[root@node2 etc]#sed  -i  's#logfile ""#logfile /apps/redis/log/redis6379.log#' 
redis6379.conf 
[root@node2 etc]#grep   "logfile"  redis6379.conf 
logfile /apps/redis/log/redis6379.log

[root@node2 etc]#sed  -i  's#logfile ""#logfile /apps/redis/log/redis6380.log#' 
redis6380.conf 
[root@node2 etc]#grep   "logfile"  redis6380.conf 
logfile /apps/redis/log/redis6380.log

[root@node2 etc]#sed  -i  's#logfile ""#logfile /apps/redis/log/redis6381.log#'  redis6381.conf 
[root@node2 etc]#grep   "logfile"  redis6381.conf 
logfile /apps/redis/log/redis6381.log

修改pid文件名称

vim /apps/redis/etc/redis6379.conf
vim /apps/redis/etc/redis6380.conf
vim /apps/redis/etc/redis6381.conf
[root@localhost etc]# grep   "pidfile"  redis6380.conf
pidfile /apps/redis/run/redis_6380.pid
[root@localhost etc]# grep   "pidfile"  redis6381.conf 
pidfile /apps/redis/run/redis_6381.pid
[root@localhost etc]# grep   "pidfile"  redis6379.conf 
pidfile /apps/redis/run/redis_6379.pid

修改端口号

sed  -i  's/^port 6379/port 6380/'  redis6380.conf
sed  -i  's/^port 6379/port 6381/'  redis6381.conf
grep   "^port"  redis6380.conf
grep   "^port"  redis6381.conf
进去修改更好

3.准备service 文件

[root@localhost etc]# cp  /lib/systemd/system/redis.service     /lib/systemd/system/redis6379.service
[root@localhost etc]# cp  /lib/systemd/system/redis.service     /lib/systemd/system/redis6380.service
[root@localhost etc]# cp  /lib/systemd/system/redis.service     /lib/systemd/system/redis6381.service

开启服务

systemctl start redis6379
systemctl start redis6380
systemctl start redis6381
systemctl status redis6379
systemctl status redis6380
systemctl status redis6381
ss -natp | grep 63

七.redis的配置优化

1.redis主要配置选项

bind 0.0.0.0 #监听地址,可以用空格隔开后多个监听IP

protected-mode yes #redis3.2之后加入的新特性,在没有设置bind IP和密码的时候,redis只允许访问127.0.0.1:6379,可以远程连接,但当访问将提示警告信息并拒绝远程访问

port 6379 #监听端口,默认6379/tcp

tcp-backlog 511 #三次握手的时候server端收到client ack确认号之后的队列值,即全连接队列长度timeout 0 #客户端和Redis服务端的连接超时时间,默认是0,表示永不超时

tcp-keepalive 300 #tcp 会话保持时间300s

daemonize no #默认no,即直接运行redis-server程序时,不作为守护进程运行,而是以前台方式运行,如果想在后台运行需改成yes,当redis作为守护进程运行的时候,它会写一个 pid 到/var/run/redis.pid 文件

supervised no #和OS相关参数,可设置通过upstart和systemd管理Redis守护进程,centos7后都使用systemd

pidfile /var/run/redis_6379.pid #pid文件路径,可以修改为/apps/redis/run/redis_6379.pid

loglevel notice #日志级别

logfile "/path/redis.log" #日志路径,示例:logfile "/apps/redis/log/redis_6379.log"databases 16 #设置数据库数量,默认:0-15,共16个库

always-show-logo yes #在启动redis 时是否显示或在日志中记录记录redis的logo

save 900 1 #在900秒内有1个key内容发生更改,就执行快照机制
save 300 10 #在300秒内有10个key内容发生更改,就执行快照机制
save 60 10000  #60秒内如果有10000个key以上的变化,就自动快照备份

stop-writes-on-bgsave-error yes #默认为yes时,可能会因空间满等原因快照无法保存出错时,会禁止redis写入操作,生产建议为no 
                                #此项只针对配置文件中的自动save有效

rdbcompression yes #持久化到RDB文件时,是否压缩,"yes"为压缩,"no"则反之

rdbchecksum yes #是否对备份文件开启RC64校验,默认是开启

dbfilename dump.rdb #快照文件名

dir ./ #快照文件保存路径,示例:dir "/apps/redis/data"
#主从复制相关
# replicaof <masterip> <masterport> #指定复制的master主机地址和端口,5.0版之前的指令为slaveof 
# masterauth <master-password> #指定复制的master主机的密码

replica-serve-stale-data yes #当从库同主库失去连接或者复制正在进行,从机库有两种运行方式:
1、设置为yes(默认设置),从库会继续响应客户端的读请求,此为建议值
2、设置为no,除去特定命令外的任何请求都会返回一个错误"SYNC with master in progress"。


replica-read-only yes #是否设置从库只读,建议值为yes,否则主库同步从库时可能会覆盖数据,造成数据丢失


repl-diskless-sync no #是否使用socket方式复制数据(无盘同步),新slave第一次连接master时需要做数据的全量同步,redis server就要从内存dump出新的RDB文件,然后从master传到slave,有两种方式把RDB文件传输给客户端:
1、基于硬盘(disk-backed):为no时,master创建一个新进程dump生成RDB磁盘文件,RDB完成之后由父进程(即主进程)将RDB文件发送给slaves,此为默认值
2、基于socket(diskless):master创建一个新进程直接dump RDB至slave的网络socket,不经过主进程和硬盘
#推荐使用基于硬盘(为no),是因为RDB文件创建后,可以同时传输给更多的slave,但是基于socket(为yes), 新slave连接到master之后得逐个同步数据。只有当磁盘I/O较慢且网络较快时,可用diskless(yes),否则一般建议使用磁盘(no)

repl-diskless-sync-delay 5 #diskless时复制的服务器等待的延迟时间,设置0为关闭,在延迟时间内到达的客户端,会一起通过diskless方式同步数据,但是一旦复制开始,master节点不会再接收新slave的复制请求,直到下一次同步开始才再接收新请求。即无法为延迟时间后到达的新副本提供服务,新副本将排队等待下一次RDB传输,因此服务器会等待一段时间才能让更多副本到达。推荐值:30-60

repl-ping-replica-period 10 #slave根据master指定的时间进行周期性的PING master,用于监测master状态,默认10s

repl-timeout 60 #复制连接的超时时间,需要大于repl-ping-slave-period,否则会经常报超时

repl-disable-tcp-nodelay no #是否在slave套接字发送SYNC之后禁用 TCP_NODELAY,如果选择"yes",Redis将合并多个报文为一个大的报文,从而使用更少数量的包向slaves发送数据,但是将使数据传输到slave上有延迟,Linux内核的默认配置会达到40毫秒,如果 "no" ,数据传输到slave的延迟将会减少,但要使用更多的带宽

repl-backlog-size 512mb #复制缓冲区内存大小,当slave断开连接一段时间后,该缓冲区会累积复制副本数据,因此当slave 重新连接时,通常不需要完全重新同步,只需传递在副本中的断开连接后没有同步的部分数据即可。只有在至少有一个slave连接之后才分配此内存空间,建议建立主从时此值要调大一些或在低峰期配置,否则会导致同步到slave失败

repl-backlog-ttl 3600 #多长时间内master没有slave连接,就清空backlog缓冲区

replica-priority 100 #当master不可用,哨兵Sentinel会根据slave的优先级选举一个master,此值最低的slave会优先当选master,而配置成0,永远不会被选举,一般多个slave都设为一样的值,让其自动选择
#min-replicas-to-write 3 #至少有3个可连接的slave,mater才接受写操作
#min-replicas-max-lag 10 #和上面至少3个slave的ping延迟不能超过10秒,否则master也将停止写操作

requirepass foobared #设置redis连接密码,之后需要AUTH pass,如果有特殊符号,用" "引起来,生产建议设置

rename-command #重命名一些高危命令,示例:rename-command FLUSHALL "" 禁用命令
   #示例: rename-command del 123456
   
maxclients 10000 #Redis最大连接客户端
 
maxmemory <bytes> #redis使用的最大内存,单位为bytes字节,0为不限制,建议设为物理内存一半,8G内存的计算方式8(G)*1024(MB)1024(KB)*1024(Kbyte),需要注意的是缓冲区是不计算在maxmemory内,生产中如果不设置此项,可能会导致OOM


appendonly no #是否开启AOF日志记录,默认redis使用的是rdb方式持久化,这种方式在许多应用中已经足够用了,但是redis如果中途宕机,会导致可能有几分钟的数据丢失(取决于dump数据的间隔时间),根据save来策略进行持久化,Append Only File是另一种持久化方式,可以提供更好的持久化特性,Redis会把每次写入的数据在接收后都写入 appendonly.aof 文件,每次启动时Redis都会先把这个文件的数据读入内存里,先忽略RDB文件。默认不启用此功能


appendfilename "appendonly.aof" #文本文件AOF的文件名,存放在dir指令指定的目录中

appendfsync everysec #aof持久化策略的配置
#no表示由操作系统保证数据同步到磁盘,Linux的默认fsync策略是30秒,最多会丢失30s的数据
#always表示每次写入都执行fsync,以保证数据同步到磁盘,安全性高,性能较差
#everysec表示每秒执行一次fsync,可能会导致丢失这1s数据,此为默认值,也生产建议值

#同时在执行bgrewriteaof操作和主进程写aof文件的操作,两者都会操作磁盘,而bgrewriteaof往往会涉及大量磁盘操作,这样就会造成主进程在写aof文件的时候出现阻塞的情形,以下参数实现控制

no-appendfsync-on-rewrite no #在aof rewrite期间,是否对aof新记录的append暂缓使用文件同步策略,主要考虑磁盘IO开支和请求阻塞时间。#默认为no,表示"不暂缓",新的aof记录仍然会被立即同步到磁盘,是最安全的方式,不会丢失数据,但是要忍受阻塞的问题
#为yes,相当于将appendfsync设置为no,这说明并没有执行磁盘操作,只是写入了缓冲区,因此这样并不会造成阻塞(因为没有竞争磁盘),但是如果这个时候redis挂掉,就会丢失数据。丢失多少数据呢?Linux默认fsync策略是30秒,最多会丢失30s的数据,但由于yes性能较好而且会避免出现阻塞因此比较推荐
#rewrite 即对aof文件进行整理,将空闲空间回收,从而可以减少恢复数据时间


auto-aof-rewrite-percentage 100 #当Aof log增长超过指定百分比例时,重写AOF文件,设置为0表示不自动重写Aof日志,重写是为了使aof体积保持最小,但是还可以确保保存最完整的数据


auto-aof-rewrite-min-size 64mb #触发aof rewrite的最小文件大小

aof-load-truncated yes #是否加载由于某些原因导致的末尾异常的AOF文件(主进程被kill/断电等),建议yes

aof-use-rdb-preamble no #redis4.0新增RDB-AOF混合持久化格式,在开启了这个功能之后,AOF重写产生的文件将同时包含RDB格式的内容和AOF格式的内容,其中RDB格式的内容用于记录已有的数据,而AOF格式的内容则用于记录最近发生了变化的数据,这样Redis就可以同时兼有RDB持久化和AOF持久化的优点(既能够快速地生成重写文件,也能够在出现问题时,快速地载入数据),默认为no,即不启用此功能

lua-time-limit 5000 #lua脚本的最大执行时间,单位为毫秒


cluster-enabled yes #是否开启集群模式,默认不开启,即单机模式


cluster-config-file nodes-6379.conf #由node节点自动生成的集群配置文件名称

cluster-node-timeout 15000 #集群中node节点连接超时时间,单位ms,超过此时间,会踢出集群

cluster-replica-validity-factor 10 #单位为次,在执行故障转移的时候可能有些节点和master断开一段时间导致数据比较旧,这些节点就不适用于选举为master,超过这个时间的就不会被进行故障转移,不能当选master,计算公式:(node-timeout * replica-validity-factor) + repl-pingreplica-period

cluster-migration-barrier 1 #集群迁移屏障,一个主节点至少拥有1个正常工作的从节点,即如果主节点的slave节点故障后会将多余的从节点分配到当前主节点成为其新的从节点。

cluster-require-full-coverage yes #集群请求槽位全部覆盖,如果一个主库宕机且没有备库就会出现集群槽位不全,那么yes时redis集群槽位验证不全,就不再对外提供服务(对key赋值时,会出现CLUSTERDOWN The cluster is down的提示,cluster_state:fail,但ping 仍PONG),而no则可以继续使用,但是会出现查询数据查不到的情况(因为有数据丢失)

cluster-replica-no-failover no #如果为yes,此选项阻止在主服务器发生故障时尝试对其主服务器进行故障转移。 但是,主服务器仍然可以执行手动强制故障转移,一般为no
#Slow log 是 Redis 用来记录超过指定执行时间的日志系统,执行时间不包括与客户端交谈,发送回复等I/O操作,而是实际执行命令所需的时间(在该阶段线程被阻塞并且不能同时为其它请求提供服务),由于slow log 保存在内存里面,读写速度非常快,因此可放心地使用,不必担心因为开启 slow log 而影响Redis 的速度

slowlog-log-slower-than 10000 #以微秒为单位的慢日志记录,为负数会禁用慢日志,为0会记录每个命令操作。默认值为10ms,一般一条命令执行都在微秒级,生产建议设为1ms-10ms之间

slowlog-max-len 128 #最多记录多少条慢日志的保存队列长度,达到此长度后,记录新命令会将最旧的命令从命令队列中删除,以此滚动删除,即,先进先出,队列固定长度,默认128,值偏小,生产建议设为1000以上

2.config动态修改配置

config 命令用于查看当前redis配置、以及不重启redis服务实现动态更改redis配置等

注意:不是所有配置都可以动态修改,且此方式无法持久保存

CONFIG SET parameter value
config   set  参数值
时间复杂度:O(1)
CONFIG SET 命令可以动态地调整 Redis 服务器的配置(configuration)而无须重启。

可以使用它修改配置参数,或者改变 Redis 的持久化(Persistence)方式。
CONFIG SET 可以修改的配置参数可以使用命令 CONFIG GET * 来列出,所有被 CONFIG SET 修改的配
置参数都会立即生效。

CONFIG GET parameter
时间复杂度: O(N),其中 N 为命令返回的配置选项数量。
CONFIG GET 命令用于取得运行中的 Redis 服务器的配置参数(configuration parameters),在
Redis 2.4 版本中, 有部分参数没有办法用 CONFIG GET 访问,但是在最新的 Redis 2.6 版本中,所
有配置参数都已经可以用 CONFIG GET 访问了。

CONFIG GET 接受单个参数 parameter 作为搜索关键字,查找所有匹配的配置参数,其中参数和值以“键-
值对”(key-value pairs)的方式排列。
比如执行 CONFIG GET s* 命令,服务器就会返回所有以 s 开头的配置参数及参数的值:

设置连接密码

#设置连接密码
127.0.0.1:6379> CONFIG SET requirepass 123456
OK

设置最大内存

127.0.0.1:6379> CONFIG SET maxmemory 8589934592
OK
127.0.0.1:6379> CONFIG GET maxmemory
1) "maxmemory"
2) "8589934592"

3.慢查询

slowlog-log-slower-than 1    #指定为超过1us即为慢的指令
slowlog-max-len 1024         #指定保存1024条慢记录

127.0.0.1:6379> CONFIG GET slow-log-slower-then  #慢查询列表
(empty list or set)

127.0.0.1:6379> SLOWLOG LEN  #查看慢日志的记录条数


SLOWLOG RESET #清空慢日志

4.持久化

Redis 虽然是一个内存级别的缓存程序,也就是redis 是使用内存进行数据的缓存的,但是其可以将内存的数据按照一定的策略保存到硬盘上,从而实现数据持久保存的目的目前redis支持两种不同方式的数据持久化保存机制,分别是RDB和AOF

持久化功能:Redis是内存数据库,所有数据都是保存在内存中,为了避免服务器断电等原因导致Redis进程异常退出后数据永久丢失,需要定期将Redis中的数据以某种形式(数据或者命令)从内存保存到硬盘;当下次Redis重启时,利用持久化文件实现数据恢复。除此之外为了进行灾难备份,可以持久将文件拷贝到一个远程位置(比如备份服务器)。

Redis 提供两种方式进行持久化:

  • RDB 持久化:原理是将Redis在内存中的数据库记录 定时保存到磁盘上

  • AOF 持久化(append only file):原理是将Redis的 操作日志已追加的方式写入文件,类似于mysql的 binlog

由于AOF的持久性实时性更好,即发生特殊情况导致数据丢失时,丢失的数据更少,因此是目前主流的持久化方式,不过RDB持久化仍然有其用武之地

4.1  RDB模式
4.1.1 RDB模式工作原理

RDB(Redis DataBase):基于时间的快照,其默认只保留当前最新的一次快照,特点是执行速度比较快,

缺点是可能会丢失从上次快照到当前时间点之间未做快照的数据

RDB bgsave实现快照的具体过程:

Redis从master主进程先fork出一个子进程,使用写时复制机制,子进程将内存的数据保存为一个临时文件,比如:tmp-.rdb,当数据保存完成之后再将上一次保存的RDB文件替换掉,然后关闭子进程,这样可以保证每一次做RDB快照保存的数据都是完整的因为直接替换RDB文件的时候,可能会出现突然断电等问题,而导致RDB文件还没有保存完整就因为突然关机停止保存,而导致数据丢失的情况.后续可以手动将每次生成的RDB文件进行备份,这样可以最大化保存历史数据

执行流程
(1) Redis父进程首先判断 :当前是否在执行save,或bgsave/bgrewriteaof的子进程,如果在执行则bgsave命令直接返回。
bgsave/bgrewriteaof 的子进程不能同时执行,主要是基于性能方面的考虑:两个并发的子进程同时执行大量的磁盘写操作,可能引起严重的性能问题。
(2) 父进程执行fork操作创建子进程,这个过程中父进程是阻塞的,Redis不能执行来自客户端的任何命令
(3) 父进程fork后,bgsave 命令返回 "Background saving started" 信息并不再阻塞父进程,并可以响应其他命令
(4) 子进程创建RDB文件,根据父进程内存快照生成临时快照文件,完成后对原有文件进行替换
(5) 子进程发送信号给父进程表示完成,父进程更新统计信息

启动时加载
RDB文件的载入是在服务器启动时自动执行的,并没有专门的命令。但是由于AOF的优先级更高,因此当AOF开启时,Redis会优先载入AOF文件来恢复数据;只有当A0F关闭时,才会在Redis服务器启动时检测RDB文件,并自动载入。服务器载入RDB文件期间处于阻塞状态,直到载入完成为止。
Redis载入RDB文件时,会对RDB文件进行校验,如果文件损坏,则日志中会打印错误,Redis启动失败

配置项有一项可以 忽略 RDB文件的错误,开启redis

RDB 持久化触发条件分为手动触发和自动触发两种

  • 手动触发

  • save命令和bgsave命令都可以生成RDB文件。

  • save命令会阻塞Redis服务器进程,直到RDB文件创建完毕为止,在Redis服务器阻塞期间,服务器不能处理任何命令请求。

  • 而bgsave命令会创建一个子进程,由子进程来负责创建RDB文件,父进程 (即Redis主进程) 则继续处理请求。

  • bgsave命令执行过程中,只有fork 子进程时会阻塞服务器,而对于save命令,整个过程都会阻塞服务器,因此save已基本被废弃,线上环境要杜绝save的使用。往往生产环境 bgsave 依然不允许轻易使用

4.1.2  RDB相关配置
ave 9001         #900s内修改了1个key即触发保存RDB
save 30010        #300s内修改了10个key即触发保存RDB
save 6010000      #60s内修改了10000个key即触发保存RDB
dbfilename dump.rdb
dir ./         #编泽编译安装,默认RDB文件存放在启动redis的工作目录,建议明确指定存入目录stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
4.1.3  实际RDB备份操作

[root@localhost data]#( redis-cli -a 123456 save & );pstree -p |grep redis-server; ls /apps/redis/data/ -l
#可以 同时执行保存命令和查看进程,可以看到如下图
4.1.4  自动触发RDB

在自动触发RDB持久化时,Redis也会选择bgsave而不是save来进行持久化。

save m n 自动触发最常见的情况是在配置文件中通过save m n,指定当m秒内发生n次变化时,会触发bgsave。

save自动触发条件是两个需要都满足,发生1次数据变化 900秒时间内

vim /etc/redis/6379.conf
--219行--以下三个save条件满足任意一个时,都会引起bgsave的调用
save 900 1 :当时间到900秒时,如果redis数据发生了至少1次变化,则执行bgsave
save 300 10 :当时间到300秒时, 如果redis数据发生了至少10次变化,则执行bgsave
save 60 10000 :当时间到60秒时,如果redis数据发生了至少10000次变化, 则执行bgsave

--242行--是否开启RDB文件压缩
rdbcompression yes

--254行--指定RDB文件名
dbfilename dump.rdb

--264行--指定RDB文件和AOF文件所在目录
dir /var/lib/redis/6379
4.1.5  实现RDB方式
  • save: 同步,会阻赛其它命令,不推荐使用

  • bgsave: 异步后台执行,不影响其它命令的执行

  • 自动: 制定规则,自动执行

可以使用  info Persistence 命令获取与持久化相关的信息

4.1.6  RDB优缺点

RDB 是Redis的默认持久化方式。它通过定期将内存中的数据集快照写入磁盘来实现持久化。RDB持久化的过程是这样的:

  • Redis在指定的时间间隔内(比如每隔几分钟),检查是否有数据修改。
  • 如果有数据修改且符合条件(例如执行了指定数量的写操作),Redis会fork出一个子进程,将当前内存中的数据集快照写入一个临时文件。
  • 当快照过程完成后,Redis会用这个临时文件替换上次持久化生成的旧文件。

优点

  • RDB 是一个紧凑的二进制文件,适合用于备份。
  • 对于数据恢复来说,由于是快照,可以更快速地进行加载和恢复。
  • 在恢复大数据集时,RDB 比 AOF 的启动速度快。

缺点

  • RDB 是定期持久化,因此如果Redis在最后一次持久化之后崩溃,可能会丢失最后一次持久化后的数据修改。
  • 如果数据集很大,fork子进程可能会消耗大量的CPU和内存资源。
4.2  AOF模式

写入操作记录

当 Redis 服务器接收到一个写入操作(例如 SET key value)时,它不仅会执行这个操作,还会将这个操作以协议格式追加到 AOF 文件的末尾。

文件的格式

AOF 文件是一个文本文件,包含了服务器接收到的写命令,以 Redis 协议的格式进行记录。这意味着每个写命令以易于理解和解析的方式存储在文件中。

持久化方式

Redis 通过配置选项控制何时将写入操作同步到 AOF 文件中:

    No(不使用同步):Redis 不主动进行同步操作,依赖操作系统来处理。这是性能最高的选项,但是可能会在发生故障时导致数据丢失。

    Everysec(每秒一次):Redis 默认的方式,每秒执行一次同步,即使发生服务器崩溃,最多会丢失一秒的数据。

    Always(always):每次写入操作后都会同步到 AOF 文件,这是最安全的选项,但性能可能会受到影响。

启动时加载 AOF 文件

当 Redis 服务器启动时,会通过读取 AOF 文件中的命令来重建数据集的状态,从而实现数据的持久化恢复。

AOF 重写

为了避免 AOF 文件过大影响性能,Redis 提供了 AOF 重写机制。AOF 重写是通过读取当前数据集的快照,并生成一个新的 AOF 文件来实现的。新的 AOF 文件包含了可以完全重建数据集状态的最少命令集合,从而达到压缩 AOF 文件的效果。

注意: AOF 模式默认是关闭的,*第一次开启AOF后,并重启服务生效后,会因为AOF的优先级高于。RDB,而AOF默认没有数据文件存在,从而导致所有数据丢失

4.2.1  AOF相关配置
appendonly yes        # 启用 AOF 持久化,默认为 no
appendfilename "appendonly.aof"  # AOF 文件的文件名
appendfsync everysec  # AOF 文件同步频率,可以是 always、everysec 或 no
everysec:表示每秒钟执行一次 fsync 操作。这是默认的配置选项,对于绝大多数情况来说,提供了较好的数据安全性和性能表现的折中方案。
always :表示每个写命令后立即执行 fsync 操作,确保每个写入操作都被安全地持久化到磁盘。这是最安全的选项,但会降低性能。
no :则依赖操作系统来决定何时执行 fsync 操作,这可能会增加数据丢失的风险,但提供了最佳的性能表现。

appendonly yes:

这个设置表示启用了 AOF 持久化。Redis 将每个接收到的写入命令追加到 AOF 文件的末尾,
以记录数据的变化。
appendfilename "appendonly.aof":

这个选项指定了 AOF 文件的名称,默认为 appendonly.aof。这是存储 Redis 数据变更操作的文件。
appendfsync everysec:

这个设置指定了 AOF 文件的同步策略。everysec 表示 Redis 将每秒钟执行一次 fsync 操作,
将缓冲区中的写入操作同步到 AOF 文件中。
这是性能和安全性之间的一种折中方案,可以保证在故障发生时最多丢失一秒钟的数据。
no-appendfsync-on-rewrite no:

这个选项设置为 no,表示在执行 AOF 重写时不禁用 appendfsync。AOF重写是为了减小AOF文件的体积,
通常会将多条写命令合并成更少的命令,从而减少存储空间和提高读取效率。

是否开启AOF

appendonly no #是否开启AOF日志记录,默认redis使用的是rdb方式持久化,这种方式在许多应用中已经足够用了,但是redis如果中途宕机,会导致可能有几分钟的数据丢失(取决于dump数据的间隔时间),根据save来策略进行持久化,Append Only File是另一种持久化方式,可以提供更好的持久化特性,Redis会把每次写入的数据在接收后都写入 appendonly.aof 文件,每次启动时Redis都会先把这个文件的数据读入内存里,先忽略RDB文件。默认不启用此功能

#在700行左右
700 appendonly no

700 appendonly yes

4.2.2  实例

开启AOF持久化

可以使用命令临时开启不需要重启

127.0.0.1:6379> CONFIG SET appendonly  yes

重新启动redis服务,查看数据目录下

数据发生修改会自动记录

同时启用 AOF 和 RDB 时如何正确恢复

AOF 优先级 比 RDB 要高 同时开启只会同步AOF 文件

先停服务器
先修改配置文件关闭AOF功能
开启服务
config  命令开启  AOF
再修改  配置文件   开启AOF

4.2.3  AOF重写机制

将一些重复的,可以合并的,过期的数据重新写入一个新的AOF文件,从而节约AOF备份占用的硬盘空间,也能加速恢复过程。可以手动执行 bgrewriteaof 触发AOF,第一次开启AOF功能,或定义自动 rewrite 策略

AOF重写配置

#同时在执行bgrewriteaof操作和主进程写aof文件的操作,两者都会操作磁盘,而bgrewriteaof
往往会涉及大量磁盘操作,这样就会造成主进程在写aof文件的时候出现阻塞的情形,以下参数实现控制

no-appendfsync-on-rewrite no #在aof rewrite期间,是否对aof新记录的append
暂缓使用文件同步策略,主要考虑磁盘IO开支和请求阻塞时间。
#默认为no,表示"不暂缓",新的aof记录仍然会被立即同步到磁盘,是最安全的方式,
不会丢失数据,但是要忍受阻塞的问题
#为yes,相当于将appendfsync设置为no,这说明并没有执行磁盘操作,只是写入了缓冲区,
因此这样并不会造成阻塞(因为没有竞争磁盘),但是如果这个时候redis挂掉,就会丢失数据。
丢失多少数据呢?Linux 的默认fsync策略是30秒,最多会丢失30s的数据,
但由于yes性能较好而且会避免出现阻塞因此比较推荐
#rewrite 即对aof文件进行整理,将空闲空间回收,从而可以减少恢复数据时间
auto-aof-rewrite-percentage 100#当Aof log增长超过指定百分比例时,重写AOF文件,
设置为0表示不自动重写Aof日志,重写是为了使aof体积保持最小,但是还可以确保保存最完整的数据
auto-aof-rewrite-min-size 64mb #触发aof rewrite的最小文件大小
​​​​​​​aof-load-truncated yes#是否加载由于某些原因导致的末尾异常的AOF文件
(主进程被kill/断电等),建议yes
127.0.0.1:6379> set age 22
OK
127.0.0.1:6379> set age 30
OK
127.0.0.1:6379> set age 40
OK
127.0.0.1:6379> set age 4050
OK
[root@localhost data]#ll
[root@localhost data]#redis-cli 
127.0.0.1:6379> BGREWRITEAOF
Background append only file rewriting started
127.0.0.1:6379> get age
"4050"
#重写过后只保留最后一次相同操作
[root@localhost data]#ll

4.2.4  AOF模式优缺点

AOF 是另一种持久化方式,通过记录每次写操作来记录数据变化。Redis会将收到的每个写命令都追加到文件末尾(Append Only),当Redis重启时,会通过重新执行文件中保存的写命令来恢复数据。

优点

  • AOF 文件以易于理解和人工处理的方式记录每个写操作,适合用于数据恢复和修复。
  • 可以根据需要进行不同的同步策略,如每秒同步、每写入命令同步等,灵活性较高。
  • AOF 文件可以更容易地进行追加备份。

缺点

  • AOF 文件通常比 RDB 文件大,因为它记录了每个写命令。
  • AOF 的恢复速度比 RDB 慢,尤其是在处理大量写入操作的情况下。
4.3  总结

RDB与AOF如何选择

  • RDB 适合用于数据备份和全量恢复,适合数据量较大但不需要高实时性的场景。
  • AOF 更适合需要更高实时性和更精确恢复的场景,可以在较小的时间间隔内实现数据持久化。
  • 一般不建议只开启AOF

八.Redis的缓存问题和解决方案

1.redis的三大缓存问题

正常情况下,大部分的访问请求应该是先被redis响应的,在redis那里得不到响应的小部分访问请求才会去请求MySQL数据库获取数据,这样MySQL数据库的负载压力是非常小的,且可以正常工作。缓存雪崩/穿透/击穿三大问题的根本原因在于redis缓存命中率下降,大量请求会直接发送给MySQL数据库,导致MySQL数据库压力过大而崩溃。

缓存雪崩:redis中大量缓存key集体过期
缓存穿透:大量请求访问redis和MySQL都不存在的资源
缓存击穿:redis中一个热点key过期,此时又有大量用户访问这个热点key(redis-cli --hotkeys 可用于查找热Key)


2.缓存雪崩的解决方案

使用随机数设置key的过期时间,防止集体过期
设置缓存标记,如果缓存过期,则自动更新缓存
数据库使用排他锁,实现加锁等待

3.缓存穿透的解决方案

对空值也进行缓存
使用布隆过滤器进行判断拦截一定不存在的无效请求
使用脚本实时监控,进行黑名单限制

4.缓存击穿的解决方案

预先对热点数据进行缓存预热
监控数据,实时调整过期时长
数据库使用排他锁,实现加锁等待


九.如何保证MySQL和Redis的数据一致

读取数据时,先从redis读取数据,如果redis中没有,再从MySQL中读取,并将读取到的数据同步到redis缓存中。
更新数据时,先更新MySQL数据库,再更新redis缓存
删除数据时,先删除redis缓存,再删除MySQL数据库
对于一些关键数据,可以使用MySQL的触发器来实现同步更新redis缓存。也可以使用定时任务,定时自动进行缓存预热,来定期同步MySQL和redis的数据。

十.Redis的优化有哪些

1)设置 config set activedefrag yes 开启内存碎片自动清理,或者定时执行 memory purge 清理内存碎片
2)尽可能使用 hash 数据类型存储数据。因为 hash 类型的一个 key 可包含多个字段,该类型的数据占用空间较小
3)建议给 key 设置过期时间
4)精简 key 的键名和键值,控制 key 占用空间的大小,避免 bigkey 的产生(redis-cli --bigkeys 可用于查找bigKey)
5)修改配置 maxmemory 指定redis可占用的最大内存大小
   修改配置 maxmemory-policy 指定内存数据淘汰策略(key的回收策略),实现保证内存使用率不超过最大内存
   修改配置 maxmemory-samples 指定内存数据淘汰策略的样本数量,一般为3~7,值越大样本越精确
   修改配置 maxclients 指定最大客户端连接数
   修改配置 tcp-backlog 指定最大连接排队数
   修改配置 timeout 指定连接超时时间
   修改配置 lazyfree-lazy-expire yes  设置惰性删除,将删除过期key的操作放在后台中去执行,避免阻塞主线程
   修改配置 no-appendfsync-on-rewrite yes  设置AOF文件重写期间,AOF后台子进程不进行刷盘操作,避免AOF重写和fsync竞争磁盘IO资源,导致redis延迟增加
6)设置AOF持久化和主从复制来备份数据,采用哨兵或集群模式实现redis集群的高可用
7)建议设置 config set requirepass 或 修改配置 requirepass 来设置 redis 密码

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值