redis(初级)跳跃表,redis安装,缓存,分布式锁,持久化,数据淘汰,事务,多机部署

安装Redis

yum 安装 redis

yum -y install redis

启动 redis

redis-server /etc/redis.conf &

操作 redis

redis-cli

设置远程连接

  1. 将 redis 配置文件下载到本地:redis 配置文件是 linux 下的 /etc/redis.conf ;
    在这里插入图片描述
    点击取消下载
    在这里插入图片描述
    此时下载完成
    在这里插入图片描述
    在这里插入图片描述

  2. 将 redis.conf 中的 “bind 127.0.0.1”注释掉;

  3. 将 redis.conf 中的“protected-mode yes” 改为“protected-mode no”;

  4. 将修改后的 redis.conf 上传至 liunx 下的 /etc 目录;

  5. 使用命令“redis-cli shutdown”先关闭 redis 服务,再使用“redis-server /etc/redis.conf &”启动 redis 服务。

  6. 开放6379端,云服务在安全策略里打开。
    在这里插入图片描述
    在这里插入图片描述
    https://redis.io/commands/使用文档

使用场景

1.会话存储:保存用户的登录信息,原本的session里存储会话,只支持一次,诺是在分布式下,会使得,用户登录需要将这些分布式服务器都登录才可以,而redis就能很好的解决这个问题。
2.存储普通缓存:列如详情页等数据的缓存信息存储。
3.实现分布式锁:redis 可以非常方便的实现微服务选的分布式锁,redis 天然支持分布式服务。也可以使用zookeeper实现分布式锁。
4.简单的消息队列:redis 自身提供的发布订阅模式,可以用来实现简单的消息队列

redis常用的数据类型

  • String:(字符串):
    常见的使用场景是存储session信息,存储缓存信息如详情页缓存,存储整数信息可使用incr实现整数 + 1和使用decr实现整数 - 1。
  • list:(列表类型):
    常见使用场景式简单的消息队列,存储某项列表数据。
  • Hash:(哈希表):
    常见使用场景是存储session信息存储商品的购物车,购物车非常适合用哈希字典表示,使用人员唯一编号作为字典的key value值,可以存储商品的ID和数量等信息,存储详情页信息。
  • Set:(集合):
    一个无序并唯一的兼职集合,它的常见使用场景是实现关注功能,比如关注我的人,我关注的人使用集合存储可以保证人员不重复。
  • Sorted Set :(有序集合):
    相比于set集合类型多了一个排序属性的 score (分值),它的常见使用场景是可以用来存储排名信息,关注列表功能,这样就可以根据关注实现排序展示了。

有序列表的底层是如何实现的?

当数据比较少时,有序集合是压缩列表(字节数组) ziplist 实现的,反之作为跳跃表 skiplist 实现的。
使用压缩列表要满足两个条件:

  • 有序集合保存的元素个数要小于128个。
  • 有序集合保存的所有元素成员的长度必须小于64个字节。

如果任意一个条件不满足,就会使用跳跃表结构进行存储。

跳跃表

它的本质是由多层链表来进行实现的。

在这里插入图片描述

跳跃表

节点随机层数。意思是每次新增的一层,单独放一个节点,随着基数越大,层数越高,但是,最高层数32层

Redis 以及缓存的作用

缓存是⼀个⾼速数据交换的存储器,使⽤它可以快速的访问和操作数据。

Redis是文档型数据库(非关系型数据库)

缓存优点
相⽐于数据库⽽⾔,缓存的操作性能更⾼,缓存性能⾼的主要原因有以下⼏个:

  1. 缓存⼀般都是 key-value 查询数据的,因为不像数据库⼀样还有查询的条件等因素,所以查询的性能⼀般会⽐数据库⾼;
  2. 缓存的数据是存储在内存中的,⽽数据库的数据是存储在磁盘中的,因为内存的操作性能远远⼤于磁盘,因此缓存的查询效率会⾼很多;
  3. 缓存更容易做分布式部署(当⼀台服务器变成多台相连的服务器集群),⽽数据库⼀般⽐较难实现分布式部署,因此缓存的负载和性能更容易平⾏扩展和增加。

