Redis事务

redis事务本质:一组命令的集合!一个事务中的所有命令都会被序列化,在事务执行过程中,会按照顺序执行

一次性、顺序性、排他性!执行一系列的命令!

----队列 set set set 执行----

Redis事务没有隔离级别的概念!

所有的命令在十五中,并没有直接被执行!只有发起执行命令的时候才会执行!Exec

redis单条命令是保证原子性的额,但是事务不保证原子性!

  • 开启事务(multi)
  • 命令入队(redis正常的其他命令...)
  • 执行事务(exec)

放弃事务

命令:discard

监控

命令: watch key名

悲观锁:

认为什么时候都会出现问题,无论做什么都会加锁!

乐观锁

  • 认为什么时候都不会出现问题,所以不会上锁!更新数据的时候去判断一下,在此期间是否有人修改过这个数据
  • 获取version
  • 更新的时候比较version watch可以当乐观锁使用,解除监视unwatch,同时监控应该在redis的事务中才能使用

Redis.conf详解

redis启动是通过配置文件来启动的

单位

# Redis configuration file example
# Note on units: when memory size is needed, it is possible to specify
# it in the usual form of 1k 5GB 4M and so forth:
#
# 1k => 1000 bytes
# 1kb => 1024 bytes
# 1m => 1000000 bytes
# 1mb => 1024*1024 bytes
# 1g => 1000000000 bytes
# 1gb => 1024*1024*1024 bytes
#
# units are case insensitive so 1GB 1Gb 1gB are all the same.

配置文件unit大小写单位不敏感

包含

################################## INCLUDES ###################################

# Include one or more other config files here.  This is useful if you
# have a standard template that goes to all Redis servers but also need
# to customize a few per-server settings.  Include files can include
# other files, so use this wisely.
#
# Notice option "include" won't be rewritten by command "CONFIG REWRITE"
# from admin or Redis Sentinel. Since Redis always uses the last processed
# line as value of a configuration directive, you'd better put includes
# at the beginning of this file to avoid overwriting config change at runtime.
#
# If instead you are interested in using includes to override configuration
# options, it is better to use include as the last line.
#
# include .\path\to\local.conf
# include c:\path\to\other.conf

可以将多个配置文件都引进来

网络

bind 127.0.0.1	# 绑定的IP
protected-mode yes	# 是否开启保护模式(想要远程访问redis客户端,就需要关掉保护)
port 6379	# 端口设置

通用GENERAL

daemonize yes	# 以守护进程的方式运行,默认是no,我们需要自己开启为yes
pidfile /var/run/redis_6379.pid	# 如果以后台方式运行,我们就需要指定一个pid文件!

# 日志
# Specify the server verbosity level.
# This can be one of:
# debug (a lot of information, useful for development/testing)
# verbose (many rarely useful info, but not a mess like the debug level)
# notice (moderately verbose, what you want in production probably) 生产环境
# warning (only very important / critical messages are logged)
loglevel notice
logfile ""	# 日志的文件位置名
database 16	# 数据库数量 默认是16个数据库
always-show-logo yes	# 是否总显示logo

快照

持久化,在规定的时间内,执行了多少次操作,则会持久化到文件:.rdb .aof

redis是内存数据库,如果没有持久化吗,那么数据断点即失!

# 如果900s内,至少有1个key进行了修改,我们进行持久化操作
save 900 1
# 如果300s内,至少有10个key进行了修改,我们进行持久化操作
save 300 10
# 如果60s内,至少有10000个key进行了修改,我们进行持久化操作
save 60 10000


stop-writes-on-bgsave-error yes	# 持久化如果出错,是否还需要继续工作!
rdbcompression yes	# 是否压缩rdb文件,需要消耗一些CPU资源!
rdbchecksum yes	# 保存rdb文件的时候,进行错误检查校验!
dir ./	# rdb文件保存的目录!

REPLICATION 复制

SECURITY 安全

可以在这里设置redis的密码,默认没有密码!

