你好offer之---Redis


在这里插入图片描述
在这里插入图片描述

Redis

Redis是现在最受欢迎的NoSQL数据库之一。

  • 基于内存运行,性能高效
  • 支持分布式,理论上可以无限扩展
  • 支持持久化和集群以及事务
  • key-value存储系统

Redis的用途

1、内存存储、持久化,内存中是断电即失、所以说持久化很重要(rdb、aof)
2、效率高,可以用于高速缓存
3、发布订阅系统
4、地图信息分析
5、计时器、计数器(浏览量!)

Redis的基本知识以及操作

Redis16个数据库,默认是第0个。
Redis的端口是6379
切换数据库:select 2
显示数据库大小:  DBSIZE
清空数据库: flush/flushall

查看所有的key: keys *
设置过期时间: expire name 10
查看当前的key的剩余时间:ttl name
判断一个key是否存在: exist name
设置过期时间: persist(坚持)
移除当前的key: move 
查看当前key的类型: type name
自动增加1:incr no

打印: echo
返回值的类型:type addr

如果存在则返回0,不存在则可以存入:setnx
测试连接是否连通:ping
退出连接:quit
返回当前数据库中key的数目:dbsize

为什么单线程的Redis能那么快

  • CPU不是redis的性能瓶颈,内存大小和网络带宽才有可能是redis的瓶颈
  • Redis 采用多路复用策略,省去了上下文切换的时间
  • redis是基于内存的,内存的读写速度非常快
  • 高效的数据结构string,list,set,zset,hash

Redis的五大数据类型

当最后一个元素移除时,数据结构都会被删除
Redis所有的数据结构都可以设置过期时间,时间到了,Redis会自动删除相应的对象
在这里插入图片描述
在这里插入图片描述

String

最简单的类型一个Key对应一个Value

Redis的字符串是动态字符串,内部实现类似于Java中的ArrayList采用预分配冗余空间的方式来减少内存的频繁分配。当字符串长度小于1M时,扩容都是加倍现有空间,当超过1M时扩容只会多扩1M。
在这里插入图片描述

hash

添加用户:zadd salary 2500 xiaohong
显示全部的用户 从小到大:ZRANGEBYSCORE salary -inf +inf
从大到进行排序:ZREVRANGE salary 0 -1

是一个String类型的field和value的映射表,他的添加和删除都是O(1)。相当于Java的HashMap,同样是数组和链表的二维结构。
在这里插入图片描述
为了不阻塞服务采用了渐进式的rehash策略

在这里插入图片描述

list

左侧插入:lpush list 1
移除list的第一个元素:Lpop list 
右侧插入:Rpush list 2
移除list的最后一个元素:Rpop list 
获取list的值: LRANGE list 0 -1
通过区间获取具体的值:LRANGE list 0 1
通过下标获得 list 中的某一个值:lindex list 1
返回列表的长度:Llen list 

主要用于消息排队。
是一个链表结构,相当于Java语言的LinkedList。就是一个每个子元素都是String的双向链表,可以同时作为队列和栈两种数据结构。
并不是一个简单的LinkedList而是一种quicklist的快速列表。qulicklist是ziplist和linked的混合体,他将linkedlist分解成多段,每一段用ziplist来紧凑存储,多个ziplist之间使用双向指针串联起来。

在这里插入图片描述
为了进一步节约空间Redis还会对ziplist进行压缩存储使用LZF算法压缩,可以选择压缩深度。
qulicklist默认压缩深度是0,为了支持快速的push/pop操作quicklist的首尾两个ziplist不进行压缩,此时深度为1。
如果首尾的两个不进行压缩,则深度为2。

set

set集合中添加:sadd myset "hello"
查看指定set的所有值:Smembers myset
判断某一个值是不是在set集合中:SISMEMBER myset hello
获取set集合中的内容元素个数:scard myset 
交集:SINTER key1 key2
并集:SUNION key1 key2 

set是hashSet实现的,具有自动去重的功能,还可以进行取交集(SINTER)和并集(SUNION)(实现共同好友和可能认识的人)

zset

是一个有顺序的Set,每个元素都会关联一个double类型的score,sorted set的实
现是skip list和hash table的混合体。
内部是一种跳跃表
在这里插入图片描述

Redis提供了三个高级数据结构

geospatital(地理空间)