在这里插入图片描述
本地缓存也叫单机缓存,也就是说可以应⽤在单机环境下的缓存。所谓的单机环境是指,将服务部署到⼀台服务器上,本地缓存的特征是只适⽤于当前系统。

分布式缓存是指可以应⽤在分布式系统中的缓存。所谓的分布式系统是指将⼀套服务器部署到多台服务器,并且通过负载分发将⽤户的请求按照⼀定的规则分发到不同服务器,

  • 本地缓存的常⻅使⽤:Spring Cache、MyBatis 的缓存等。
  • 分布式缓存的常⻅使⽤:Redis 和 Memcached。

使用redis

Spring/Spring Boot 操作redis java客户端
Spring Redis lettuce

添加Redis依赖。
在这里插入图片描述
设置Redis远程连接

在配置文件中写入

#设置Redis连接信息
spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.password=
spring.redis.database=1

因为我没有设置密码,所以无需填入。
在这里插入图片描述
通过RedisAPI调用。

@RestController
public class TestController {
    private static final  String _REDIS_KEY="myapplication_test";
    
    @Resource
    private RedisTemplate redisTemplate;
    
    @RequestMapping("/setval")
    public void setVal(String val){
        //得到操作redis的String类型
        redisTemplate.opsForValue()
                        .set(_REDIS_KEY,val,1000, TimeUnit.SECONDS);
        
    }
    
    @RequestMapping("/getval")
    public String getValue(){
        return (String) redisTemplate.opsForValue()
                .get(_REDIS_KEY);
    }
}

session升级到Redis中

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
            <version>2.7.14</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework.session/spring-session-data-redis -->
        <dependency>
            <groupId>org.springframework.session</groupId>
            <artifactId>spring-session-data-redis</artifactId>
            <version>2.7.0</version>
        </dependency>
spring.session.store-type=redis

#过期时间
server.servlet.session.timeout=1800

spring.session.redis.flush-mode=on_save
#用户登录的session存在这个目录下
spring.session.redis.namespace=spring:session

在这里插入图片描述

Redis如何实现分布式锁

在分布式存储的服务器中一个应用在一台服务器上进行实现,运行,并且加锁的话,那么相应的对于其他服务器而言,他们也有相同的应用也需要进行加锁,而此时我们平常的加锁是对于一个服务器来说进行加锁,所以此时的需求就需要我们进行对同时多个服务器进行加锁。

分布式加锁是一个-----》逻辑概念

Redis 是单线程的模型。它的速度为什么会比较快,并且没有用到多线程度?其原因就在于:

  • 它的内部结构是通过 key value 对进行存储数据的。可以通过某种算法快速定位到相应的值。就是他在查找的过程中他的时间复杂度为O(1)。这种设计有效的避免了多线程的锁竞争和锁开销。所以在这种模式下,可以处理大量的并发请求。
  • Redis 是一种基于内存的数据存储系统,所有的数据都存储在内存中。内存的访问速度明显高于磁盘存储系统的速度。
  • Redis 提供了高效的数据结构。这些数据结构都进行了优化。
  • Redis 使用了 非 I/O 模型 就意味着,当进行磁盘读写或者网络通信时,Redis 不会等待数据的返回,而是继续处理其他请求。

如何实现分布式加锁操作 Redis 给出了他的解决方案。因为Redis 本身可以实现分布式,所以通过 setnx(set it not exists)命令实现。del 释放锁

setnx lock true;创建锁成功
del lock;释放锁

分布式加锁,产生死锁:

获取锁的线程下线了或者是崩溃,线程不会继续执行看,那么就会发生死锁。
如何解决:添加超时时间。

set (锁名字)true ex (设置的时间) nx
定期删除,不是超时删除。

锁误删
线程的锁在删除的过程中,删除了其他的线程。

如何解决误删,在锁中添加标识符。判断锁的归属。

非原子性
此时又出现一个问题,因为出现了判断结果,并修改,有读和写操作,此时是非原子性操作。

为了解决这种状况。有两种方案:
1.使用lua脚本(Redis 可使用可保证原子性的脚本)
2.Redisson框架

数据不丢失(持久化)

所谓的持久化就是将数据从内存保存到磁盘的过程,它的⽬的就是为了防⽌数据丢失。因为服务器重启之后数据会丢失,但是如果存储到磁盘中,此时就永久保存了下来。Memcached与Redis最本质的区别就是这个。