localhost:0>config get requirepass	# 获取密码
 1)  "requirepass"
 2)  ""
localhost:0>config set requirepass "123456" "xxxxx"	# 设置密码

限制CLIENTS

maxclients 10000	# 设置能连接上redis的最大客户端的数量
maxmemory <bytes>	# redis 配置最大的内存容量 默认单位是字节
maxmemory-policy noeviction	# 内存达到上限之后的处理策略

	1、volatile-lru:只对设置了过期时间的key进行LRU算法进行删除
	2、allkeys-lru : 对所有key执行LRU算法进行删除
	3、volatile-lfu:只对设置了过期时间的key进行LFU算法进行删除
	4、allkeys-lfu:对所有key执行LFU算法进行删除
	5、volatile-random:随机删除设置有过期时间的key
	6、allkeys-random:随机删除
	7、volatile-ttl : 删除即将过期的
	8、noeviction : 永不过期,返回错误

APPEND ONLY MODE aof配置

appendonly no	# 默认关闭aof模式,因为默认是使用rdb方式持久化,通常情况下rdb完全够用!
appendfilename "appendonly.aof"	# aof持久化文件的名字

# appendfsync always	# 每次修改都会sync。消耗性能
appendfsync everysec	# 每秒执行一次sync 可能为丢失这1s数据
# appendfsync no	# 不执行同步,这个时候操作系统自己同步数据,速度最快

Redis持久化

RDB

在主从复制中,rdb就是备用了!在从机上!

在指定的时间间隔内将内存中的数据集快照写入磁盘,也就是Snapshot快照,它恢复时将快照文件直接读到内存里。

Redis会单独创建(fork)一个子进程来进行持久化,会先将数据写入到一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件。整个过程中,住进程是不进行任何IO操作的。这就确保了极高的性能。如果需要进行大规模数据的回复,且对于数据回复的完整性不是非常敏感,那RDB方式要比AOF方式更高效。RDB的缺点是最后一次持久化后的数据可能丢失。

触发机制

  1. 满足save的规则 会自动触发rdb规则
  2. 执行flushall命令
  3. 退出redis

如何回复rdb文件

将rdb文件放到redis启动目录,redis启动会自动检查dump.rdb文件,恢复数据 ps:查看需要存放的位置,使用命令:config get dir

优点:

  1. 适合大规模数据恢复
  2. 如果对数据完整性要求不高

缺点:

  1. 需要一定的时间间隔进行操作!如果redis以外宕机,最后一次修改的数据就没有了
  2. fork进程的时候会占用一定的内存空间

AOF(Append Only File)

将我们所有的命令都记录下来,history,恢复的时候就把这个文件全部再执行一遍!

以日志的形式来记录每个写操作,将Redis执行过的所有指令记录下来(读操作不记录),只许追加文件但不可以改写文件,redis启动之初会读取该文件重新构建数据,换言之,redis重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作

ps:如果aof文件有错误,那么redis是启动不了的,可以使用redis自带工具进行修复,命令:redis-check-aof --fix appendonly.aof

重写规则说明

aof默认就是文件的无限追加,文件会越来越大

no-appendfsync-on-rewrite no

# Automatic rewrite of the append only file.
# Redis is able to automatically rewrite the log file implicitly calling
# BGREWRITEAOF when the AOF log size grows by the specified percentage.
#
# This is how it works: Redis remembers the size of the AOF file after the
# latest rewrite (if no rewrite has happened since the restart, the size of
# the AOF at startup is used).
#
# This base size is compared to the current size. If the current size is
# bigger than the specified percentage, the rewrite is triggered. Also
# you need to specify a minimal size for the AOF file to be rewritten, this
# is useful to avoid rewriting the AOF file even if the percentage increase
# is reached but it is still pretty small.
#
# Specify a percentage of zero in order to disable the automatic AOF
# rewrite feature.

auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

如果aof文件大于64mb,redis会fork一个新的进程来将我们的文件进行重写!

