redis002,-事务-发布订阅,主从复制

1、事务

笔记来自—狂神视频
redis单条命令保存原子性,但redis的事务不保证原子性。

事务本质:一组命令的集合。命令被放到队列中,一个事务的所有命令都会被序列化,在事务执行过程中会按照顺序执行。
一次性,顺序性,排他性,执行一系列的命令。

也没有隔离级别的概念。
所有的命令在事务中,并没有直接被执行,只有发起执行命令的时候才被执行。 Exec

redis的事务:
开启事务:(multi)
命令入队:()
执行事务:(exec)

锁:redis可以实现乐观锁,watch

127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> multi # 开启事务
OK
127.0.0.1:6379> set k1 v1
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> get k2
QUEUED
127.0.0.1:6379> set k3 v3
QUEUED
127.0.0.1:6379> exec # 执行事务
1) OK
2) OK
3) "v2"
4) OK

############################################################
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set k1 v1
QUEUED
127.0.0.1:6379> set k3 v3
QUEUED
127.0.0.1:6379> set k4 v4
QUEUED
127.0.0.1:6379> discard  # 放弃事务
OK
127.0.0.1:6379> get k4
(nil)


编译型异常(代码有问题,命令有错!)食物中的所有命令都不执行

127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set k1 v1
QUEUED
127.0.0.1:6379> set k2 v3
QUEUED
127.0.0.1:6379> getset k3 # 错误命令
(error) ERR wrong number of arguments for 'getset' command
127.0.0.1:6379> set k4 v5
QUEUED
127.0.0.1:6379> exec
(error) EXECABORT Transaction discarded because of previous errors.

运行时异常(1/0)如果事务队列存在语法性,那么执行命令的时候,其他命令可以执行,错误命令会抛出异常

事务中一个错误的命令报错,后续的命令继续执行,所以redis事务没有原子性

127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> set k1 "v1"
OK
127.0.0.1:6379> multi 
OK
127.0.0.1:6379> incr k1 # 不能自加1,而后面的命令继续执行
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> set k3 v3
QUEUED
127.0.0.1:6379> exec
1) (error) ERR value is not an integer or out of range
2) OK
3) OK
127.0.0.1:6379> get k3
"v3"
127.0.0.1:6379> 

这更像是批处理,不像事务。

2、乐观锁,悲观锁

2.1、悲观锁

很悲观,认为什么时候都会出问题

2.2、乐观锁

什么时候都不会出问题
1.获取version
2.更新的时候比较version

watch就是乐观锁

127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> set money 100
OK
127.0.0.1:6379> set out 0
OK
127.0.0.1:6379> watch money
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> decrby money 20
QUEUED
127.0.0.1:6379> incrby out 20
QUEUED
127.0.0.1:6379> exec
1) (integer) 80
2) (integer) 20

测试多线程,修改值,使用watch可以当成redis的乐观锁操作

127.0.0.1:6379> watch money # 监视money
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> decrby money 20
QUEUED
127.0.0.1:6379> incrby money 20
QUEUED
127.0.0.1:6379> exec # 执行之前,另外一个线程修改了我们的值,这个时候,就会导致事务执行失败。
(nil)


################################
然后怎么搞?
先解锁:unwatch
再加锁:watch money
执行失败也会自动解锁

如果修改失败,去再次获取最新的值就好,
自旋锁可以很好的完成这个。
redis秒杀系统就是乐观锁,watch实现

3、jedis

是什么?
redis官方推荐的java连接开发工具,使用java操作redis中间件。
1、导入对应的依赖
2、编码测试
new一个jedis对象,然后调用昨天命令对应的方法,
setex设置过期时间
setnx如果不存在就处理,(分布式锁)

事务:

4、springBoot整合

5、Redis.conf详解

自己虚拟机:
配置文件在
sudo vi /etc/redis/redis.conf
1、单位大小写不敏感

units are case insensitive so 1GB 1Gb 1gB are all the same

2、可以把别的配置合并到redis的配置
在这里插入图片描述
3、网络

bind 127.0.0.1 ::1  #绑定的ip

protected-mode yes  # 保护模式

# Accept connections on the specified port, default is 6379 (IANA #815344).
# If port 0 is specified Redis will not listen on a TCP socket.
port 6379   # 默认端口

4、通用配置

daemonize yes #以守护进程方式运行

pidfile /var/run/redis/redis-server.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 /var/log/redis/redis-server.log # 生成的日志文件名,如果为“”空,就直接输出
databases 16 # 数据库的数量
always-show-logo yes  # 是否总是显示logo