推算地理位置、计算两地距离、找附近的人
在这里插入图片描述

# getadd 添加地理位置 
# 规则:两级无法直接添加,我们一般会下载城市数据,直接通过java程序一次性导入! 
# 有效的经度从-180度到180度。
# 有效的纬度从-85.05112878度到85.05112878度。 
# 当坐标位置超出上述指定范围时,该命令将会返回一个错误。 


# 参数 key 值() 
127.0.0.1:6379> geoadd china:city 116.40 39.90 beijing 
(integer) 1 
127.0.0.1:6379> geoadd china:city 121.47 31.23 shanghai 
(integer) 1 
127.0.0.1:6379> geoadd china:city 106.50 29.53 chongqi 114.05 22.52 shengzhen (integer) 2 
127.0.0.1:6379> geoadd china:city 120.16 30.24 hangzhou 108.96 34.26 xian 
(integer) 2

获得当前定位:一定是一个坐标值

127.0.0.1:6379> GEOPOS china:city beijing # 获取指定的城市的经度和纬度! 
1) 1) "116.39999896287918091" 
   2) "39.90000009167092543" 

127.0.0.1:6379> GEOPOS china:city beijing chongqi 
1) 1) "116.39999896287918091" 
   2) "39.90000009167092543" 
2) 1) "106.49999767541885376" 
    2) "29.52999957900659211"

两人之间的距离

127.0.0.1:6379> GEODIST china:city beijing shanghai km # 查看上海到北京的直线距离 "1067.3788" 

127.0.0.1:6379> GEODIST china:city beijing chongqi km # 查看重庆到北京的直线距离 "1464.0708"

HyperLogLog

HyperLogLog是Redis的高级数据结构,是统计基数的利器。
UV:统计有多少人访问,一个人多次访问算一次
PV:统计有多少点击量
HyperLogLog提供了三个指令,PFADD(增加计数)和PFCOUNT(获取计数)PFMERGE(将多个PFCOUNT数值累加在一起形成一个新的PFCOUNT)

127.0.0.1:6379> PFadd mykey a b c d e f g h i j # 创建第一组元素 mykey 
(integer) 1 
127.0.0.1:6379> PFCOUNT mykey # 统计 mykey 元素的基数数量 
(integer) 10 
127.0.0.1:6379> PFadd mykey2 i j z x c v b n m # 创建第二组元素 mykey2 
(integer) 1 
127.0.0.1:6379> PFCOUNT mykey2 
(integer) 9 
127.0.0.1:6379> PFMERGE mykey3 mykey mykey2 # 合并两组 mykey mykey2 => mykey3 并集 OK
127.0.0.1:6379> PFCOUNT mykey3 # 看并集的数量! 
(integer) 15

位图

应用场景:

  • 用户签到
  • 用户在线状态
  • 统计活跃用户
  • 各种状态值
  • 自定义布隆过滤器
  • 点赞功能

记录打卡:
在这里插入图片描述查看某一天是否有打卡

127.0.0.1:6379> getbit sign 3 
(integer) 1 
127.0.0.1:6379> getbit sign 6 
(integer) 0

统计操作,统计 打卡的天数

127.0.0.1:6379> bitcount sign # 统计这周的打卡记录,就可以看到是否有全勤! 
(integer) 3

位图不是Redis的一种数据结构,它的内容就是普通的字符串。

Redis事务

单个 Redis 命令的执行是原子性的,但 Redis 没有在事务上增加任何维持原子性的机制,所以 Redis 事务的执行并不是原子性的。redis 事务不保证原子性,且没有回滚,中间某条命令执行失败,前面已执行的命令不回滚,后续的指令继续执行。

redis的事务本质是一组命令的集合,一个事务中所有的命令都会被序列化,在事务执行过程中会按照顺序来执行。

Redis事务 没有隔离级别的概念,所有的命令在事务中,并没有被直接执行,只有发起执行后命令才会执行

Redis的事务:

  • 开启事务:multi
  • 命令入队:set key value
  • 执行事务:exec

Redis事务命令

  • watch:(相当于乐观锁)进行监控,一旦一个键被修改或者被删除,后面的命令都会停。(在当多线程即多个用户对数据修改的时候包保证了安全)
  • MULTI:开启一个事务,存放于队列
  • EXEC:执行所有事务块内的命令(事务中任意命令执行失败,前面已执行的命令不回滚,后续的命令继续执行。)

