IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> 【Redis】Redis事务、主从复制、哨兵模式、消息订阅、Jedis客户端 -> 正文阅读

[大数据]【Redis】Redis事务、主从复制、哨兵模式、消息订阅、Jedis客户端

Redis


Redis数据库事务、持久化、主从复制、安全设置、Jedis操作Redis 【普及】


NoSQL ---- Redis的基本命令和数据类型的常见指令分享了一下,这些命令掌握之后才能进行其他的高级操作,博主接下来的一个月的重心就是数据库领域,Mysql和Redis的基础介绍了,但是没有深入呢,比如什么主从复制,锁机制,使用B树,SQL优化…

刚刚Fn+ F11将触摸屏锁了,最开始没有意识到,以为鼠标不见了,还是命令好啊,easy调出控制面板,发现没有问题,就打开dos,输入shutdown 就可以关机了;

Redis

Redis是作为Cache使用的基于key-value的NoSql数据库,所在的层次应该是在service和dao层之间,其主要的功能就是减少了磁盘IO的次数,利用的局部性原理切实提高的性能;Nosql牺牲了很多来提高性能,其中就包括事务【🔒】

Redis事务

事务时一系列的操作步骤,这一些列操纵要么完全执行,要么完全不执行。Redis中的事务就是一组命令的集合,至少时两个或者两个以上的命令,redis事务保证这些命令被执行的时候不会被其他的任何操作打断 ---- 和Mysql中的事务概念是不相同的 没有回滚rollback的概念

事务操作指令

multi 标记事务的开始

(multi 多)可以简单理解为创建了一个任务队列【可以理解为ES6中的任务队列类似】,可以看出就是一个装指令的队列,事务内的多条指令会按照先后顺序放到这个队列中

返回值总是ok

exec 执行任务队列中的所有指令

execute 执行, exec简写,执行事务块 ----- 任务队列中的所有的命令

返回值就是事务内的所有执行语句的内容, 如果事务被影响打断就返回nil -----> 所以不是一定执行成功

discard 放弃队列中所有的命令

(之前的set和zset统计数量就是scard和zcard命令),【discard 弃置】,取消事务,放弃执行事务块内的所有的命令

返回值总是ok ---- 简单理解为删除整个队列

watch 观察监视一个或者多个key

watch key [key…] 监视一个或者多个key,可以理解为一个异步的线程,如果在当前事务执行exec之前,这些key被其他的命令改动,那么该事务就会被打断,取消执行diacard

返回值总是ok

unwatch 取消所有的监视

取消watch命令对所有的key的监视,如果在执行watch命令之后,exec或者discard先执行,就不需要unwatch了,因为没有取消的必要了,返回值也总是ok

事务实现

可以看出来,Redis中的事务的含义就是将一些命令加入到队列中,也就是暂时先不执行指令,等到exec放出后才开始执行所有的指令;【Mysql中的指令就是自动的保证一组DML语句同时成功或者同时失败】

正常执行事务

正常执行事务就是

  • 首先开启事务multi
  • 向事务队列中加入命令【添加成功会显示QUEUED】
  • exec执行任务队列中的所有命令

返回的结果就是每条指令执行的任务列表

127.0.0.1:6379[5]> select 0
OK
127.0.0.1:6379> multi 
OK
127.0.0.1:6379(TX)> set usr CFENG
QUEUED
127.0.0.1:6379(TX)> set class HC2001
QUEUED
127.0.0.1:6379(TX)> set no 1001
QUEUED
127.0.0.1:6379(TX)> get usr
QUEUED
127.0.0.1:6379(TX)> get class
QUEUED
127.0.0.1:6379(TX)> get no
QUEUED
127.0.0.1:6379(TX)> exec
1) OK
2) OK
3) OK
4) "CFENG"
5) "HC2001"
6) "1001"

入队的命令语法错误、或者严重错误导致不能工作 — 自动放弃

事务执行exec前,redis可以根据命令的语法来判断命令是否书写正确,类似可检查异常,这个时候就会直接给出错误信息,并且放弃事务discard