优点

  1. 每次修改都同步,文件的完整性会更好
  2. 每秒同步一次可能会丢失一秒数据
  3. 从不同步,效率最高

缺点

  1. 相对于数据文件来说,aof远远大于rdb,修复速度也比rdb慢!
  2. aof运行效率也要比rdb慢,所以我们redis默认配置就是rdb持久化!

拓展

  1. rdb持久化方式能够在指定的时间间隔内对你的数据进行快照存储
  2. aof持久化方式记录每次对服务器写的操作,当服务器重启的时候会重新执行这些命令来恢复原始的数据,aof命令以redis协议追加保存每次写的操作到文件末尾,redis还能对aof文件进行后台重写,使得aof文件的体积不至于过大
  3. 制作缓存,如果只希望你的数据在服务器运行的时候存在,可以不使用任何持久化
  4. 同时开启两种持久化方式
    • 在这种情况下,当redis重启的时候会优先载入aof文件来恢复原始的数据,因为在通常情况下aof文件保存的数据集要比rdb文件保存的数据集完整
    • rdb的数据不实时,同时使用两种时服务器重启也置灰找aof文件,那要不要只使用aof呢?作者建议不要,因为RDB更适合用于备份数据库(aof在不断的变化不好备份),快速重启,而且不会有aof可能潜在的bug留着作为一个万一的手段。
  5. 性能建议
    • 因为rdb文件只用作后备用途,建议只在slave上持久化rdb文件,而且只要15分钟备份一次就够了,只保留save 900 1这条规则。
    • 如果enable aof,好处是在最恶劣的情况下也只会丢失不超过两秒数据,启动脚本比较简单只load自己的aof文件就可以了,代价一是带来了持续的IO,二是aof rewrite的最后将rewrite过程中产生的新数据写到新文件造成的阻塞几乎是不可避免的。只要硬盘许可,应该尽量减少aof rewrite频率,aof重写的基础大小默认值64M太小了,可以设到5G以上,默认超过原大小100%大小重写可以改到适量数值。
    • 如果不enable aof,仅靠Master-Slave Replication实现高可用也可以,能省掉一大笔IO,也减少了rewrite时带来的系统波动。代价是如果Master/Slave同时倒掉,会丢失十几分钟的数据,启动脚本也要比较两个Master/Slave中的RDB文件,载入较新的那个,微博就是这种架构。

Redis发布订阅

redis发布订阅(pub/sub)是一种 消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。 redis客户端可以订阅任务数量的频道。

命令

PSUBSCRIBE pattern [pattern ...] 订阅一个或多个符合给定模式的频道。

PUBSUB subcommand [argument [argument ...]] 查看订阅与发布系统状态。

PUBLISH channel message 将信息发送到指定的频道。

PUNSUBSCRIBE [pattern [pattern ...]] 退订所有给定模式的频道。

SUBSCRIBE channel [channel ...] 订阅给定的一个或多个频道的信息。

UNSUBSCRIBE [channel [channel ...]] 指退订给定的频道。

Redis主从复制

主从复制,是指将一台redis服务器的数据,复制到其他的redis服务器。前者称为主节点(master/leader),后者称为从节点(slave/follower);数据的复制是单向的,只能从主节点到从节点。Master以写为主,Slave以读为主。

默认情况下,每台redis服务器都是主节点;且一个主节点可以有多个从节点(或没有从节点),但一个从节点只能有一个主节点。

主从复制的作用主要包括:

  1. 数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。
  2. 故障恢复:当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复;实际上是一种服务的冗余。
  3. 负载均衡:在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务(即写redis数据时应用连接主节点,读redis数据时应用连接从节点),分担服务器负载;尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高redis服务器的并发量。
  4. 高可用基石:除了上述作用以外,主从复制还是哨兵和集群能够实施的基础,因此说主从复制是redis高可用的基础