批量操作在发送 EXEC(执行) 命令前被放入队列缓存收到 EXEC 命令后进入事务执行,事务中任意命令执行失败,前面已执行的命令不回滚,后续的命令继续执行。

在这里插入图片描述

Jedis

是 Redis 官方推荐的 java连接开发工具! 使用Java 操作Redis 中间件
在 SpringBoot2.x 之后,原来使用的jedis 被替换为了 lettuce。

需要导入对应的依赖

在这里插入图片描述

所有的api命令,就是我们对应的上面学习的指令,一个都没有变化!

在这里插入图片描述

SpringBoot整合

1、导入依赖
在这里插入图片描述2、配置连接

在这里插入图片描述
3、测试

在这里插入图片描述

RedisTemplete


import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
public class RedisConfig {
 
            
@Bean 
@SuppressWarnings("all") 
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
    // 我们为了自己开发方便,一般直接使用 <String, Object> 
    RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
    template.setConnectionFactory(factory); 
    
    // Json序列化配置 
    Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); 
    ObjectMapper om = new ObjectMapper(); 
    om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); 
    om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); 
    jackson2JsonRedisSerializer.setObjectMapper(om); 
    // String 的序列化 
    StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); 
    
    // key采用String的序列化方式 
    template.setKeySerializer(stringRedisSerializer); 
    // hash的key也采用String的序列化方式 
    template.setHashKeySerializer(stringRedisSerializer); 
    // value序列化方式采用jackson 
    template.setValueSerializer(jackson2JsonRedisSerializer); 
    // hash的value序列化方式采用jackson 
    template.setHashValueSerializer(jackson2JsonRedisSerializer); 
    template.afterPropertiesSet(); return template; } }
}

Redis.conf详解

网络

bind 127.0.0.1 # 绑定的ip 
protected-mode yes # 保护模式 
port 6379 # 端口设置

快照

# 如果900s内,如果至少有一个1 key进行了修改,我们及进行持久化操作 
save 900 1 
# 如果300s内,如果至少10 key进行了修改,我们及进行持久化操作 
save 300 10 
# 如果60s内,如果至少10000 key进行了修改,我们及进行持久化操作 
save 60 10000 
# 我们之后学习持久化,会自己定义这个测试! 
stop-writes-on-bgsave-error yes # 持久化如果出错,是否还需要继续工作! 

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

rdbchecksum yes # 保存rdb文件的时候,进行错误的检查校验! 

dir ./ # rdb 文件保存的目录!

Redis 缓存处理请求的两种情况

  • 缓存命中:Redis 中有相应数据,就直接读取 Redis,性能非常快。
  • 缓存缺失:Redis 中没有保存相应数据,就从后端数据库中读取数据,性能就会变慢。而且,一旦发生缓存缺失,为了让后续请求能从缓存中读取到数据,我们需要把缺失的数据写入 Redis,这个过程叫作缓存更新。缓存更新操作会涉及到保证缓存和数据库之间的数据一致性问题。

在这里插入图片描述

缓存的类型

按照 Redis 缓存是否接受写请求,我们可以把它分成只读缓存和读写缓存。

只读缓存

在这里插入图片描述
只读缓存直接在数据库中更新数据的好处是,所有最新的数据都在数据库中,而数据库是提供数据可靠性保障的,这些数据不会有丢失的风险。

读写缓存

和只读缓存不一样的是,在使用读写缓存时,最新的数据是在 Redis 中,而 Redis 是内存数据库,一旦出现掉电或宕机,内存中的数据就会丢失。

同步直写是指,写请求发给缓存的同时,也会发给后端数据库进行处理,等到缓存和数据库都写完数据,才给客户端返回。

而异步写回策略,则是优先考虑了响应延迟。此时,所有写请求都先在缓存中处理。等到这些增改的数据要被从缓存中淘汰出来时,缓存将它们写回后端数据库。

在这里插入图片描述

Redis核心-管道

Redis默认每次执行请求都会创建和断开一次连接池的操作,如果想执行多条命令的时候会在这件事情上消耗过多的时间,因此我们可以使用Redis的管道来一次性发送多条命令并返回多个结果,节约发送命令和创建连接的时间提升效率。
在这里插入图片描述
Redis管道的本质:
在这里插入图片描述
在这里插入图片描述

