Redis

什么是Redis???

Redis的全称是 远程字典服务(Remote  dictionary  server ),Redis是一个开源的,使用C语言的编写的,支持网络交互的,可基于内存

也可持久化的key-value数据库(不仅仅是一个数据库

 

 为什么要使用Redis???

1.redis是基于内存的内存的读写速度非常快(纯内存); 数据存在内存中,数据结构用HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1)

2.redis是单线程的,省去了很多上下文切换线程的时间(避免线程切换和竞态消耗)。

3.redis使用IO多路复用技术(IO multiplexing, 解决对多个I/O监听时,一个I/O阻塞影响其他I/O的问题),可以处理并发的连接(非阻塞IO)

 

 

 

1.先安装好Redis(网上有详细教程)

2.启动Redis服务(建议使用后台启动Redis)

 

 

 

 五大基本结构

String(字符串是我们最常用的数据结构)

 

 

 

 

 

 注意使用双引号赋值时可以有空格,但必须在双引号里面,不然会报错

 

 

 

 

 

 

 

 

 

 

Hash(哈希散列)

 

 

 

 

 

 

 

 

 

 

List

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Set(跟List集合类似,但Set集合中的所有元素都是唯一的,不重复)

 

 

 

 

 

 

 

 

 所以使用Set集合可实现共同好友,共同关注等需求。

 

zSet(有序集合)

 顾名思义,Redis zset(有序集合)中的成员是有序排列的,它和 set 集合的相同之处在于,集合中的每一个成员都是字符串类型并且不允许重复;而它们最大区别是,

有序集合是有序的,set 是无序的,这是因为有序集合中每个成员都会关联一个 double(双精度浮点数)类型的 score (分数值),Redis 正是通过 score 实现了对集合成员的排序。

 

zset 是 Redis 常用数据类型之一,它适用于排行榜类型的业务场景,比如 QQ 音乐排行榜、用户贡献榜等。在音乐排行榜单中,我们可以将歌曲的点击次数作为 score 值,把歌曲的名字作为 value 值,通过对 score 排序就可以得出歌曲“热度榜单”

 

 

 

 

 

 

 

 

 

二  大特殊结构

1.Geospatial(地理位置 ):(经纬度查询)

可用于实现附近位置,摇一摇等功能。

 

 

 

 

 

 

 

 

 

 

 

 

2.HyperLogLogs(基数统计)

这个结构可以非常省内存的去统计各种计数,比如注册 IP 数每日访问 IP 数页面实时UV在线用户数共同好友数等。

 

 

 

 

 

3.Bitmaps(位图)

统计用户信息,活跃不活跃! 登录,未登录! 打卡,不打卡! 两个状态的,都可以使用 Bitmaps! 

 

 

 

 

 

 三 事务

事务的四个基本元素(跟MySQL数据库的事务类似)

1.原子性:要么都成功,要不都失败,在Redis中单条命令保证原子性,但是事务不能保证原子性

2.一致性:事务必须是一个状态到另一个状态,没有中间状态。

3.隔离性:一个事务的执行不能被另一个事务干扰,即事务内部的操作及使用的数据对并发的其他事务不能互相干扰。

但在Redis中,事务没有隔离级别的概念,因为Redis是单线程的。

4.持久性:事务一旦提交,数据库里的数据将保持不变,不受任何其他因素的干扰。

 

1.开启事务

 

 

 

 

 

 

 

 

 

 

说明在Redis数据库中,不保证事务的原子性。

单个 Redis 命令的执行是原子性的,但 Redis 没有在事务上增加任何维持原子性的机制,所以 Redis 事务的执行并不是原子性的。

事务可以理解为一个打包的批量执行脚本,但批量指令并非原子化的操作,中间某条指令的失败不会导致前面已做指令的回滚,也不会造成后续的指令不做

 

 

乐观锁和悲观锁的区别???

悲观锁:认为什么时候都会出现问题,所以一直监视着,没有执行当前步骤完成前,不会让任何线程执行,十分浪费性能!!现在一般很少用。