一般来说,要将redis运用于工程项目中,只使用一台redis是万万不能的,原因如下:

  1. 从结构上,单个redis会发生单点故障,并且一台服务器需要处理所有的请求负载,压力较大;
  2. 从容量上,单个redis服务器内存容量有限,就算一台reids服务器内存容量为256G,也不能将所有内存用作redis存储内存,一般来说,单台redis最大使用内存不应该超过20G。 电商网站的商品,一般都是一次上传,无数次浏览的,说专业点也就是“读多写少”。对于这种场景,我们通常使用一主二从(多从)的架构。

主从复制配置 只配置从库,不用配置主库!

localhost:0>info replication	# 查看当前库的信息
"# Replication
role:master	# 角色 master
connected_slaves:0	# 没有从机
master_replid:719f5c8caeffddd3ffdfef7cb7e5904e0a3b9f32
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
"

复制3个配置文件,然后修改对应的信息

  1. 端口
  2. pid名字
  3. log文件名字
  4. dump.rdb名字 修改完之后启动3个redis服务,通过进程信息查看

命令

  • 启动命令:redis-server xxxxx.conf
  • 连接客户端命令:redis-cli -p port(端口)
  • 关闭服务:shutdown

一主二从

默认情况下,每台redis服务器都是主节点;我们一般情况下只用配置从机就行了! 一主(79)二从(80、81)

localhost:0>SLAVEOF	127.0.0.1 6379	# SLAVEOF	HOST PORT配置从机的主机地址及端口号

真实的主从配置应该在配置文件中配置,这样的话是永久的,我们这里使用的是命令,是暂时的!

################################# REPLICATION #################################

# Master-Replica replication. Use replicaof to make a Redis instance a copy of
# another Redis server. A few things to understand ASAP about Redis replication.
#
#   +------------------+      +---------------+
#   |      Master      | ---> |    Replica    |
#   | (receive writes) |      |  (exact copy) |
#   +------------------+      +---------------+
#
# 1) Redis replication is asynchronous, but you can configure a master to
#    stop accepting writes if it appears to be not connected with at least
#    a given number of replicas.
# 2) Redis replicas are able to perform a partial resynchronization with the
#    master if the replication link is lost for a relatively small amount of
#    time. You may want to configure the replication backlog size (see the next
#    sections of this file) with a sensible value depending on your needs.
# 3) Replication is automatic and does not need user intervention. After a
#    network partition replicas automatically try to reconnect to masters
#    and resynchronize with them.
#
# replicaof <masterip> <masterport>	# 用这行去进行主从配置

细节

主机可以写,从机不能写只能读!主机中的所有信息和数据,都会自动被从机保存! 主机断开连接,从机依旧是连到主机的,但是不能有写操作,这个时候,如果主机回来了,从机依旧可以直接获取到主机写的信息! 如果是使用命令行来进行主从配置的,这个时候如果重启了从机,那么从机就会自动变成主机,是拿不到原先主机的信息的。只要变为原主机的从机,立马可以获取原主机的信息。

复制原理

Slave启动成功连接到master后会发送一个sync同步命令

Master街道命令,启动后台的存盘进程。同时收集所有接收到的用于修改数据集命令,在后台进程执行完毕之后,master将传送整个数据文件到slave,并完成一次完全同步

全量复制(从机连接到主机后执行):而slave服务在接收到数据库文件数据后,将其存盘并加载到内存中

增量复制(已经连上主机,后续在主机上进行的增删改操作后执行):Master继续将新的所有收集到的修改命令一次传给slave,完成同步 但是只要重新连接到master,一次完全同步(全量复制)将被自动执行!我们的数据一定可以在从机中看到!

层层链路

79(主)-》80(主/从)-》81(从)

80此时用命令查看依旧属于从节点

上一个M连接下一个S!这时候也能完成我们的主从复制!

ps:如果79这个主节点down了,那么我们可以使用命令(SLAVEOF no one)使自己变成主机!其他的节点就可以手动连接到最新的这个主节点(手动)!如果这时候79节点恢复了,那就只能重新配置

哨兵模式(自动选举主节点的模式)

概述