Redi的过期策略

  • 定时删除
  • 懒汉删除
  • 定期删除
    定时删除和定期删除为主动删除:Redis会定期主动淘汰一批已过去的key
    惰性删除为被动删除:用到的时候才会去检验key是不是已过期,过期就删除惰性删除为redis服务器内置策略

Redis的持久化

内存快照(RDB)和日志(AOF)

AOF

优点:
1、每一次修改都同步,文件的完整会更加好!
2、每秒同步一次,可能会丢失一秒的数据
3、从不同步,效率最高的!
缺点:
1、相对于数据文件来说,aof远远大于 rdb,修复的速度也比 rdb慢!
2、Aof 运行效率也要比 rdb 慢,所以我们redis默认的配置就是rdb持久化
在这里插入图片描述

AOF执行过程

AOF会先让系统执行命令,只有命令能执行成功,才会被记录到日志中,否则,系统就会直接向客户端报错。所以,Redis 使用写后日志这一方式的一大好处是,可以避免出现记录错误命令的情况。

AOF的三种写回策略
  • Always,同步写回:每个写命令执行完,立马同步地将日志写回磁盘;
  • Everysec,每秒写回:每个写命令执行完,只是先把日志写到 AOF 文件的内存缓冲区,每隔一秒把缓冲区中的内容写入磁盘;
  • No,操作系统控制的写回:每个写命令执行完,只是先把日志写到 AOF 文件的内存缓冲区,由操作系统决定何时将缓冲区内容写回磁盘。
    在这里插入图片描述
    想要获得高性能,就选择 No 策略;如果想要得到高可靠性保证,就选择 Always 策略;如果允许数据有一点丢失,又希望性能别受太大影响的话,那么就选择 Everysec 策略。
重写日志

实际上,重写机制具有“多变一”功能。所谓的“多变一”,也就是说,旧日志文件中的多条命令,在重写后的新日志中变成了一条命令。
在这里插入图片描述

RDB

优点:
1、适合大规模的数据恢复!
2、对数据的完整性要不高!
缺点:
1、需要一定的时间间隔进程操作!如果redis意外宕机了,这个最后一次修改数据就没有的了!
2、fork进程的时候,会占用一定的内容空间

和 AOF 相比,RDB 记录的是某一时刻的数据,并不是操作,所以,在做数据恢复时,我们可以直接把 RDB 文件读入内存,很快地完成恢复。

Redis 提供了两个命令来生成 RDB 文件,分别是 save 和 bgsave。

  • save:在主线程中执行,会导致阻塞;
  • bgsave:创建一个子进程,专门用于写入 RDB 文件,避免了主线程的阻塞,这也是 Redis RDB 文件生成的默认配置。

为了快照而暂停写操作,肯定是不能接受的。所以这个时候,Redis 就会借助操作系统提供的写时复制技术(Copy-On-Write, COW),在执行快照的同时,正常处理写操作。

写时复制机制保证快照期间数据可修改:
在这里插入图片描述
在这里插入图片描述
做了一次全量快照后,后续的快照只对修改的数据进行快照记录,这样可以避免每次全量快照的开销。

在这里插入图片描述

AOF和RDB的混用

在这里插入图片描述

Redis集群的数据同步

Redis的高可靠性:一是数据尽量少丢失,二是服务尽量少中断。AOF 和 RDB 保证了前者,而对于后者,Redis 的做法就是增加副本冗余量,将一份数据同时保存在多个实例上。即使有一个实例出现了故障,需要过一段时间才能恢复,其他实例也可以对外提供服务,不会影响业务使用。

Redis 提供了主从库模式,以保证数据副本的一致,主从库之间采用的是读写分离的方式。

  • 读操作:主库、从库都可以接收;写操作:首先到主库执行,然后,主库将写操作同步给从库。
  • 写操作:首先到主库执行,然后,主库将写操作同步给从库。
    在这里插入图片描述

主从库间如何进行第一次同步

Redis 提供了主从库模式,以保证数据副本的一致,主从库之间采用的是读写分离的方式

  • 第一阶段建立连接,进行协商同步,
  • 第二阶段主库向同步发送RDB文件将同步数据给从库
  • 第三阶段主库发送新的写命令给从库。也可以选择一些从库进行为其他从库进行复制
    在这里插入图片描述