127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> set usr CSHENG
QUEUED
127.0.0.1:6379(TX)> incr no class
(error) ERR wrong number of arguments for 'incr' command
127.0.0.1:6379(TX)> get usr
QUEUED
127.0.0.1:6379(TX)> exec
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> get usr
"CFENG"

命令没有语法错误,但是执行出错 ---- 事务提交

redis中没有要求同时成功或者同时失败,没有回滚的概念, 所以当某条命令执行出错,其他的命令还是会正常执行的,只是结果列表中,会显示错误的信息

Redis追求高效,如果要求回滚那么性能就降低,设计者认为这种命令执行错误问题可以测试避免,不会出现在生产环境中

127.0.0.1:6379> multi 
OK
127.0.0.1:6379(TX)> set usr CLEI
QUEUED
127.0.0.1:6379(TX)> lrange class 0 -1
QUEUED
127.0.0.1:6379(TX)> exec
1) OK
2) (error) WRONGTYPE Operation against a key holding the wrong kind of value
127.0.0.1:6379> get usr
"CLEI"

手动放弃事务 discard

可以直接执行discard命令,就会放弃执行之前的命令队列中的命令

127.0.0.1:6379> multi 
OK
127.0.0.1:6379(TX)> set usr CHUAN
QUEUED
127.0.0.1:6379(TX)> discard
OK
127.0.0.1:6379> get usr
"CFENG"

watch机制的多线程操作

watch监视的key如果在另外的位置已经进行了修改,那么当前整个事务就会直接被取消,类似于Mysql中的乐观锁,先到先改,后面的就自动放弃,不参与竞争 【因为大多数情况下,不同的客户端访问的是不同的key,竞争情况很少】

  • watch命令生效时间就是watch执行开始,到调用exec为止,之后不管是否成功执行事务,监视都会取消
  • 客户端断开连接时,对该客户端的key的监视也会自动discard
  • unwatch可以手动取消监视【但是不监视,就没有乐观🔒】
-----客户端A中在B开启watch之后修改了值---
[root@localhost ~]# cd /usr/local/redis-6.2.6/src
[root@localhost src]# ./redis-cli
127.0.0.1:6379> keys *
1) "usr"
2) "no"
3) "class"
127.0.0.1:6379> set usr CLEI
OK
127.0.0.1:6379> get usr
"CLEI"


------客户端B在A执行之后想要修改同一个key-----乐观锁、自愿放弃所有的事务
[root@localhost src]# ./redis-cli
127.0.0.1:6379> keys *
1) "usr"
2) "no"
3) "class"
127.0.0.1:6379> watch usr
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> incr no
QUEUED
127.0.0.1:6379(TX)> set usr CHUAN
QUEUED
127.0.0.1:6379(TX)> exec
(nil)
127.0.0.1:6379> get usr
"CLEI"
127.0.0.1:6379> get no
"1001"

持久化 rdb、aof

持久化就是存储,将数据存储到不会丢失的位置,redis是一个键值对方式的缓存cache,电脑重启或者断电数据丢失,内存、缓存的数据都不是持久化的,放在磁盘文件中就是持久化;redis提供了rdb和aof方式来进行持久化

RDB redis database

数据集快照 ---- 在指定的时间间隔中将内存中的数据集快照写入磁盘,数据恢复时自动将快照文件读到内存, 默认是使用的rdb方式,所以博主每次登录的时候之前的测试数据还是存在

RDB保存了某个时间点的全部数据,存在一个二进制文件中,默认就是dump.rdb,这个文件的路径默认是./ – 和cli在同一个目录下

RDB技术适合做备份,可以保存醉经的全部数据; 保存数据是单独的进程在操作,不影响Redis的使用,之前就是看到过提示信息,RDB恢复数据比AOF快

可以使用在redis.conf中键入snapshots,就可以到达RDB的设置位置:

save time changetimes time的单位为s,就可以设置是否

可以通过save “” 来关闭RDB // 同时需要注意的是还有其他的选项,比如dir就是保存的目录,默认就是启动目录src

原理 : 进程复制

Redis会复制一个与当前进程一样的进程,新进程的所有的数据【变量、PC等】都一致,但是是一个全新的作为源进程的子进程,进行持久化。主进程是没有进行IO操作的,所以高性能

