一篇Redis搞定面试官《Java-2021面试谈资系列》

Redis高频面试点!!!

    • 一、事务
    • 二、Redis.conf详解
    • 三、Redis持久化
        • 3.1RDB (Redis DataBase)
        • 3.2AOF(Append Only File)
    • 四、Redis发布订阅
    • 五、Redis主从复制
        • 5.1环境配置
        • 5.2一主二从
        • 5.3哨兵模式

一、事务

Mysql:ACID!要么同时成功,要么同时失败-----原子性

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

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

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

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

  • 开启事务 multi
  • 命令入队 …
  • 执行事务 exec
  • 锁:Redis可以实现乐观锁

正常执行事务

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 k2 v2
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> 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> set k3 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 v4
QUEUED
127.0.0.1:6379> exec
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> get k4
(nil)

运行时异常(1/0),若事务中存在语法错误,执行命令时,其他命令可以正常执行

127.0.0.1:6379> set k1 "v1"
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> incr k1  #运行时异常,执行时失败
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> get k2
QUEUED
127.0.0.1:6379> exec #运行时,不影响其他命令
1) (error) ERR value is not an integer or out of range
2) OK
3) "v2"

监控!

悲观锁:

  • 很悲观,什么时候都会出问题,无论什么都会加锁!

乐观锁:

  • 很乐观,认为什么时候都不会出现问题,所有不上锁,更新数据时去判断数据是否改动!
  • 获取version
  • 更新时比较version

Redis测试

正常执行成功!

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 #监视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
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> decrby money 10
QUEUED 
127.0.0.1:6379> incrby out 10
QUEUED
127.0.0.1:6379> exec #执行之前,另一个线程,修改了值,导致执行失败
(nil)

#另一个线程
127.0.0.1:6379> get money
"80"
127.0.0.1:6379> set money 1000
OK

#如果事务执行失败,就解锁 unwatch
#再重新执行这个事务的命令,获取最新的值!

二、Redis.conf详解

启动的时候,通过配置文件启动!

单位
一篇Redis搞定面试官《Java-2021面试谈资系列》_第1张图片

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

包含

就好比我们学习的spring,import

网络

bind 127.0.0.1  #绑定的ip

protected-mode yes #开启安全模式

port 6379 #端口号

通用

daemonize yes #守护进程方式开启,默认no

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 "" #日志的文件位置名

databases 16 #默认16个数据库
always-show-logo yes #是否显示logo

快照

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

#redis是内存数据库,如果没有持久化,那么数据断电即失去!
save 900 1 #900秒内,如果至少有一个key进行了修改,我们即进行持久化操作
save 300 10
save 60 10000

#之后可以自己定义测试

stop-writes-on-bgsave-error yes
#持久化如果出错,是否还需要继续工作!

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

rdbchecksum yes
#保存rdb文件时,进行错误校验

dir ./ #文件保存目录

安全

#默认密码为空
127.0.0.1:6379> config get requirepass
1) "requirepass"
2) ""

#设置密码
127.0.0.1:6379> config set requirepass "123456"

限制

maxclients 10000 
#设置能连接redis最大的连接数

maxmemory <bytes>
#redis设置最大的内存容量

maxmemory-policy noeviction
#内存达到上限之后的处理策略

#maxmemory-policy 六种方式
1、volatile-lru:只对设置了过期时间的key进行LRU(默认值) 
2、allkeys-lru : 删除lru算法的key   
3、volatile-random:随机删除即将过期key   
4、allkeys-random:随机删除   
5、volatile-ttl : 删除即将过期的   
6、noeviction : 永不过期,返回错误

AOF:APPEND ONLY MODE

AOF的配置

appendonly no #默认不开启,默认使用rdb

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

# appendfsync always #每次修改都会写入,速度慢
appendfsync everysec  #每秒执行一次同步,可能会丢失这一秒的数据
# appendfsync no     #不同步,速度快

三、Redis持久化

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

3.1RDB (Redis DataBase)

什么是rdb
一篇Redis搞定面试官《Java-2021面试谈资系列》_第2张图片
rdb保存的文件就是:dump.rdb
在这里插入图片描述
都是在我们的配置文件中的快照里面设置

触发机制

1.save的规则满足的情况下,会自动触发rdb规则!

2.执行flushall命令,也会触发我们的rdb规则

3.退出redis,也会产生rdb文件!

备份就是自动生成一个rdb文件

如何回复rdb文件!

1.只需要将rdb文件放在我们redis启动的目录下,redis启动的时候会自动检查dump.rdb

恢复其中的数据!

2.查看需要存放的位置

127.0.0.1:6379> config get dir
1) "dir"
2) "/usr/local/bin" #如果在这个目录下存在dump.rdb文件,启动会自动扫描,恢复其中数据

优点:

  • 适合大规模数据恢复!dump.rdb
  • 对数据完整性要求不高!

缺点:

  • 需要一定的时间间隔进程操作!如果redis意外宕机了,这个最后一个修改数据就没了!
  • fork进程的时候,会占用一定的内存空间!

3.2AOF(Append Only File)

是什么

将我们的所有命令都记录下来,history,恢复的时候,就是把这个文件里面的命令再执行一次
一篇Redis搞定面试官《Java-2021面试谈资系列》_第3张图片

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

aof保存的文件:appendonly.aof