三种方式:

  • 快照⽅式RDB, Redis DataBase)将某⼀个时刻的内存数据,以⼆进制的⽅式写⼊磁盘;
  • ⽂件追加⽅式(AOF, Append Only File),记录所有的操作,非查询命令,并以⽂本的形式追加到⽂件中;
  • 混合持久化⽅式,混合持久化是结合了 RDB 和 AOF 的优点,在写⼊的时候,先把当前的数据以 RDB 的形式写⼊⽂件的开头,再将后续的操作命令以 AOF 的格式存⼊⽂件,这样既能保证 Redis 重启时的速度,⼜能减低数据丢失的⻛险。

RDB

RDB工作原理:

RDB持久化是通过快照的方式,将当前release内存中的数据二进制格式保存到硬盘上的一个文件中,快照文件是一个经过二压缩的二进制文件,代表了某个时间点上的数据库状态。

RDB 优点:

  • 效率高:RDB持久化是将整个数据集与二进制格式保存到磁盘上,因此在数据恢复时速度较快。
  • 文件较小:相比于AOF,RDB生成的快照文件通常较小,占用较小的磁盘空间

缺点:

  • 数据丢失:由于 RDB 是定期保存快照,如果reduce在快照之间发生故障,可能导致部分数据丢失。

AOF

AOF的工作原理:
AOF持久化是将 Redis 的写操作与日志的形式,追加到一个文件中,类似于数据库中的日志,当Redis需要重启时,可以通过回放 AOF 文件中的写操作来恢复数据。

AOF优点:

  • 数据完整性较好:AOF 持久化是通过追加,写操作来记录数据变化的,因此通常比 RDB 更可靠,数据丢失的可能性比较低。
  • 可读性高 :AOF文件是一个文本文件,可以方便的查看和分析,其中的内容也更容易进行手动修复。
  • 多种持久化策略,为Redis提供了不同的AOF持久化策略,可以根据需要,选择不同级别的数据安全性和性能。

缺点:

  • 文件比较大:由于追加写,AOF文件会随着时间比较长,可能会变得很大,而较大的AOF文件可能影响重启和恢复的速度。
  • 对磁盘的写入频繁:AOF持久化需要平凡写入日志文件,可能会对磁盘造成一定的写入压力

AOF持久化策略有3中:

  • always:每天Redis操作命令都会写入磁盘,最多丢失一条数据。
  • everysec:每秒钟写一次磁盘,最多丢失一秒的数据
  • no:不设置写入磁盘的规则,根据当前操作系统来决定何时写入磁盘,Linux默认30秒写一次。

这三种配置在Redis的文件Redis.conf中,通过 “appendfsync everysec”来设置。

redis的键值过期后就会删除吗?

不会的。redis并不会在过期后,立即删除过期数据,而是等待多个过期数据,然后一起删除。降低开销。

数据淘汰

如何删除过期数据:

  • 定时删除,在设置 键值 过期时,创建一个时间事件,当过期时间达到时,由事件处理器自动执行删除操作。
  • 惰性删除,不主动删除过期键,每次从数据库获取键值时,判断是否过期,如果过期则删除键值,并返回null。
  • 定期删除,每隔一段时间检查一次数据库,随机删除一些过期键。

定期删除的流程:

  1. 从过期字典中随机取出20个键
  2. 删除这20个键中过期的键
  3. 如果过期key的比例超过25%,则重复步骤1.

redis内存会用完吗?

会的。也就是当Redis的运行内训,超过Redis设置的对大内存后,将会采取内存淘汰机制来删除符合条件的键值对,一次来保证Redis的正常运行。

那么内存淘汰机制有哪些:

  • noeviction:不淘汰任何数据。
  • allkeys-lru:淘汰最久未使用的键值
  • allkeys-random:淘汰时间最久的。


其实主要四种。一种是不淘汰,只报错,一种是设置淘汰时间的。一种随机淘汰,一种淘汰时间最长的。

LRU 和 LFU 的区别