但是缺点就是最后如果数据改变次数没有达到触发条件,就不会进行持久化,数据的完整性较差。最后依次的数据可能丢失,如果需要进行大规模数据恢复,还是使用RDB,因为更快【不敏感】

每次同步数据到磁盘都会生成一个新的rdb文件,会覆盖源文件,redis启动时会加载dump.rdb文件

AOF append only File

redis默认不开启,这个功能可以弥补rdb的不足【数据的完整性和不一致】,采用的是日志的方式来记录每一个写操作,读操作不记录,并且是追加到日志文件中,不是覆盖 ---- 所以这个文件会越来越大… 这个时候就可以使用自动的优化机制; redis重启的时候会根据日志文件写指令完成数据库的恢复,默认不开启

可以就当作一个日志,记录了所有的修改操作,重启的时候重新执行写指令来进行恢复数据。

aof保存的文件都是appendonly.aof文件,位置就是Redis的启动目录,开启AOF,每次写操作都追加操作内容

实际开发中,可能因为某种操作出现异常,这个时候就可以使用命令redis-check-aof-fix appendonly.aof 来进行修复,这个时候就会将异常操作去掉

也可以在文件中开启AOF,直接搜索AOF就可以找到位置
appendonly : 是否开启aof,开启就选择yes
appendfilename  : AOF保存文件名,默认即可
appendfsync: 持久化策略,always就是每次写操作都同步,而eversrc就是每秒同步一次, 而no就是不即时同步,操作系统决定,可能是30s【默认就是everysec】

AOF重写

AOF采用的是文件追加的方式,就这份日志的内容会越来越大,重写机制就可以压缩AOF的文件内容,只保留可以恢复数据的

比如 set k1 v1; set k1 v3 ; set k1 v5; 这几条指令就直接为set k1 v5; AOF文件持续增长而过大时,就会fork出一条新的进程来重写文件,先写临时文件,之后rename,默认情况下时rewrite后上次的1倍但是小于64M

Redis消息的发布和订阅

Redis除了可以用作Cache之外,还可以用来做消息队列,可以进行消息的发布和订阅,可以和dubbo来对比

Redis发布订阅【pub/sub】是一种消息通信的模式,缔约接收消息,Redis客户端可以订阅任何的频道

在这里插入图片描述

消息发布者将消息发布到频道,然后消息就会发送给3个订阅者

发布订阅的命令

这里就先简单介绍,之后这里就可以基于Redis和socket网络通信做聊天室嵌入网页中

subscribe channelx 订阅 一个或者多个频道

这个命令就可以订阅频道,返回值就是订阅的消息 这里同时也会创建出一个频道

publish channel message 发送消息message到channel

将信息发送到指定的频道, 这样另外一个客户端订阅者就可以接收到信息

psubscribe pattern 订阅所有给定模式的频道

这里的pattern就是进行通配的,因为频道很多,比如 psubscribe new.*

返回值也是订阅频道的消息

主从复制【集群、哨兵sentinel】

主从复制针对的就是Redis集群,因为在实际的生产环境中,一台服务器能够承载的访问量是很低的,所以就出现了分布式集群,多台服务器集合在一起干一件事情,也就成为集群,比如Redis缓存Cache,为了能够提高效率,也就可以使用Redis集群,这个时候需要考虑主从复制

主机数据更新后根据配置和策略,自动同步到从机;【也就是主机和从机的数据是共享的,相同的】;Master以写为主,可以查询,Slave以读为主,但是不能写;

一主二从

一主二从是小规模的集群,一台主机,两台从机,主写从读,实现读写分离; 主机如果宕机,如果有哨兵,那么久可以自动选举产生新的主机,如果没有,就手动将从升主机

配置从属关系: slaveof 主库 IP 端口

这里可以简单使用一台虚拟机,配置3份redis.conf文件模拟三台服务器【占据不同的端口】

[root@localhost redis-6.2.6]# cp redis.conf redis6382.conf
[root@localhost redis-6.2.6]# vim redis6380.conf 
[root@localhost redis-6.2.6]# vim redis6381.conf 
[root@localhost redis-6.2.6]# vim redis6382.conf 