乐观锁:认为什么时候都不会出新问题,所以只有在更新数据的时候去判断一下,判断在此期间是否有人修改过被监视的这个数据,没有的话正常执行事务,反之之心失败。

 

 

 

 

多个线程操控

 

 

 

 

 

如果多个线程操控事务执行失败,该怎么办???

 

 

 

四 SpringBoot 整合 Redis

1.创建好SpringBoot项目,导入所需要的依赖

2.在application.yaml文件中配置好所需要的信息

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

五 发布订阅功能

Redis 发布订阅(pub/sub)是一个消息通信模式:发送者发送消息,订阅者接受消息

 

 

客户端订阅一个频道

 

 

 

 

服务端向一个频道(所有频道)发送消息

 

 

 

 

 订阅该频道的所有客户端将收到消息

 

 

 

 

 

 

 

 

 

六 持久化技术

Redis 的读写都是在内存中,所以它的性能较⾼,但在内存中的数据会随着服务器的重启⽽丢失,为了保证数据不丢失,我们需要
将内存中的数据存储到磁盘,以便 Redis 重启时能够从磁盘中恢复原有的数据,⽽整个过程就叫做 Redis 持久化

 

 

Redis 持久化也是 Redis 和 Memcached 的主要区别之⼀,因为 Memcached 不具备持久化功能。

RDB(Redis DataBase):也叫快照方式,将某一时刻的内存数据,以二进制的形式写入磁盘

AOF(Append Only File):文件追加方式,记录所有的操作命令,并以文本的形式追加到文件中

RDB和AOF混合方式:Redis 4.0 之后新增的⽅式,混合持久化是结合了 RDB 和 AOF 的优点在写⼊的时候,先把当前的数据以RDB 的形式写⼊⽂件的开头

再将后续的操作命令以 AOF 的格式存⼊⽂件,这样既能保证 Redis 重启时的速度,⼜能简单数据丢失的⻛险。 

 

RDB提供了三种机制:save、bgsave、自动化

 

 执行完成时候如果存在老的RDB文件,就把新的替代掉旧的。我们的客户端可能都是几万或者是几十万,这种方式显然不可取

 

 

 具体操作是Redis进程执行fork操作创建子进程,RDB持久化过程由子进程负责,完成后自动结束。阻塞只发生在fork阶段,一般时间很短基本上 Redis 内部所有的RDB操作都是采用 bgsave 命令

 

3、自动触发

自动触发是由我们的配置文件来完成的。在redis.conf配置文件中,里面有如下配置,我们可以去设置:

 

 

 

AOF文件实现原理

 

 

AOF也提供了三种机制

 

 

AOF和RDB的优缺点???

RDB是Redis默认的持久化方式

 

 

AOF

 

 

 

如何选择AOF和RDB

 

 

 

 

 

 

主从复制+哨兵模式

主从复制:是指将一台主机上的数据复制到另一台主机上,前者称为主机(master),后者称为从机(slave)。

 

 

 在这个过程中,只有 master 主机可执行写命令,其他 salve 从机只能只能执行读命令,这种读写分离的模式可以大大减轻 Redis 主机的数据读取压力,

从而提高了Redis 的效率,并同时提供了多个数据备份。主从模式是搭建 Redis Cluster 集群最简单的一种方式。

 

哨兵(Sentinel)模式:当一台服务器出现故障时,会有一台服务器成为新的主机,这就是哨兵模式。

 

 

 

第一:哨兵节点会以每秒一次的频率对每个 Redis 节点发送PING命令,并通过 Redis 节点的回复来判断其运行状态

第二:当哨兵监测到主服务器发生故障时,会自动在从节点中选择一台将机器,并其提升为主服务器

然后使用 PubSub 发布订阅模式通知其他的从节点,修改配置文件,跟随新的主服务器

 

 

 

 

 

Redis分布式锁

分布式锁并非是 Redis 独有,比如 MySQL 关系型数据库,以及 Zookeeper 分布式服务应用,它们都实现分布式锁,只不过 Redis 是基于缓存实现的。
Redis 分布式锁有很对应用场景,举个简单的例子,比如春运时,您需要在 12306 上抢购回家火车票,但 Redis 数据库中只剩一张票了,

