redis
1redis可以用来干什么
-
1.缓存
缓存机制可以说是所有大型网站必备的,缓存能够有效地缓解后端数据源的压力。Redis提供了键值过期时间的设置,提供了灵活控制最大内存和内存溢出后的淘汰策略。
2.排行榜
排行榜系统几乎存在于所有的网站,比如按照热度排名的排行榜,按照时间,以及按照各种复杂维度计算出的排行榜。Redis提供了列表和有序集合数据结构,对于排行榜非常方便。
3.计数器应用
计数器在网站中至关重要,如视频网站播放数,电商浏览数,为了保证数据实时性,这对高并发的的传统关系型数据库的性能是一种很大的挑战。Redis却非常方便。
4.社交网络
赞/踩,粉丝,共同好友/洗好,推送,下拉刷新等是社交网站的必备功能,由于社交网站的访问量比较大,传统的关系型数据库不适合保存这种类型的数据,Redis提供的数据结构可以比较容易的实现这些功能。
5.消息队列系统
消息队列也是大型网站的必备基础组件,因为其具有业务解耦,非实时业务削峰等特性。Redis也提供了这些功能。
Redis不适合做什么?
对于Redis不适合做什么,可以从数据大小和数据冷热角度进行分析。比如如果每天有几亿用户行为数据,使用redis来存储基本就是个无底洞。冷热数据是指,对于视频网站来说,视频基本信息是各个业务线都要经常操作的数据,需要存在Redis,而用户的观看记录不是经常访问的数据,所以可以放在传统数据库里。
2.redis 的安装
-
环境准备
- 1.虚拟机一台
- centso7
- 需要安装gcc依赖 yum install gcc
-
下载redis 安装包
-
主页 : www.redis.io
-
1.将压缩包上传到虚拟机
-
2.解压安装包 使用 tar -zxvf 安装包名(redis-5.0.5.tar.gz)
-
解压完成后, 进入解压目录执行make命令
-
如果出现make 没法执行 安装gcc命令 yum install -y gcc
-
安装完后执行make 如果出现致命错误
-
直接在make命令后加上 MALLOC=libc —> make MALLOC=libc 执行
-
make MALLOC=libc 执行后,
执行 make install PREFIX=/要解压到的指定目录(/usr/redis)
返回~ 目录 -
-
进入 /usr/redis/bin
-
-
启动redis ./redis-server
-
开启一个窗口接收请求 port :端口号 pid 进程id 按住ctrl+c 停止
-
-
新开一个窗口 模仿客户端发消息给redis
新窗口进入 /usr/redis/bin 启动客户端 ./redis-cli -p 6379 -h 127.0.01
-p 指定端口号
-h 指定要连接的ip 地址
(如果不指定-p -h 会使用默认,默认就是6379 和127.0.0.1)
-
3.redis 的常用命令
redis默认有16个库 ,默认从0-15 默认使用的是0号库
1.切换库
切换库 select 库的编号
清空当前库中的所有数据 flushdb
清空所有库中数据 flushdbAll
2.key 相关指令
set 键 值
获取键的值 gei 键
1.del key --删除一个或多个key
虚拟机连接数据库
2.exists key 检查给定的key 是否存在 若key 存在,就返回1,否则返回0
3.expire key 数字 设置一个key 的过期时间 时间单位为秒 (可以用于手机验证码过期时间)
4.keys * 原来查看库中的所有key
-
(* ) 匹配0- 多个任意字符
-
(?) 匹配1个任意字符
-
[] 匹配 一个【】 中包含的字符
-
5.move key 库号 移动key 到指定库中
6.pexpire key 设置一个key 的过期时间 单位为毫秒
7.pexpireat key 设置key的过期时间,,时间为时间戳
8.ttl key 获取一个key的存货时间 单位为秒
- 返回值 >=0 剩余时间
- -1 永不过期
- -2 代表当前key 不存在
9.pttl key 原来获取一个key 的剩余时间, 时间单位为毫秒
-
randomkey 随机返回一个key 不会将返回的key 删除
-
rename keyold keynew 给已存在的key 修改名字
-
type key 原来判断一个key 所对应的值的类型
当我们存储一个键值对时 如果value 是中文 ,取出来是编码,默认连接的客户端不支持对中文作转码,如果想要作转码的话, 在启动客户端的时候加上
--raw ---> ./redis-cli --raw
- mset key value key value key value 设置多个键值对
-
getset 获得原来的key值 同时设置新值
-
strlen key 获取对应key存储value 的长度
-
append key value 为对应key 的value 追加内容
-
getrange key 截取value 内容 索引从0开始 临时截取
getrange key 0 -1 截取所有的内容
-
setex 设置一个key的存活有效期 秒
-
psetex 设置一个key的存活有效期 毫秒
-
setnx key value 存在不做任何操作 ,不存在添加
-
mestnx 可以同时设置多个key ,只要有一个存在都不保存
-
decr 进行数值类型的-1 操作
-
decrby 根据提供的数据进行减法操作
-
incr 进行数值类型的+1操作
-
incrby 根据提供的数据进行加法操作
-
incrbyfloat 根据提供的数据加入浮点数
redis中的细节和Java操作redis
1.redis细节
- 修改redis 的加载配置文件启动(可以修改redis启动的端口号等。。。。)
- 好处 : 通过redis配置文件修改默认参数
redis .conf 是redis 的配置文件
1.2 将配置文件复制一份到 ./usr/redis/bin 一份
1.2.使用配置文件形式启动redis —> ./redis-server 配置文件路径和名称
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MNHvdOeA-1620347639468)(C:\Users\鲜芳\AppData\Roaming\Typora\typora-user-images\1618487123804.png)]
1.3.修改配置文件默认端口号 直接修改配置文件即可
2.Java操作redis
1.客户端指定端口号 和主机ip 连接resdis (redsi 连接远程主机连接不上,)
./redis-cli -p 端口号 -h 主机名
2.开启redis 的远程连接权限
修改配置文件redis.conf的bind (这里代表绑定的127.0.0.1 表示只能连接本地 所有不能连接其他的ip ) 修改为 bind 0.0.0.0 即可远程连接其他的ip 地址
修改配置文件的端口号为7000
使用配置文件的形式启动redis-server \
./redis-server ../redis.conf
在客户端直接开启 远程李连接
./redis-cli -p 7000 -h 192.168.119.129
3.安装redis 可视化工具
也可以使用another redis desktop manager来操作
官网地址: https://redisdesktop.com/download
或者
百度网盘:https://pan.baidu.com/s/15xVRpCT8mkP2uT8PoBHT3g 提取码:v727
下载步骤参考以下博客地址
https://blog.csdn.net/JacaCao/article/details/106088148?ops_request_misc=&request_id=&biz_id=102&utm_term=%E5%AE%89%E8%A3%85redis%20%E5%8F%AF%E8%A7%86%E5%8C%96%E5%B7%A5%E5%85%B7&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduweb~default-2-106088148.first_rank_v2_pc_rank_v29&spm=1018.2226.3001.4187
如果可视化工具李连接不上,可以康康防火墙关闭没有, systemctl status firewalld
如果没有使用 systemctl stop firewalld
4.redis服务器守护进程启动
就是是redis启动后会占用一个窗口,如果我们要启动客户端又要另外开个窗口,守护进程启动就是启动服务和启动客户端都在一个窗口(就是redis-server 在后台启动)
1.修改redis.conf 里面的daemonize no 修改为 daemonize yes
查看是否启动 ps axu|grep redis
可以直接在该窗口开启客户端 ./redis-cli -p7000
5.修改redis 默认库的个数
默认库 : 0-15号
修改配置文件 redis.conf
前提是查看redis-server服务启动没有 启动了 要结束 redis服务 使用kill 进程id
修改并配置文件redis.conf 的databases 设置成想要的个数即可
2.java操作redis
启动redis -server
1.引入reids 操作依赖,
redis java —> jedis
引入jedis
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
创建jedis 对redis 进行操作
redis的持久化机制
1.redis中持久化?
持久化: 将数据永久保存到磁盘的过程,称之为数据持久化
2.快照的持久化机制有两种 :一种是快照持久化机制,另外一种是aof 只追加日志文件机制
-
快照持久化机制 ,redis默认是把数据存储在/usr/redis/bin dump.rdb里面了,每次redis时都会把dump.rdb的数据进行加载 dump.rdb是保存某时刻的数据状态
- 相当于虚拟机的快照
- 定义:将redis服务器中某一时刻的数据状态 ,以快照的形式写入xxx.rdb结尾文件中
- redis中默认的持久化机制
- 快照的生成时机(可以手动生成快照也可以让redis自动生成快照)
redis.conf设置每次生成默认快照文件名,前提是之前默认的dump.rdb已经删除,
-
创建快照的几种方式
1.手动快照 :
bgsave 保证快照持久化同时,不会阻塞redis主服务提供服务
save
-
客户端可以使用BGSAVE命令来创建一个快照,当接收客户端的BGSAVE命令时,redis会调用fork 来创建一个子进程,然后子进程负责将快照写入磁盘中,而父进程则继续处理命令请求
-
客户端还可以使用SAVE命令来创建一个快照,接收到SAVE命令的redis服务器在快照创建完毕之前将不再响应任何其他的命令
-
注意: SAVE命令并不常用 ,使用SAVE命令在创建快照完毕之前,redis处于阻塞状态,无法对外服务
-
fork解释: fork 当一个进程创建子进程的时候,底层的操作系统会创建该进程的一个副本,在类unix系统中创建子进程的操作会进行优化,在刚开始的时候,父子进程共享相同内存,直到父进程或子进程对内存进行了写之后, 对被写入的内存的共享才会结束服务
-
shutdowm redis在接收到这个指令会自动执行save命令 , 在save创建快照结束后关闭redis服务
2.自动创建快照
-
根据redis.conf 中配置的save选项自动触发bgsave
-
redis.conf 的secondes (时间 ;单位秒) changes (改变)
-
-
-
save 900 1 如果15分钟内 有1个key 发生变化,自动触发一次bgsave save 300 10 如果5分钟内 有10个key 发生变化,自动触发一次bgsave save 60 1000 如果1分钟内 有1000个key 发生变化,自动触发一次bgsave
save选项可以配置多个,任何一个满足都会触发一次快照持久化
-
快照持久化会丢失不定量的数据 ,刚刚做完快照,还没有到达下一次任何一个save选项的条件,此时如果redis服务出现宕机,会丢失在刚刚做完快照之后的所有客户端的写操作
-
aof 只追加日志文件机制 为了解决快照持久化丢失不定量数据问题
-
定义: append only file (只追加日志文件) redis服务会讲接收的所有客户端的写操作以命令的方式记录到一个名字为xxx.aof 日志文件中
-
开启aof 默认是没有开启的
- 修改redis.conf 文件中的 appendonly no 改为yes (appendonly yes)
-
指定aof 文件的名称 修改成想要的即可
- -
注意 ,日志文件存放的位置和快照文件指定目录一致
-
aof日志文件的同步频率
- 1.always : 将每个客户端写操作立即同步到sof文件中,严重降低redis速度
- 好处: 保证redis不丢失任何数据
- 2.everysec :每秒执行一次同步显示的将多个写命令同步到磁盘
- 好处: 当1秒内有多个客户端写操作只同步一次aof日志文件
- 缺点: 最多丢失1s内的数据
- 3.no : 由操作系统决定何时同步
- 1.always : 将每个客户端写操作立即同步到sof文件中,严重降低redis速度
-
在配置文件中指定同步频率即可
-
-
aof文件的重写
aof的方式也同时带来一个问题, 持久化文件会变得越来越大,极端情况会用尽所有的物理磁盘,导致redis服务阻塞甚至宕机。 例如我们调用100次set name xx 文件中必须保存全部的100条命令,其实有99条都是多余的,因为要恢复数据库的状态,其实文件中保存最后一次 set name xx就够了 为了压缩aof 的持久化redis提供了aof重写机制
aof 重写指的是: 将原来的aof日志文件进行压缩
重写机制:不是指对原始文件进行压缩,而是生成新的日志文件对原始文件进行替换
- 重写aof文件的两种方式
-
1.bgrewriteaof 客户端执行
- 执行流 程
- 1.执行 bgrewriteaof 命令后,,redis调用fork ,开启父子进程,,子进程根据内存中的数据库进行快照,往临时文件中写入重建数据库命令 (其实就是把当时数据库的数据作了一个快照,写入临时文件)
-
- 父进程继续处理客户端发来的请求,将请求缓存到一块区域,如果子进程执行完 快照处理写入临时文件的 任务后,再将缓存中的命令写入临时文件 执行完后就替换掉原来的aof文件, 如果子线程在执行重建数据库时发生异常 ,那么数据也不会发生丢失,会使用原来的aof文件,将缓存的请求写入到原来的aof文件
-
2.在配置文件redis.conf中配置自动重写选项
- 修改配置文件中的 auto-aof-rewrite-percentage 选项
-
springboot集成redis
1.创建一个springboot项目
-
(第一种方式) 使用Java操作redis 创建psringboot项目。导入依赖
-
<dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.9.0</version> </dependency>
-
使用jedis操作redis
-
2.引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive
</artifactId>
</dependency>
3.配置yml 文件
spring:
redis:
host: 192.168.119.129
port: 7000
database: 0
jedis:
pool:
max-active: 8
max-idle: 8
max-wait: -1
min-idle: 0
完成上述配置在启动springboot的应用后在工厂中自动创建两个对象
1.redisTemplate 第二种方式 专用于对象类型的操作
-
使用方式
-
注意:redisTemplate 默认使用key序列化方式和value的序列化方式使用的都是jdk Serializer序列化 (意思就是存入进去的key value被序列化,使用redisTemplate 用key 拿值的时候,拿不到,除非是使用redisTemplate 序列化进去) 如果是要传进去的value 是一个对象,该对象必须实现序列化
-
自定义redisTemplate 使用序列化方式
-
1.自定义key的序列化方式
-
2.自定义value的序列化方式
-
当取对象的时候想要它直接转换成对象 而不是一个一个去set复制 可以在设置value序列化方式的时候,把类型传进去
-
-
穿进去的字符串形式
-
-
直接这样获取对象即可
-
注意hash 要设置两个key 第二个key 要再设置一下序列化
还要第59行如果使用的是 leftPush 如果namesss这个不存在是不会做任何操作的 里面所有使用add方法只能添加一个对象,leftPushAll 如果key不存在就新建 而且可以一次性添加多个对象
-
-
2.StringRedisTemplate 第三种方式 专用于字符串类型的操作 key value 都是string
- 使用方式
- 操作key相关的api redisTemplate .xxx
- 操作String 类型 redisTemplate .opsForValue().xxx
- 操作List类型 redisTemplate .opsForList().xxx
- 操作Set类型 redisTemplate .opsForSet().xxx
- 操作Zset类型 redisTemplate .opsForZset().xxx
- 操作Hash类型 redisTemplate .opsForHash().xxx
一次业务中对key做n次操作 这个时候就用到了 约束key 的操作
- Key Bound Operations 绑定key做操作
- StringRedisTemplate.boundString|List|…(“key的名称”);
- 注意一旦绑定了key之后后续根据返回对象的操作都是基于这个key的操作
redis缓存应用
1.什么是缓存
2.缓存的好处
- 读写快
- 断电后 数据丢失
-
项目中缓存解决的问题
- 使用缓存可以提高网站的响应速度
- 减少请求每次访问数据库,给数据库带来的压力
-
项目中是否全部应用缓存
- 缓存应该适用于查询多, 增删改极少的这种业务场景
-
现有的项目中应该如何开发缓存模块
- springboort +mybatis 使用mybatis框架提供的二级缓存技术
- mybatis 二级缓存的使用 ,只需要在要使用的缓存模块的mapper.xml文件中加入 ’ ‘’ 即可 开启二级缓存
- 、想要注意的是 如果每个项目中都这样开启缓存,缓存是在jvm 里面开启的 如果缓存越来越大,会影响项目的运行 每个项目访问数据库开启缓存,还是增加了数据库的压力,我们此时可以使用redis 开启缓存,是每个项目访问redis的缓存即可,这样更加降低了数据库的压力
-
mybatis 自身缓存存在问题?本地缓存存在的缺陷
- 本地缓存存储当前运行的jvm内存中,如果缓存数据过多,会占用一定的jvm内存,会导致应用运行缓慢
- 不能在分布式系统中做到缓存共享
解决问题 :重写mybatis cache 使用redis作为分布式缓存
-
缓存会出现的问题
-
使用redis实现分布式session共享机制
-
在springboot项目中引入
-
操作redis的依赖,有了它就不用导入Jedis包了 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> <version>2.4.4</version> </dependency> 全局session管理依赖 <dependency> <groupId>org.springframework.session</groupId> <artifactId>spring-session-data-redis</artifactId> </dependency>
-
自定义一个配置类
-
-
-
redis订阅发布
redis发布订阅是一种消息通信模式,发送者(pub)发送消息,订阅者(sub)接收消息
redis客户端可以订阅任意数量的频道
订阅/发布消息图
下图展示了频道 channel1 , 以及订阅这个频道的三个客户端 —— client2 、 client5 和 client1 之间的关系:
当有新消息通过 PUBLISH 命令发送给频道 channel1 时, 这个消息就会被发送给订阅它的三个客户端:
命令
命令 | 描述 |
---|---|
PSUBSCRIBE pattern [pattern..] | 订阅一个或多个符合给定模式的频道。 |
PUNSUBSCRIBE pattern [pattern..] | 退订一个或多个符合给定模式的频道。 |
PUBSUB subcommand [argument[argument]] | 查看订阅与发布系统状态。 |
PUBLISH channel message | 向指定频道发布消息 |
SUBSCRIBE channel [channel..] | 订阅给定的一个或多个频道。 |
SUBSCRIBE channel [channel..] | 退订一个或多个频道 |
订阅端:
127.0.0.1:7000> SUBSCRIBE ks #相当于客户订阅一个公众号
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "ks"
3) (integer) 1
1) "message"
2) "ks"
3) "2333"
发送端:
127.0.0.1:7000> publish ks 2333 # 公众号发布消息
(integer) 1
127.0.0.1:7000>
原理
每个 Redis 服务器进程都维持着一个表示服务器状态的 redis.h/redisServer 结构, 结构的 pubsub_channels 属性是一个字典, 这个字典就用于保存订阅频道的信息,其中,字典的键为正在被订阅的频道, 而字典的值则是一个链表, 链表中保存了所有订阅这个频道的客户端。 客户端订阅,就被链接到对应频道的链表的尾部,退订则就是将客户端节点从链表中移除。
缺点
-
如果一个客户端订阅了频道,但自己读取消息的速度却不够快的话,那么不断积压的消息会使redis输出缓冲区的体积变得越来越大,这可能使得redis本身的速度变慢,甚至直接崩溃。
-
这和数据传输可靠性有关,如果在订阅方断线,那么他将会丢失所有在短线期间发布者发布的消息。
应用
- 消息订阅:公众号订阅,微博关注等等(起始更多是使用消息队列来进行实现)
- 多人在线聊天室。
稍微复杂的场景,我们就会使用消息中间件MQ处理。
redis的主从复制
概念
主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(Master/Leader),后者称为从节点(Slave/Follower), 数据的复制是单向的!只能由主节点复制到从节点(主节点以写为主、从节点以读为主)。
默认情况下,每台Redis服务器都是主节点,一个主节点可以有0个或者多个从节点,但每个从节点只能由一个主节点。
作用
1.数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余的方式。
2.故障恢复:当主节点故障时,从节点可以暂时替代主节点提供服务,是一种服务冗余的方式
3.负载均衡:在主从复制的基础上,配合读写分离,由主节点进行写操作,从节点进行读操作,分担服务器的负载;尤其是在多读少写的场景下,通过多个从节点分担负载,提高并发量。
4.高可用基石:主从复制还是哨兵和集群能够实施的基础。
一般来说,要将redis用于工程项目中,指使用一台reidis是万万不能的(宕机),原因:
1,从结构上,单个reids服务器会发送单点故障, 并且一台服务器需要处理所有的请求负载均衡, 压力较大
2,从容量上,单个redis服务器内存容量有限,就算一台服务器的内存容量为256G,也不能将所有内存用作reids存储内存,一般来说,单台的redis最大使用内存不应该超过20G
为什么使用集群
1.单台服务器难以负载大量的请求
2.单台服务器故障率高,系统崩坏概率大
3.单台服务器内存容量有限。
redis环境配置
- 只配置从库,不用配置主库
使用info replication 查看详细信息
127.0.0.1:7000> info replication --查看当前库的信息
# Replication
role:master -- 角色master
connected_slaves:0 -- 没有从机
master_failover_state:no-failover
master_replid:512cf4b41dba8e04c73609784e8c18511870f8b2
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:7000>
1。复制3个redis.conf文件
[root@localhost redis]# ls
bin redis.conf
[root@localhost redis]# cp redis.conf redis79.conf
[root@localhost redis]# cp redis.conf redis80.conf
[root@localhost redis]# cp redis.conf redis81.conf
[root@localhost redis]# ls
bin redis79.conf redis80.conf redis81.conf redis.conf
2.修改配置文件的 logfile
-
修改redis79.conf 的 prot 7000 -->prot 6379 修改 logfile “” --》 logfile “6379.log” 修改 dbfilename dump.rdb --》 dbfilename dump6379.rdb
-
修改redis80.conf的prot 7000 -->prot 6380 修改pidfile /var/run/redis_6379.pid—》/var/run/redis_6380.pid 修改 logfile “” --》 logfile “6380.log” 修改 dbfilename dump.rdb --》 dbfilename dump6380.rdb
-
修改redis81.conf的prot 7000 -->prot 6381修改pidfile /var/run/redis_6379.pid—》/var/run/redis_6381pid 修改 logfile “” --》 logfile “6381.log” 修改 dbfilename dump.rdb --》 dbfilename dump6381.rdb
port:进程占用的端口号
pid(port ID):记录了进程的 ID,文件带有锁。可以防止程序的多次启动。
logfile:明确日志文件的位置
dbfilename:dumpxxx.file #持久化文件位置
3.三个窗口分别以redisXX.conf 文件启动redis服务
4.一主二从
三个端口都开启redis-cli -p 端口号,
- 默认情况下,每台redis服务器都是主节点,: 我们一般情况下只用配置从机即可
相当于 从机认老大
使用 slavof 主机地址, 端口号
使用 info replication 查看详细信息
主机
[root@localhost bin]# ./redis-cli -p 6379
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:1 -- 表示有一个从机
slave0:ip=127.0.0.1,port=6380,state=online,offset=98,lag=1 从机信息
master_failover_state:no-failover
master_replid:e96ece6a348804ff0647f7751c980c78a2eba8f5
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:98
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:98
127.0.0.1:6379>
真实的主从配置应该在配置文件中配置,这样的话是永久的,使用命令是暂时的
修改redis.conf 配置文件 输入 /replication 查找相关的关键字
-
replicaof 表述要搭建从机的主机地址
- 《masterport》 表示要搭建从机的端口号
-
masterauth 《master-password》如果主机有密码,配置即可
-
配置完毕后,使用该文件启动的时候,就会自动配置从机
细节了解:
主机可以写,从机不能写只能读,主机宕机,从机依旧连接到主机的,但是没有写操作, 这个时候 如果主机回来了 从机依旧可以直接获取到主机写的信息
-
如果是使用命令行 来配置的主从机,如果重启 从机会变回主机。如果重新再次配置变为从机 立马就会从主机中获取值!
-
- 复制原理
从机(Slave)启动成功连接到 主机(master) 后会发送一个同步 (sync)命令
主机接收到命令,启动后台的存盘进程, 同时收集所有接收到的用于修改数据集命令,在后台进程执行完毕之后,主机将传送整个数据文件到从机,并完成一次完全同步
全量复制: 而从机服务在接收到数据库文件数据后,将其存盘并加载到内存中
增量复制: 主机和继续将新的所有收集到的修改命令依次传给从机,完成同步
但是只要是重新连接主机吗,一次完全同步(全量复制) 将会执行 我们的数据一定可以在从机中看到
层层链路式主从
上一个主结点连接下下一个从节点
80使用slaveof 指向79 81使用slaveof 指向80 此时的79 使用info replication 只显示有80 一个从节点,80 使用info replication 显示只有81一个从节点,
这时候也可以完成我们的主从复制
如果主机断开了连接,我们可以使用slaveof no one 让自己成为主机,其他的节点就可以手动连接到最新的这个主节点(手动),如果这个时候 老大恢复了,老大就得重新配置从机了,
哨兵模式
(当主机宕机后,从机自动顶替主句 主从模式)
- 主从切换技术的方法是:当主服务器宕机后,需要手动把一台从服务器切换为主服务器,这就需要人工干预,费事费力,还会造成一段时间内服务不可用,这不是一种推荐的方式, 更多时候,我们优先考虑吧哨兵模式,redis从2.8开始正式提供了Sentinel(哨兵)架构来解决这个问题。
- 主从切换自动版 能够后台监控主机是否异常,如果故障了根据投票数自动将从库转换为主库
哨兵模式是一种特殊的模式, 首先redis提供了哨兵的命令,哨兵是一个独立的进程,作为进程,它会独立运行,其原理是哨兵通过发送命令,等待redis服务器响应,从而监控运行的多个reids实例
这里的哨兵有两个作用
●通过发送命令,让Redis服务器返回监控其运行状态,包括主服务器和从服务器。
●当哨兵监测到master宕机,会自动将slave切换成master ,然后通过发布订阅模式通知其他的从服务器,修改配置文件,让它们切换主机。
然而一个哨兵进程对Redis服务器进行监控,可能会出现问题,为此,我们可以使用多个哨兵进行监控。各个哨兵之间还会进行监控,这样就形成了多哨兵模式。
假设主服务器宕机,哨兵1先检测到这个结果,系统并不会马上进行failover过程,仅仅是哨兵1主观的认为主服务器不可用,这个现象成为主观下线。当后面的哨兵也检测到主服务器不可用,并且数量达到一定值时,那么哨兵之间就会进行一次投票,投票的结果由一个哨兵发起,进行failover[故障转移]操作。切换成功后,就会通过发布订阅模式,让各个哨兵把自己监控的从服务器实现切换主机,这个过程称为客观下线
我们目前的状态是一主二从
配置哨兵
1.配置哨兵配置文件sentinel.conf文件里面输入
#sentinel monito 被监控的名称 host port 1
sentinel monitor myredis 127.0.0.1 6379 1
1代表至少需要几个sentinel进程同意可以开启faillover
启动哨兵模式
如果主机宕机,这个时候就会从从机中随机选择一个服务器(这里面有一个算法)
如果主机此时回来了,只能归并到新的主机下,当作从机,这就是哨兵模式的规则
优点:
1.哨兵模式,基于主从复制模式,所有的主从配置优点它都有
2.主从可以切换,故障可以转移,系统的可用性就会更好
3.哨兵模式就是主从模式的升级,手动到自动 更加健壮
缺点:
1.redis 不好在线扩容,集群容量一旦达到上限,在线扩容就十分麻烦
2.实现哨兵模式的配置其实是很麻烦的 ,里面有很多选择
哨兵模式的全部配置
# Example sentinel.conf
# 哨兵sentinel实例运行的端口 默认26379
port 26379
# 哨兵sentinel的工作目录
dir /tmp
# 哨兵sentinel监控的redis主节点的 ip port
# master-name 可以自己命名的主节点名字 只能由字母A-z、数字0-9 、这三个字符".-_"组成。
# quorum 当这些quorum个数sentinel哨兵认为master主节点失联 那么这时 客观上认为主节点失联了
# sentinel monitor <master-name> <ip> <redis-port> <quorum>
sentinel monitor mymaster 127.0.0.1 6379 1
# 当在Redis实例中开启了requirepass foobared 授权密码 这样所有连接Redis实例的客户端都要提供密码
# 设置哨兵sentinel 连接主从的密码 注意必须为主从设置一样的验证密码
# sentinel auth-pass <master-name> <password>
sentinel auth-pass mymaster MySUPER--secret-0123passw0rd
# 指定多少毫秒之后 主节点没有应答哨兵sentinel 此时 哨兵主观上认为主节点下线 默认30秒
# sentinel down-after-milliseconds <master-name> <milliseconds>
sentinel down-after-milliseconds mymaster 30000
# 这个配置项指定了在发生failover主备切换时最多可以有多少个slave同时对新的master进行 同步,
这个数字越小,完成failover所需的时间就越长,
但是如果这个数字越大,就意味着越 多的slave因为replication而不可用。
可以通过将这个值设为 1 来保证每次只有一个slave 处于不能处理命令请求的状态。
# sentinel parallel-syncs <master-name> <numslaves>
sentinel parallel-syncs mymaster 1
# 故障转移的超时时间 failover-timeout 可以用在以下这些方面:
#1. 同一个sentinel对同一个master两次failover之间的间隔时间。
#2. 当一个slave从一个错误的master那里同步数据开始计算时间。直到slave被纠正为向正确的master那里同步数据时。
#3.当想要取消一个正在进行的failover所需要的时间。
#4.当进行failover时,配置所有slaves指向新的master所需的最大时间。不过,即使过了这个超时,slaves依然会被正确配置为指向master,但是就不按parallel-syncs所配置的规则来了
# 默认三分钟
# sentinel failover-timeout <master-name> <milliseconds>
sentinel failover-timeout mymaster 180000
# SCRIPTS EXECUTION
#配置当某一事件发生时所需要执行的脚本,可以通过脚本来通知管理员,例如当系统运行不正常时发邮件通知相关人员。
#对于脚本的运行结果有以下规则:
#若脚本执行后返回1,那么该脚本稍后将会被再次执行,重复次数目前默认为10
#若脚本执行后返回2,或者比2更高的一个返回值,脚本将不会重复执行。
#如果脚本在执行过程中由于收到系统中断信号被终止了,则同返回值为1时的行为相同。
#一个脚本的最大执行时间为60s,如果超过这个时间,脚本将会被一个SIGKILL信号终止,之后重新执行。
#通知型脚本:当sentinel有任何警告级别的事件发生时(比如说redis实例的主观失效和客观失效等等),将会去调用这个脚本,
#这时这个脚本应该通过邮件,SMS等方式去通知系统管理员关于系统不正常运行的信息。调用该脚本时,将传给脚本两个参数,
#一个是事件的类型,
#一个是事件的描述。
#如果sentinel.conf配置文件中配置了这个脚本路径,那么必须保证这个脚本存在于这个路径,并且是可执行的,否则sentinel无法正常启动成功。
#通知脚本
# sentinel notification-script <master-name> <script-path>
sentinel notification-script mymaster /var/redis/notify.sh
# 客户端重新配置主节点参数脚本
# 当一个master由于failover而发生改变时,这个脚本将会被调用,通知相关的客户端关于master地址已经发生改变的信息。
# 以下参数将会在调用脚本时传给脚本:
# <master-name> <role> <state> <from-ip> <from-port> <to-ip> <to-port>
# 目前<state>总是“failover”,
# <role>是“leader”或者“observer”中的一个。
# 参数 from-ip, from-port, to-ip, to-port是用来和旧的master和新的master(即旧的slave)通信的
# 这个脚本应该是通用的,能被多次调用,不是针对性的。
# sentinel client-reconfig-script <master-name> <script-path>
sentinel client-reconfig-script mymaster /var/redis/reconfig.sh
缓存穿透(查不到)
缓存穿透的概念很简单,用户想要查询一个数据,发现redis内存数据库没有,也就是缓存没有命中,于是向持久层数据库查询。发现也没有,于是本次查询失败。当用户很多的时候,缓存都没有命中(秒杀! ) , 于是都去请求了持久层数据库。这会给持久层数据库造成很大的压力,这时候就相当于出现了缓存穿透。
解决方案
布隆过滤器
布隆过滤器是一种数据结构,对所有可能查询的参数以hash形式存储,在控制层先进行校验,不符合则丢弃,从而避免了对底层存储系统的查询压力;
缓存空对象
当存储层不命中后,即使返回的空对象也将其缓存起来,同时会设置-个过期时间,之后再访问这个数据将会从缓存中获取,保护了后端数据源;
但是这种方法会存在两个问题:
1、如果空值能够被缓存起来,这就意味着缓存需要更多的空间存储更多的键,因为这当中可能会有很多的空值的键;
2、即使对空值设置了过期时间,还是会存在缓存层和存储层的数据会有- -段时间窗口的不一致,这对于需要保持一致性的业务会有影响。
缓存击穿(量太大,缓存过期)
,概述
这里需要注意和缓存击穿的区别,缓存击穿,是指一-个key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问, 当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个屏障 上凿开了-一个洞。
当某个key在过期的瞬间,有大量的请求并发访问,这类数据一般是热点数据,由于缓存过期,会同时访问数据库来查询最新数据,并且回写缓存,会导使数据库瞬间压力过大。
解决方案
设置热点数据永不过期
从缓存层面来看,没有设置过期时间,所以不会出现热点key过期后产生的问题。
加互斥锁
分布式锁:使用分布式锁,保证对于每个key同时只有一个线程去查询后端服务 ,其他线程没有获得分布式锁的权限,因此只需要等待即可。这种方式将高并发的压力转移到了分布式锁,因此对分布式锁的考验很大。
缓存雪崩
概念
缓存雪崩,是指在某一一个时间段I缓存集中过期失效。Redis 宕机!
产生雪崩的原因之一, 比如在写本文的时候,马上就要到双十二零点,很快就会迎来一波抢购 ,这波商品时间比较集中的放入了缓存,假设缓存-一个小时。 那么到了凌晨一点钟的时候 ,这批商品的缓存就都过期了。而对这批商品的访问查询,都落到了数据库上,对于数据库而言,就会产生周期性的压力波峰。于是所有的请求都会达到存储层,存储层的调用量会暴增,造成存储层也会挂掉的情况。
解决方案
redis高可用
这个思想的含义是,既然redis有可能挂掉,那我多增设几台redis ,这样一台挂掉之后其他的还可以继续 工作,其实就是搭建的集群。
限流降级
这个解决方案的思想是,在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许-一个线程查询数据和写缓存,其他线程等待。
数据预热
缓存起来,这就意味着缓存需要更多的空间存储更多的键,因为这当中可能会有很多的空值的键;
2、即使对空值设置了过期时间,还是会存在缓存层和存储层的数据会有- -段时间窗口的不一致,这对于需要保持一致性的业务会有影响。
缓存击穿(量太大,缓存过期)
,概述
这里需要注意和缓存击穿的区别,缓存击穿,是指一-个key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问, 当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个屏障 上凿开了-一个洞。
当某个key在过期的瞬间,有大量的请求并发访问,这类数据一般是热点数据,由于缓存过期,会同时访问数据库来查询最新数据,并且回写缓存,会导使数据库瞬间压力过大。
解决方案
设置热点数据永不过期
从缓存层面来看,没有设置过期时间,所以不会出现热点key过期后产生的问题。
加互斥锁
分布式锁:使用分布式锁,保证对于每个key同时只有一个线程去查询后端服务 ,其他线程没有获得分布式锁的权限,因此只需要等待即可。这种方式将高并发的压力转移到了分布式锁,因此对分布式锁的考验很大。
缓存雪崩
概念
缓存雪崩,是指在某一一个时间段I缓存集中过期失效。Redis 宕机!
产生雪崩的原因之一, 比如在写本文的时候,马上就要到双十二零点,很快就会迎来一波抢购 ,这波商品时间比较集中的放入了缓存,假设缓存-一个小时。 那么到了凌晨一点钟的时候 ,这批商品的缓存就都过期了。而对这批商品的访问查询,都落到了数据库上,对于数据库而言,就会产生周期性的压力波峰。于是所有的请求都会达到存储层,存储层的调用量会暴增,造成存储层也会挂掉的情况。
解决方案
redis高可用
这个思想的含义是,既然redis有可能挂掉,那我多增设几台redis ,这样一台挂掉之后其他的还可以继续 工作,其实就是搭建的集群。
限流降级
这个解决方案的思想是,在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许-一个线程查询数据和写缓存,其他线程等待。
数据预热
数据加热的含义就是在正式部署之前,我先把可能的数据先预先访问- -遍,这样部分可能大量访问的数据就会加载到缓存中。在即将发生大并发访问前手动触发加载缓存不同的key ,设置不同的过期时间,让缓存失效的时间点尽量均匀。