appendonly no #默认不开启,默认使用rdb

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

# appendfsync always #每次修改都会写入,速度慢
appendfsync everysec  #每秒执行一次同步,可能会丢失这一秒的数据
# appendfsync no     #不同步,速度快

默认不开启,需手动配置开启,重启redis就可以生效!

如果这个aof文件有错误,可以采用修复
一篇Redis搞定面试官《Java-2021面试谈资系列》_第4张图片

redis-check-aof --fix 文件名

优点:

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

缺点:

  • 相对于数据文件,aof远远大于rdb,修复数据比rdb慢
  • aof运行效率比rdb慢,所以我们redis默认的持久化是rdb

重写机制
一篇Redis搞定面试官《Java-2021面试谈资系列》_第5张图片
当文件大于64m,fork一个新的进程来将我们的文件重写!会无限追加,越来越大,导致效率低下!

四、Redis发布订阅

发布订阅是一种消息通信模式:发布者pub发送消息,订阅者sub接收消息。

微博,微信,关注系统等!

Redis客户端可以订阅任意数量的频道
一篇Redis搞定面试官《Java-2021面试谈资系列》_第6张图片
第一个:消息发送者

第二个:频道

第三个:消息订阅者!

命令
一篇Redis搞定面试官《Java-2021面试谈资系列》_第7张图片

测试:

========频道================
127.0.0.1:6379> clear
127.0.0.1:6379> subscribe zjdzka
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "zjdzka"
3) (integer) 1

1) "message"
2) "zjdzka"
3) "hello,redis"

1) "message"
2) "zjdzka"
3) "hello,java"


========发布者==============
127.0.0.1:6379> publish zjdzka "hello,redis"
(integer) 1
127.0.0.1:6379> publish zjdzka "hello,java"
(integer) 1
127.0.0.1:6379> 

使用场景:

  • 实时消息
  • 实时聊天
  • 订阅,关注系统
  • 复杂一点:使用消息中间件如MQ

五、Redis主从复制

主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(master/leader),后者称为从节点(slave/follower);数据的复制是单向的,只能由主节点到从节点。默认情况下,每台Redis服务器都是主节点;且一个主节点可以有多个从节点(或没有从节点),但一个从节点只能有一个主节点
一篇Redis搞定面试官《Java-2021面试谈资系列》_第8张图片

主从复制,读写分离

5.1环境配置

只配置从库,不用配置主库

#查看信息
127.0.0.1:6379> info replication
# Replication
role:master #角色
connected_slaves:0 #无从机
master_replid:a1e2ce7a051ce03606c7c53ea06ca3c90752f535
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个配置文件,然后修改对应的信息

  • 端口
  • pid名字
  • log文件名字
  • dump.rdb文件名字
    一篇Redis搞定面试官《Java-2021面试谈资系列》_第9张图片

5.2一主二从

默认情况下每一台redis都是主机

#认老大!
127.0.0.1:6381> slaveof 127.0.0.1 6379
OK


127.0.0.1:6380> slaveof 127.0.0.1 6379
OK

127.0.0.1:6380> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6379
master_link_status:down
master_last_io_seconds_ago:-1
master_sync_in_progress:0
slave_repl_offset:1
master_link_down_since_seconds:1615087654
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:053a2768c0c78d4c682a605159d914ff5e471769
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

主机:

真实的配置主从,是在配置文件中永久的配置

127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=6381,state=online,offset=42,lag=1
slave1:ip=127.0.0.1,port=6380,state=online,offset=42,lag=1
master_replid:1d5258fc7605709d9d0f89f0f100853405e9139a
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:42
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:42

细节

  • 主机负责写,从机负责读!主机中的所有信息和数据都会自动被从机保存
    一篇Redis搞定面试官《Java-2021面试谈资系列》_第10张图片

主机断开连接,从机依旧可以连接到主机,但是没有写操作。但是主机回来,从机还可以继续操作

注意:

如果是使用命令行配置的主从,这个时候如果重启,从机会变成主机

但是只要变成从机,数据立马可以从主机在获取值

层层链路模型

上一个主节点连接下一个从节点

如果没有老大了,这个时候能不能选择一个老大呢?

如果主机断开了连接,我们可以使用slaveof no one 让自己变成主机!其他的节点就可以主动连接到最新的这个主节点(手动!!!)

5.3哨兵模式

自动选取老大的模式!!!

概述:

在主从模式的Redis系统中,从数据库在整个系统中起到了数据 冗余备份和 读写分离的作用,但是当数据库遇到异常中断服务后,我们只能通过手动的方式选择一个从数据库来升格为主数据库,显然这种方式很麻烦需要人工介入,这时通过哨兵模式可以实现自动化的系统监控和故障恢复。

测试!

1.配置哨兵配置文件

sentinel monitor myredis 127.0.0.1 6379 1

后面的数字1代表主机宕机,进行从机投票选举

2.启动哨兵!

redis-sentinel myconfig/sentinel.conf 

3.如果master节点宕机,从机中随机选择–投票算法
一篇Redis搞定面试官《Java-2021面试谈资系列》_第11张图片
4.如果之前的主机回来了,只能归并到新的主机下,当从机
在这里插入图片描述
优点:

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

缺点:

  • redis不好在线扩容
  • 实现哨兵模式的配置其实很麻烦

你可能感兴趣的:(笔记,java,redis,linux,java)