主从级联模式分担全量复制时的主库压力

我们可以再选择一些从库(例如三分之一的从库),在这些从库上执行如下命令,让它们和刚才所选的从库,建立起主从关系。
在这里插入图片描述

主从库间网络断了怎么办?

网络断了之后,主从库会采用增量复制的方式继续同步。

全量复制是同步所有数据,而增量复制只会把主从库网络断连期间主库收到的命令,同步给从库。

当主从库断连后,主库会把断连期间收到的写操作命令,写入 replication buffer,同时也会把这些操作命令也写入 repl_backlog_buffer 这个缓冲区。repl_backlog_buffer 是一个环形缓冲区,主库会记录自己写到的位置,从库则会记录自己已经读到的位置。

Redis repl_backlog_buffer 的使用
在这里插入图片描述
Redis 增量复制流程
在这里插入图片描述
不过,有一个地方我要强调一下,因为 repl_backlog_buffer 是一个环形缓冲区,所以在缓冲区写满后,主库会继续写入,此时,就会覆盖掉之前写入的操作。如果从库的读取速度比较慢,就有可能导致从库还未读取的操作被主库新写的操作覆盖了,这会导致主从库间的数据不一致。

主库挂了,怎么办?

哨兵其实就是一个运行在特殊模式下的 Redis 进程,主从库实例运行的同时,它也在运行。哨兵主要负责的就是三个任务:监控、选主(选择主库)和通知。

  • 监控是指哨兵进程在运行时,周期性地给所有的主从库发送 PING 命令,检测它们是否仍然在线运行。如果从库没有在规定时间内响应哨兵的 PING 命令,哨兵就会把它标记为“下线状态”;同样,如果主库也没有在规定时间内响应哨兵的 PING 命令,哨兵就会判定主库下线,然后开始自动切换主库的流程。

  • 这个流程首先是执行哨兵的第二个任务,选主。主库挂了以后,哨兵就需要从很多个从库里,按照一定的规则选择一个从库实例,把它作为新的主库。这一步完成后,现在的集群里就有了新主库。

  • 然后,哨兵会执行最后一个任务:通知。在执行通知任务时,哨兵会把新主库的连接信息发给其他从库,让它们执行 replicaof 命令,和新主库建立连接,并进行数据复制。同时,哨兵会把新主库的连接信息通知给客户端,让它们把请求操作发到新主库上。
    在这里插入图片描述
    哨兵机制,它通常会采用多实例组成的集群模式进行部署,这也被称为哨兵集群。引入多个哨兵实例一起来判断,就可以避免单个哨兵因为自身网络状况不好,而误判主库下线的情况。同时,多个哨兵的网络同时不稳定的概率较小,由它们一起做决策,误判率也能降低。
    在这里插入图片描述

新主库的选择过程

首先,哨兵会按照在线状态、网络状态,筛选过滤掉一部分不符合要求的从库,然后,依次按照优先级、复制进度、ID 号大小再对剩余的从库进行打分,只要有得分最高的从库出现,就把它选为新主库。。在这里插入图片描述

哨兵模式

主库挂掉了通过哨兵选出新主库

哨兵主要负责的就是三个任务:监控、选主(选择主库)和通知。

  • 监控:负责监控 redis master 和 slave 进程是否正常工作
  • 选主:如果 master node 挂掉了,会自动转移到 slave node 上(哨兵会先排除一些不适合做主库的从库,然后通过比较进行打分得分最高的推举为新主库)
  • 消息通知:如果某个 redis 实例有故障,那么哨兵负责发送消息作为报警通知给管理员。

哨兵实例之间可以相互发现,要归功于 Redis 提供的 pub/sub 机制,也就是发布 / 订阅机制,哨兵只要和主库建立起了连接,就可以在主库上发布消息了,
同时,它也可以从主库上订阅消息,获得其他哨兵发布的连接信息

网络断了之后,主从库会采用增量复制的方式继续同步

哨兵间的通信

哨兵实例之间可以相互发现,要归功于 Redis 提供的 pub/sub 机制,也就是发布 / 订阅机制。

哨兵只要和主库建立起了连接,就可以在主库上发布消息了,比如说发布它自己的连接信息(IP 和端口)。同时,它也可以从主库上订阅消息,获得其他哨兵发布的连接信息。当多个哨兵实例都在主库上做了发布和订阅操作后,它们之间就能知道彼此的 IP 地址和端口。