LRU(最近最少使用)和 LFU(最不常用使用)都是常见的缓存淘汰策略,他们在淘汰缓存中的键有不同的侧重点。

  • LRU(最近最少使用)(基于时间的概念):淘汰时会优先淘汰最久未被访问的键
  • LFU(最不常用使用)(基于访问次数的概念):会优先选择访问字数最少的键
  1. LRU基于时间,LFU基于访问频率
  2. LRU策略假设最近被访问的键可能再次访问,LFU假设访问次数最少的键是最不常使用的。
  3. LRU维护一个访问顺序表,LFU维护一个计数器
  4. LRU只关注的访问顺序,而LFU关注键的访问频率

过期淘汰策略和内存淘汰策略有什么区别

  • 内存淘汰机制:解决Redis运行内存过大的问题(节约内存空间)
  • 过期删除策略:主要是为了删除过期数据

Redis事务

Redis和Mysql事务最大的区别是Redis事务本质是一组命令加入到一次性执行,并没有提供向Mysql那样的事务隔离性。Redis没有隔离性。

Redis中,单条命令是原子性执行的,但事务不保证原子性,且没有回滚。事务中任意命令执行失败,其余的命令仍会被执行。

在事务执行过程,会按照顺序串行化执行队列中的命令,其他客户端提交的命令请求不会插入到事务执行命令序列中。

redis事务就是一次性、顺序性、排他性的执行一个队列中的一系列命令

Redis事务相关命令:
开始事务
命令入队
执行事务

  • watch key1 key2 … : 监视一或多个key,如果在事务执行之前,被监视的key被其他命令改动,则事务被打断 ( 类似乐观锁 )

  • multi : 标记一个事务块的开始( queued )

  • exec : 执行所有事务块的命令 ( 一旦执行exec后,之前加的监控锁都会被取消掉 )

  • discard : 取消事务,放弃事务块中的所有命令

  • unwatch : 取消watch对所有key的监控

雪崩

缓存雪崩是指在短时间内,有⼤量缓存同时过期,导致⼤量的请求直接查询数据库,从⽽对数据库造成了巨⼤的压⼒,严重情况下可能会导致数据库宕机的情况叫做缓存雪崩。
如何解决:

  1. 加锁排队:可以起到缓冲的作⽤,防⽌⼤量的请求同时操作数据库,但它的缺点是增加了系统的响应时间,降低了系统的吞吐量,牺牲了⼀部分⽤户体验。
  2. 随机化过期时间:为了避免缓存同时过期,可在设置缓存时添加随机时间,这样就可以极⼤的避免⼤量的缓存同时失效。
// 缓存原本的失效时间
int exTime = 10 * 60;
// 随机数⽣成类
Random random = new Random();
// 缓存设置
jedis.setex(cacheKey, exTime+random.nextInt(1000) , value);
  1. 设置⼆级缓存:⼆级缓存指的是除了 Redis 本身的缓存,再设置⼀层缓存,当 Redis 失效之后,先去查询⼆级缓存。
    在这里插入图片描述

缓存穿透

缓存中没有没有数据。每次访问就穿过缓存进入数据库查询

缓存穿透是指查询数据库和缓存都⽆数据,因为数据库查询⽆数据,出于容错考虑,不会将结果保存到缓存中,因此每次请求都会去查询数据库,这种情况就叫做缓存穿透。

缓存击穿

缓存失效(使得程序直接访问数据库,滤过了Redis)

缓存击穿指的是某个热点缓存,在某⼀时刻恰好失效了,然后此时刚好有⼤量的并发请求,此时这些请求将会给数据库造成巨⼤的压⼒,这种情况就叫做缓存击穿。

解决方式:

  • 加锁排队:缓冲操作请求以此来减少服务器的运⾏压⼒
  • 设置永不过期:对于某些热点缓存,我们可以设置永不过期,这样就能保证缓存的稳定性,但需要注意在数据更改之后,要及时更新此热点缓存,不然就会造成查询结果的误差

缓存预热

缓存预热指的是在系统启动的时候,先把查询结果预存到缓存中,以便⽤户后⾯查询时可以直接从缓存中读取,以节约⽤户的等待时间。

缓存预热的实现思路有以下三种:

  1. 把需要缓存的⽅法写在系统初始化的⽅法中,这样系统在启动的时候就会⾃动的加载数据并缓存数据

  2. 把需要缓存的⽅法挂载到某个⻚⾯或后端接⼝上,⼿动触发缓存预热;

  3. 设置定时任务,定时⾃动进⾏缓存预热