这里修改的配置文件
port 修改
dbfilename 修改  //dump.rdb
logfile  修改   6379.log
pidfile   进程标识

之后打开3个窗口分别加载3个配置文件启动redis-server,模拟3太服务器

设置主从关系

可以直接在客户端中使用命令: 比如这里是6380为主

info replication 复制的信息 ; 就是当前机器的主从关系

在81和82客户端分别slaveof 127.0.0.1 6380 就建立了主从关系
# Replication
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=6382,state=online,offset=56,lag=0
slave1:ip=127.0.0.1,port=6381,state=online,offset=56,lag=1
master_failover_state:no-failover
master_replid:54c1d33b181f10ff1a4019a19867bbdafce2e8b9
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:56
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:56





127.0.0.1:6382> set age 12
(error) READONLY You can't write against a read only replica.

Redis就可以自动开启主从复制—全量复制和增量复制

  • 全量复制: 主机中的全部数据,从机都可以获取到
  • 增量复制: 主机set的数据, 马上再从机查询可以查询到

复制的原理:

全量复制: slave启动后成功连接到master之后会发送一个sync命令,Master接收后启动后台的存盘进程,手机所有的修改指令,后台进程执行完毕,master传送整个数据文件给slave,完成一次全同步,接收后,存盘并加载到内存, 每次重新连接,一次全量复制就会自动进行

增量复制:Master将所有收集的修改指令传送给slave,完成同步

主机宕机,手动改变主从关系

这里模拟宕机,退出6380服务器,然后手动让6382成为主机

6382 salveof no one 6381 slaveof 6382

哨兵模式搭建[高可用]

从机上位自动进行,哨兵是独立的进程,通过发送一个心跳的命令ping ,如果指定事件没有pong返回,就认为挂了,投票选举新的master,通过消息订阅通知其他的slave,自动切换主机

哨兵模式搭建和之前的主从复制类似,必须是奇数个哨兵,要进行投票, 哨兵进程占用的端口号为26379, 配置文件为redis_sentinel.conf, 这里也可以复制3份

修改其中的内容, 端口号port, 监控的策略

sentinel nonitor mymaster 192.168.204.100 26379 2 [大于2就进行主从关系的切换]
如果有密码
sentinel auth-pass mymaster XXX

启动哨兵进程和server类似,也是加载配置文件

[root@localhost redis-6.2.6]# cp sentinel.conf sentinel26381.conf
[root@localhost redis-6.2.6]# cp sentinel.conf sentinel26382.conf
[root@localhost redis-6.2.6]# vim sentinel26382.conf 
[root@localhost redis-6.2.6]# vim sentinel.conf 
[root@localhost redis-6.2.6]# vim sentinel26382.conf 
[root@localhost redis-6.2.6]# vin sentinel26381.conf 
bash: vin: 未找到命令...
[root@localhost redis-6.2.6]# vim sentinel26381.conf 
[root@localhost redis-6.2.6]# vim sentinel26382.conf 

开启三个窗口分别开启3个哨兵进程

[root@localhost src]# ./redis-sentinel ../sentinel26382.conf 

可以查看监控信息【这里还是让主机宕机然后恢复】