5、快照SNAPSHOTTING
持久化,在规定时间内,执行了多少次操作,则会持久化到文件 .rdb文件,.aof文件
redis是内存数据库,如果不持久化就会丢

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

之后我们会自己定义自己的持久化测试。



# 持久化错误之后还要不要继续工作
stop-writes-on-bgsave-error yes 

#是否压缩rdb文件,会消耗cpu资源
rdbcompression yes

# 保存rdb文件的时候,是否校验rdb文件的错误
rdbchecksum yes

# rdb保存的文件目录
dir /var/lib/redis

6、主从复制相关 REPLICATION

7、安全SECURITY

进入数据库之后:---> config get requirepass  # 获取密码

配置文件中设置密码:需要重启才能生效
# requirepass foobared
requirepass 123456

命令行设置密码:
config set requirepass "123456"

下次操作需要验证:
6379----> auth 123456


8、客户端限制 CLIENTS

# maxclients 10000

# maxmemory <bytes> # 最大内存设置


# maxmemory-policy noeviction # 内存达到上限之后的处理策略
1、volatile-lru:只对设置了过期时间的key进行lru(默认)
2、allkeys-lru:所有的key进行lru
3、volatile-random:随机删除即将过期的key
4、allkeys-random:随即删除
5、volatile-ttl:删除即将过期的
6、noeviction:永不过期,返回错误

9、aof配置 APPEND ONLY MODE

appendonly no # 默认不开启aof模式,默认使用rdb持久化,在大部分所有的情况下rdb够用了

# 持久化文件的名字
appendfilename "appendonly.aof"


# appendfsync always # 每次写入都会同步,速度慢
appendfsync everysec # 每秒都执行一次同步,可能会丢失这一秒的数据
# appendfsync no # 不执行同步,操作系统自己执行同步,速度最快

6、redis持久化

redis是内存数据库,如果不把数据库状态保存到磁盘,那么一旦服务器进程退出,服务器中的数据库状态也会消失,所以提供了持久化功能。

6.1、RDB(redis DataBase)

在5、快照SNAPSHOTTING 中配置,和一些默认的持久化规则。
在这里插入图片描述

在指定的时间间隔内将内存中的数据集快照写入磁盘,也就是Snapshot快照,它恢复时试讲快照文件直接读到内存里。
Redis会单独创建(fork)一个子进程进行持久化,先将数据写入一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件。整个过程中,主进程不进行任何IO操作,确保极高的性能,如需要大规模数据的恢复,且对数据恢复的完整性,不是非常敏感,那RDB比AOF方式更加高效,
RDB缺点:最后一次持久化的数据可能丢失,默认RDB,一般情况下不修改这个配置。
rdb保存的文件是:dump.rdb文件。都是在配置文件中快照进行配置。

save命令就可以直接保存配置文件了

RDB触发机制
1、save的规则满足情况下,会自动触发RDB规则
2、执行flushall 命令,也会触发
3、退出redis,也会产生rdb文件

如何恢复rdb文件
1、只需将rdb文件放在我们redis启动目录就可以了,redis启动的时候,会自动检查dump.rdb文件,恢复其中的文件。

config get dir


127.0.0.1:6379> config get dir
1) "dir"
2) "/etc/redis"  # 在这个文件夹下有dump.rdb文件,启动时候就会恢复了

生产环境,会把这个文件备份、

优点
1、适合大规模的数据恢复
2、对数据完整性要求不高
缺点
1、需要一定时间间隔进程操作,如果redis意外宕机了,最后一次的修改无法记录
2、fork进程的时候,会占用一定的内容空间、

6.2、AOF(Append Only File)

将我们的所有命令都记录下来,history类似,恢复的时候就把这个文件全部命令全部再执行一遍。
是什么?
在这里插入图片描述
以日志的形式来记录每个写操作,将redis执行过的所有指令记录下来,(读操作不记录),只许追加文件,不让修改,redis启动之初会读取文件重新构建数据,就是:redis重启的话,就根据日志文件的内容将写指令充钱到后执行一次,以完成数据的恢复。
AOF保存的是appendonly.aof文件

默认是不开启的。
写的时间间隔
重写不重写的配置,重写的规则,时间,大小

如果aof文件被破坏,redis就启动不起来了。可以使用redis-check-aof程序检测文件来修复这个.aof配置文件。

redis-check-aof --fix appendonly.aof