此时有多个用户来预订购买,那么这张票会被谁抢走呢?Redis 服务器又是如何处理这种情景的呢?在这个过程中就需要使用分布式锁。

Redis 分布式锁主要有以下特点:

第一:互斥性是分布式锁的重要特点,在任意时刻,只有一个线程能够持有锁

第二:锁的超时时间,一个线程在持锁期间挂掉了而没主动释放锁,此时通过超时时间来保证该线程在超时后可以释放锁,这样其他线程才可以继续获取锁;

第三:加锁和解锁必须是由同一个线程来设置

第四:Redis 是缓存型数据库,拥有很高的性能,因此加锁和释放锁开销较小,并且能够很轻易地实现分布式锁。

注意:一个线程代表一个客户端

 

 

 

 

 缓存穿透,缓存击穿和缓存雪崩

缓存穿透是指当用户查询某个数据时,Redis 中不存在该数据,也就是缓存没有命中,此时查询请求就会转向持久层数据库 MySQL,结果发现 MySQL 中也不存在该数据

MySQL 只能返回一个空对象代表此次查询失败。如果这种类请求非常多,或者用户利用这种请求进行恶意攻击,就会给 MySQL 数据库造成很大压力,甚至于崩溃,这种现象就叫缓存穿透。

 

解决方案:

1.缓存空对象。当 MySQL 返回空对象时, Redis 将该对象缓存起来,同时为其设置一个过期时间。当用户再次发起相同请求时,就会从缓存中拿到一个空对象

用户的请求被阻断在了缓存层,从而保护了后端数据库,但是这种做法也存在一些问题,虽然请求进不了 MSQL,但是这种策略会占用 Redis 的缓存空间

2.使用布隆过滤器。利用一种概率型数据结构,快速的判断某个key是否存在。如果不存在及直接返return,存在时才会去查询缓存和数据库。

 首先将用户可能会访问的热点数据存储在布隆过滤器中(也称缓存预热),当有一个用户请求到来时会先经过布隆过滤器,如果请求的数据,布隆过滤器中不存在,

那么该请求将直接被拒绝,否则将继续执行查询。相较于第一种方法,用布隆过滤器方法更为高效、实用。

 

 

 

 缓存击穿是指用户查询的数据缓存中不存在,但是后端数据库却存在,这种现象出现原因是一般是由缓存中 key 过期导致的。比如一个热点数据 key

它无时无刻都在接受大量的并发访问,如果某一时刻这个 key 突然失效了,就致使大量的并发请求进入后端数据库,导致其压力瞬间增大。这种现象被称为缓存击穿。

有两种解决方案

第一种就是修改过期时间,比如设置热点时间永不过期

第二种就是使用分布式锁,重新设计缓存的使用方式

 

上锁:当我们通过 key 去查询数据时,首先查询缓存,如果没有,就通过分布式锁进行加锁,第一个获取锁的进程进入后端数据库查询,并将查询结果缓到Redis 中。

解锁:当其他进程发现锁被某个进程占用时,就进入等待状态,直至解锁后,其余进程再依次访问被缓存的 key。

 

缓存雪崩是指缓存中大批量的 key 同时过期,而此时数据访问量又非常大,从而导致后端数据库压力突然暴增,甚至会挂掉,这种现象被称为缓存雪崩。

它和缓存击穿不同,缓存击穿是在并发量特别大时,某一个热点 key 突然过期,而缓存雪崩则是大量的 key 同时过期,因此它们根本不是一个量级。

 

 解决方案:

缓存雪崩和缓存击穿有相似之处,所以也可以(第一种)采用热点数据永不过期的方法,来减少大批量的 key 同时过期。

再者就是为(第二种) key 设置随机过期时间避免 key 集中过期

 

posted @ 2022-06-28 18:03  luoshen-luo  阅读(78)  评论(0编辑  收藏  举报