为了区分不同应用的消息,Redis 会以频道的形式,对这些消息进行分门别类的管理。所谓的频道,实际上就是消息的类别。当消息类别相同时,它们就属于同一个频道。反之,就属于不同的频道。只有订阅了同一个频道的应用,才能通过发布的消息进行信息交换。
在这里插入图片描述

Redis发布订阅

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

subscribe kuangshenshuo(channel) # 订阅一个频道 
publish kuangshenshuo "hello" # 发布者发布消息到频道

保证缓存与数据库双写时的数据一致性

  • 一种情况是串行化,但是吞吐率会大幅度降低
  • 另一种是先更新数据库后删除缓存。通过维护一个删除失败队列(失败后再删除)或者设置一个过期时间

Redis的过期删除策略

  • 定时过期:到过期时间就会立即清除。该策略可以立即清除过期的数据,对内存很友好;但是会占用大量的CPU资源,从而影响缓存的响应时间和吞吐量。
  • 惰性过期:只有当访问一个key时,才会判断该key是否已过期,过期则清除。该策略可以最大化地节省CPU资源,却对内存非常不友好
  • 定期过期:每隔一段时间,对一些key进行检查,删除里面过期的key。

Redis中同时使用了惰性过期和定期过期两种过期策略。通过配合使用这两种过期键的删除策略,
服务器可以很好地在合理使用CPU时间和避免浪费内存空间之间取得平衡。

Redis的内存淘汰策略:

全局的键空间选择性移除:移除最近最少使用的key
设置过期时间的键空间选择性移除:在设置了过期时间的键空间中,移除最近最少使用的key。

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

redis为什么不支持回滚

  • Redis 命令只会因为错误的语法而失败
  • 错误应该在开发的过程中被发现,而不应该出现在生产环境中。
  • 因为不需要对回滚进行支持,所以 Redis 的内部可以保持简单且快速。

缓存异常:

  • 缓存雪崩是指缓存同一时间大面积的失效:
    缓存数据过期时间随机
    热点数据不设置过期时间

  • 缓存穿透是指缓存和数据库中都没有的数据
    从缓存取不到的数据,在数据库中也没有取到,
    这时也可以将key-value对写为key-null,缓存有效时间可以设置短点
    布隆过滤器

  • 缓存击穿
    缓存雪崩不同的是,缓存击穿指并发查同一条数据,缓存雪崩是缓存同一时间大面积失效。
    热点数据不设置过期时间

SpringBoot使用Redis做缓存

一个系统在于数据库交互的过程中,内存的速度远远快于硬盘速度,当我们重复的获取相同数据时一次又一次的请求数据库,在性能上进行了极大的浪费于是用Redis做缓存是一个不错的选择。

Cache的缓存注解

  • @Cacheable:标记在一个方法或者类上,缓存该类所有的方法的返回值。
  • @CacheEvict:从缓存中移除数据
  • @CachePut:方法支持缓存功能。与@Cacheable区别是不会去检查缓存中是否有这个结果,而是每次都会执行该方法,并将执行的结果以键值对的形式存入指定的缓存中。

io多路复用的三种方法(Linux)

IO复用是Linux中的IO模型之一,IO复用就是进程告诉内核需要监视的IO条件,使得内核一旦发现进程指定的一个或多个IO条件就绪,就通过进程处理,从而不会在单个IO上阻塞了,Linux中,提供了select、poll、epoll三种接口来实现IO复用

select与poll
在这里插入图片描述

epoll
在这里插入图片描述

Redis的分布式锁

Redis为单进程单线程模式,采用队列模式将并发访问变成串行访问。Redis中可以使用SETNX命令实现分布式锁

  • 可重入锁
  • 不可重入锁
    在这里插入图片描述

分布式锁的缺陷

在集群模式时候并不是绝对安全的
Redis在哨兵模式下主节点挂掉之前某个客户端申请了一把锁。新的主节点并不知道,就把锁分给了另一个客户端。导致同样一把锁被两个客户端同时持有。
为了解决这个问题–红锁

Redis的启动命令

使用配置文件启动Redis的服务器

方法一:独占式启动Redis
在这里插入图片描述

方法二:非独占式启动Redis
在这里插入图片描述

启动Redis

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值