修复操作:
在这里插入图片描述
优点:
1、每一次修改都同步,文件的完整性就更加好。
2、默认每秒同步一次,可能丢失一秒的数据。
3、从不同步,效率最高,

缺点:
1、相对于数据文件来说,aof远远大于rdb,修复的速度慢。
2、aof运行效率也比rdb慢,(io操作)。所以默认的是rdb

当这个文件达到64MB的时候就重写一个文件。fork一个新的进程来将我们的文件进行重写。
aof默认文件的无限追加,文件会越来越大。

面试问你持久化机制?
聊一聊参数,

聊一聊基本原理:
aof是读写文件,
rdb是fork子进程,记录文件。

默认rdb。
可以承受数分钟以内的数据丢失, 那么你可以只使用 RDB 持久化。
在主从复制中,rdb就是备用了,从机上面。而aof几乎不使用。
扩展
在这里插入图片描述
2
在这里插入图片描述

7、Redis发布订阅

在这里插入图片描述
被广泛用于构建即时通信应用,网络聊天室,和实时广播,实时提醒
1、实时消息系统
2、实时聊天,频道当做聊天室,将信息回显给所有人。
3、订阅关注系统都可以。
4、稍微复杂的场景就使用消息中间件(MQ)卡夫卡
在这里插入图片描述

在这里插入图片描述

订阅端:

$ redis-cli
127.0.0.1:6379> subscribe kuangshenshuo # 订阅一个频道,
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "kuangshenshuo"
3) (integer) 1   # 等待读取信息

1) "message" # 消息
2) "kuangshenshuo"  # 频道
3) "hello world" # 内容
1) "message"
2) "kuangshenshuo"
3) " game over"

发布端:

~$ redis-cli
127.0.0.1:6379> publish kuangshenshuo "hello world"  # 发布消息
(integer) 1
127.0.0.1:6379> publish kuangshenshuo " game over"
(integer) 1
127.0.0.1:6379> 



8、Redis主从复制

狂神视频链接
将一台redis服务器的数据复制到其他redis服务器,master/leader,数据复制是单向的。master写为主,slave以读为主。
主从复制,读写分离,80%都是在读。减缓服务器压力。最低1主2从,哨兵。
默认每台redis都是主节点,且一个主节点可以有多个从节点,一个从节点只能有一个主节点(一个爸爸可以有多个儿子,一个儿子只能有一个爸爸)

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

一般一台redis是不够用:
1.从结构上,单个redis服务会发生单点故障,且处理所有请求,压力较大。
2.从容量上,单个redis服务器容量有限,单台redis服务器使用的内存不应该超过20G,
电商网站上的商品都是一次上传,无数次浏览,“读多写少”

8.2、环境配置

只配置从库,

$ redis-cli
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:0
master_replid:dc5d56bca2403bb682490ed37aeaf2a177573757
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、修改端口,6379
2、后台运行
3、pidfile /var/run/redis_6379.pid
4、logfile “6379.log”
5、dbfilename dump6379.rdb

开启:
redis-server kconfig/redis6379.conf
redis-server kconfig/redis6380.conf
redis-server kconfig/redis6381.conf
在这里插入图片描述
至少一主二从、
只需要配置从机。
认老大

slaveof 127.0.0.1 6379

# 查看: info replication

有密码的在从节点配置文件中把masterauth 主节点的密码写上
在这里插入图片描述
我们这里是命令配置的,临时的,如果需要永久配置就在配置文件中配置,replication那一块,配置ip和端口和密码

细节了解
主节点负责写,从节点只能读,主机中的所有信息和数据都会自动被从机保存。
在这里插入图片描述
如果主节点断了,没有哨兵的时候,从节点还是从节点,除非去主动修改从节点变回来成主机。而断开了的主机再次连接回来之后,从节点就自动去连接主节点了。

如果从机断掉了,如果是使用命令来配置的主从关系,这时候从机如果重启了,从机就自动变成了master。再次把自己变成主机的从机,就可以再次去主机拿到信息了。

全量复制,增量复制:从机再次连接到主机。
在这里插入图片描述

8.3、层层链路

在这里插入图片描述

谋朝篡位:
如果主机断开了,从机就自己成为主机。哨兵没出来之前就是手动。如果这个时候原来的老大回来了,这个时候也只是一个光杆司令。只能重新配置

slaveof no one