Redi多机部署

Redis 主从同步

把主要存储数据的节点叫做主节点 (master),把其他通过复制主节点数据的副本节点叫做从节点 (slave)。

在 Redis 中⼀个主节点可以拥有多个从节点,⼀个从节点也可以是其他服务器的主节点。
在这里插入图片描述
我们可以使⽤ replicaof host port 命令,把⾃⼰设置为⽬标 IP 的从服务器。

replicaof host port

如果主服务设置了密码,需要在从服务器输⼊主服务器的密码,使⽤ config set masterauth 主服务密码

config set masterauth 主服务密码

主从同步的缺点:这种模式本身存在⼀个致命的问题,当主节点奔溃之后,需要⼈⼯将从节点中设置一个主节点才能恢复 Redis 的正常使⽤。

Redis 哨兵模式

假如晚上发⽣了主从服务器宕机的情况,尤其是在主从服务器节点⽐较多的情况下。Redis Sentinel (哨兵模式) 来把⼿动的过程变成⾃动的,让 Redis 拥有⾃动容灾恢复 (failover) 的能⼒。

但是读写能力相对于主从结构,没有改变,还是以一个服务器为主节点交互。
在这里插入图片描述
哨兵的⼯作原理是,

  1. ⾸先每个 Sentinel(哨兵) 会以每秒钟 1 次的频率,向已知的主服务器、从服务器和以及其他 Sentinel (哨兵)实例,发送⼀个 PING 命令。

  2. 如果超越了所定的时间,就认为主服务器下线并做好标记。

  3. 之后正在监视这个主服务器的所有 Sentinel 节点,要以每秒 1 次的频率确认主服务器是否确实确进⼊了主观下线状态

  4. 如果有⾜够数量 (quorum 配置值) 的 Sentinel 在指定的时间范围内同意这⼀判断,那么这个主服务器
    被标记为客观下线。此时所有的 Sentinel 会按照规则协商⾃动选出新的主节点

Redis 集群服务

Redis 集群(Redis Cluster)是 Redis 多机运⾏最完美的终极⽅案。Redis Cluster 是⽆代理模式去中⼼化的运⾏模式。

主从节点还是遵循哨兵模式。

⽔平扩展⼀倍的主节点就相当于请求处理的性能也提⾼了⼀倍,所以 Redis Cluster 的性能是⾮常⾼的。

Redis Cluster 可以拥有⽆数个主从节点,因此 Redis Cluster 拥有更强⼤的平⾏扩展能⼒,也就是说当 Redis Cluster 拥有两个主从节点时,从理论上来讲 Redis 的性能相⽐于单机服务来说性能提升了 2 倍。
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Redis可以用来作为分布式缓存分布式和消息队列的原因有以下几点。 首先,Redis具有高性能的内存数据库特性,在缓存场景下,能够实现快速的读写操作,提高数据的访问速度。通过将常用的数据存储在Redis中,可以避免频繁地查询数据库,减少响应时间,提高系统的吞吐量。 其次,Redis支持数据过期制和LRU(Least Recently Used,最近最少使用)算法等缓存策略,可以根据需求定时清理过期数据或者根据缓存数据的使用频率进行淘汰,保证缓存的有效性和一定的容量。 此外,Redis还提供了常见的数据结构,例如字符串、列、哈希、集合和有序集合等,这些数据结构的操作都是原子性的,可以支持多个客户端同时访问和修改数据,利于实现分布式的功能。通过Redis的SETNX(SET if Not eXists)指令可以实现简单的互斥制,通过设定过期时间和唯一标识可以防止死的发生。 此外,通过Redis的订阅与发布制,可以轻松地实现消息队列的功能。发布者可以发布消息,订阅者可以实时地接收到消息并进行相应处理。同时,Redis还支持发布与订阅模式的消息持久,即使在消息发布者和订阅者之间存在断开连接的情况下,消息也不会丢失。 综上所述,Redis的高性能、灵活的缓存策略、原子性的数据操作和消息持久制,使其成为一个强大的工具,可以用来实现分布式缓存分布式和消息队列的功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值