4370:X 07 May 2022 21:44:01.015 # +monitor master mymaster 127.0.0.1 6380 quorum 2
4370:X 07 May 2022 21:44:01.015 * +slave slave 127.0.0.1:6382 127.0.0.1 6382 @ mymaster 127.0.0.1 6380
4370:X 07 May 2022 21:44:01.017 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6380
4370:X 07 May 2022 21:44:01.164 * +sentinel sentinel 07016e2727a59ccc452ee94b0332279a56909459 127.0.0.1 26381 @ mymaster 127.0.0.1 6380
4370:X 07 May 2022 21:44:01.904 * +sentinel sentinel cbbf8194187381ebe814534fd4198a0895f7b65c 127.0.0.1 26379 @ mymaster 127.0.0.1 6380
4370:X 07 May 2022 21:46:27.584 # +sdown master mymaster 127.0.0.1 6380
4370:X 07 May 2022 21:46:27.673 # +new-epoch 1
4370:X 07 May 2022 21:46:27.674 # +vote-for-leader cbbf8194187381ebe814534fd4198a0895f7b65c 1
4370:X 07 May 2022 21:46:27.685 # +odown master mymaster 127.0.0.1 6380 #quorum 2/2
4370:X 07 May 2022 21:46:27.685 # Next failover delay: I will not start a failover before Sat May  7 21:52:27 2022
4370:X 07 May 2022 21:46:28.266 # +config-update-from sentinel cbbf8194187381ebe814534fd4198a0895f7b65c 127.0.0.1 26379 @ mymaster 127.0.0.1 6380
4370:X 07 May 2022 21:46:28.266 # +switch-master mymaster 127.0.0.1 6380 127.0.0.1 6382
4370:X 07 May 2022 21:46:28.266 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6382
4370:X 07 May 2022 21:46:28.266 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6382
4370:X 07 May 2022 21:46:58.292 # +sdown slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6382
4370:X 07 May 2022 21:48:35.338 # -sdown slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6382
4370:X 07 May 2022 21:49:17.334 # +sdown slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6382
4370:X 07 May 2022 21:49:19.358 * +reboot slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6382
4370:X 07 May 2022 21:49:19.424 # -sdown slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6382
4370:X 07 May 2022 21:50:29.627 * +reboot slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6382

可以看到主机宕机后哨兵选举82成为新的主机

127.0.0.1:6382> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=6381,state=online,offset=113190,lag=0
slave1:ip=127.0.0.1,port=6380,state=online,offset=113190,lag=1

主机恢复后自动成为82的从机【反正数据是共享相同的】

查看源图像

哨兵有3个功能: 监控、提醒、 故障转移【 提醒就是可以提醒管理员出现异常】故障转移就是自动选举

安全设置

这里的安全设置很easy,就设置一下密码,这样客户端访问就必须使用密码才能够访问,修改redis.conf的requirepass,设置密码

设置的密码要复杂,因为redis访问速度快,破解速度快

requirepass XXXX

访问有密码的redis有两种方式

  • 连接客户端后,会进入之前的界面,如果有密码,是不能进行set、get操作的,这个时候输入
> auth XXX    返回OK,就正常访问
  • 连接客户端时,可以直接-a 接密码
# ./redis-cli -p 6380 -a XXX

同时还要修改端口号,不然都知道默认端口为6379

Jedis和Commons-pool

Jedis就是Redis的java客户端,利用Jedis对象就可以操作Redis数据库,Jedis对象类似于之前的mysql中的Connection对象;但是之前的Connection要复杂一些【还有Statement操作对象和Result返回结果集】

Jedis的好处就是操作的命令和之前分享的Redis的命令相同

Jedis对象不是线程安全的,再多线程下使用同一个Jedis对象出现并发问题,避免重新构建,所以也是池化的思想,提供Pool,JedisPool就是基于Commons Pool 2实现的线程安全的连接池

    <dependency>
      <groupId>redis.clients</groupId>
      <artifactId>jedis</artifactId>
      <version>4.2.1</version>
    </dependency>

    <dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-pool2</artifactId>
      <version>2.11.1</version>
    </dependency>

导入依赖,现在就可以进行连接,下面给一个简单的测试程序

//这里出现报错可能是因为开启了保护模式,装载一个配置文件bak_redis.conf,将其中的protect—model 设置为no

    @Test
    public void testJedis() {
        Jedis jedis = new Jedis("192.168.204.100",6379);
        jedis.set("breakTime","晚上23点");
        System.out.println(jedis.get("breakTime"));
    }
}

晚上23点

这里就正常进行连接了,对于连接池来说,需要配置连接池的相关参数,这样就可以直接从池中获取jedis对象,

Jedis jedis = pool.getSource(); 使用完毕之后close放回即可

明天将谈谈如何在SpringBoot中进行配置🎉

  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2022-05-09 12:46:25  更:2022-05-09 12:48:48 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 23:30:17-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码