哨兵模式自动称为主机
能够后台监控主机是否故障,如果故障了根据投票数,自动将从库转换成主库
哨兵模式是一种特殊的模式,哨兵是一个独立的进程。它独立运行。原理是哨兵通过发送命令,等待redis服务器响应,从而监控运行的多个redis实例。
哨兵发消息,如果不回就是死了。
在这里插入图片描述
哨兵集群,哨兵还会相互监控,以防止哨兵死了。
在这里插入图片描述
再变成:
投片算法,去研究源码。
在这里插入图片描述

1、在配置文件当前路径下:配置哨兵的配置文件

vim sentinel.conf
在打开的文件中:
# sentinel monitor host port 1
sentinel monitor myredis 127.0.0.1 6379 1   # 使这个哨兵监控主机

后面的1,表示只要有一个哨兵认为主服务已经下线,就被判定为客观下线。

2、启动哨兵

redis-sentinel kconfig/sentinel.conf

可以通过 info replication 来显示投票换主机的日志信息

如果master节点断开了,这个时候就会从从机中随机选择一个服务器。(这里有一个投票算法)

如果主机之后再回来,也只能当弟弟,这就是哨兵模式的规则

哨兵优点:
1、哨兵集群,基于主从复制模式,所有的主从复制模式优点,它全有,
2、主从可以切换,故障可以转移,系统的可用性就会更好。
3、哨兵模式就是主从模式的升级,手动到自动,更加健壮
缺点:
1、redis不好在线扩容,集群容量一旦达到上限,在线扩容十分麻烦。
2、实现哨兵模式的配置其实是很麻烦的,里边有很多选择。

哨兵模式的全部配置:
1、如果有哨兵集群,需要配置每个哨兵的端口
2、定义哨兵的工作目录
3、设置默认主机节点,ip+端口
4、每个主机的密码
5、默认的延时时间(默认30秒)
6、故障转移时间
7、出现问题,执行脚本,通知一下工作人员,运维来配置。

9、Redis缓存穿透和雪崩

9.1、缓存穿透(查不到)

用户想去查询一个数据,发现redis内存数据库中没有,也就是缓存没有命中,于是想持久层数据库查询,发现也没有,于是本次查询失败,当用户很多时候,缓存都没有命中,于是都去请求了持久层数据库,就会给持久层数据库很大的压力,就相当于出现了缓存穿透。

在这里插入图片描述

9.1、布隆过滤器(解决方案1)

是一种数据结构,对所有可能查询的参数以hash形式存储,在控制层先进行校验,不符合就丢弃,从而避免了对底层存储系统的查询压力。
在这里插入图片描述

9.2、缓存空对象(解决方案2)

当存储层不命中后,即使返回的空对象也缓存起来,同时设置一个过期时间,之后再访问这个数据,将会从缓存中获取这个空对象,保护了后端数据源。
在这里插入图片描述
会出现两个问题:
1、如果空值被缓存起来,意味着缓存需要更多的空间存储更多的键,因为这当中可能会有很多空值的键、
2、即使对空值设置了过期时间,还是会存在缓存层和存储层数据会有一段时间窗口的不一致,这对于需要保持一致性的业务有影响。(缓存层没有,而存储层已经有了)

9.3、缓存击穿(量太大)

微博服务器宕机,(热搜)

解决方案:
1、设置热点数据永不过期:从缓存层面看,没有设置过期时间,所有不会出现热点key过期后产生的问题

2、加互斥锁(setnx)
使用分布式锁:保证对每个key同事只有一个线程去查询后端服务,其他线程没有获得分布式锁的权限,因此只需等待就行,这种方式将高并发的压力转移到了分布式锁,

在这里插入图片描述

9.2、缓存雪崩

指在某一段时间段,缓存集中过期失效。redis宕机,停电了。
产生雪崩的原因之一:比如在写文本的时候,马上双十一零点,很快迎来一波抢购,这波商品时间比较集中的放进了缓存,假设缓存了一个小时,那么到凌晨1点的时候,这一批商品的缓存都过期了,而对这批商品的访问查询,都落在了数据库,对数据库而言,就会产生周期性的压力波峰,所有的请求都达到存储层,存储层的调用暴涨,造成存储层也会挂掉的情况。
在这里插入图片描述
停掉一些服务,(保证主要的服务可用)不让退款,

解决方案:
redis高可用:redis既然有可能挂掉,那就多设几台redis,这样挂了一个还有其他,其实就是搭建的集群(异地多活)
限流降级
在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待。
数据预热
数据在正式部署之前,先把可能的数据预先访问一遍,大量访问的数据就会加载到缓存中,在即将发生大并发访问前手动触发加载缓存不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀。

狂神视频

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值