主从切换结束的方法是:当主服务器宕机后,需要手动把一台从服务器切换为主服务器,这就需要人工干预,费事费力,还会造成一段时间内服务不可用。这不是一种推荐的方式,更多时候,我们优先考虑哨兵模式。redis从2.8开始正式提供了Sentinel(哨兵)架构来解决这个问题。

选举主节点的自动版,能够后台监控主机是否故障,如果故障了根据投票数自动将从节点转换为主节点。

哨兵模式是一种特殊的模式,首先Redis提供了哨兵的命令,哨兵是一个独立的进程,作为进程,它会独立运行。其原理是哨兵通过发送命令,等待redis服务器响应,从而监控运行的多个redis实例。

这里的哨兵有两个作用

  • 通过发送命令吗,让redis服务器返回监控其运行状态,包括主服务器和从服务器。
  • 当哨兵检测到master宕机,会自动将slave切换成master,然后通过发布订阅模式通知其他的从服务器,修改配置文件,让他们切换主机。

然而一个哨兵进程对redis服务器进行监控,可能会出现问题,为此,我们可以使用多哨兵进行监控。各个哨兵之间还会进行监控,这样就形成了多哨兵模式 假设主服务器宕机,哨兵1先检测到这个结果,系统并不会马上进行failover过程,仅仅是哨兵1主观的认为主服务器不可用,这个现象称为主观下线。当后面的哨兵也检测到主服务器不可用,并且数量达到一定值时,那么哨兵之间就会进行一次投票,投票的结果由一个哨兵发起,进行failover[故障转移]操作。切换成功后,就会通过发布订阅模式,让各个哨兵把自己监控的从服务器实现切换主机,这个过程称为客观下线

测试

1、配置哨兵配置文件sentinel.conf

#sentinel monitor 被监控的名称 host port 1
sentinel monitor myredis 127.0.0.1 6379 1

后面的这个数字1,代表主机挂了,slave投票看让谁接替成为主机,票数最多的,就会成为主机!

2、启动哨兵

命令:redis-sentinel sentinel.conf

如果Master节点断开了,这个时候就会从从机中随机选择一个服务器当主机(这里面有一个投票算法),当这太服务器恢复后,只能归并到新的主机下做从机,这就是哨兵规则!

优点 哨兵集群,基于主从复制模式,所有的主从配置有点,他全有 主从可以切换,故障可以转义,系统的可用性就会更好 哨兵模式就是主从模式的升级,手动变自动,更加健壮

缺点 redis不方便在线扩容,集群容量一旦到达上限,在线扩容就十分麻烦! 实现哨兵模式的配置其实是很麻烦的,里面有很多选择!

哨兵模式的全部配置

port 26379 # 配置端口
daemonize yes # 以守护进程模式启动
logfile "sentinel_16379.log" # 日志文件名
dir "/opt/redis/redis-sentinel26379/data" # 存放备份文件以及日志等文件的目录
sentinel monitor mymaster 192.168.1.29 6379 2 # 监控的IP 端口号 名称 sentinel通过投票后认为mater宕机的数量,此处为至少2个
sentinel down-after-milliseconds mymaster 30000 # 30秒ping不通主节点的信息,主观认master宕机
sentinel parallel-syncs mymaster 1
#故障转移开始,三分钟内没有完成,则认为转移失败
sentinel failover-timeout mymaster 180000
sentinel auth-pass mymaster 123 设置密码

redis缓存击穿、穿透和雪崩

概念

1.redis击穿:热key在某个时间点到期,大量请求越过redis直接冲击数据库

解决方案:设置热点数据永不过期或者使用互斥锁

2.redis穿透:大量请求数据库中本来就没有或者为空的数据,从而对持久层造成大量的压力

解决方案:布隆过滤器或者缓存空对象

3.redis雪崩:大量热key在同一时间过期或者redis宕机,大量请求直接访问数据库

解决方案:redis高可用(搭建集群)、限流降级(spring cloud组件)、数据预热(设置不同的过期时间让缓存失效的时间尽量均匀)