Redis进阶

什么是redis?它是用来做什么的?

Redis是一个c语言编写的nosql的数据库,支持网络,可基于内存也可持久化的,key-value类型的数据库。 与一般数据库不同的是,redis是存储在内存中的,他的读写速度非常快,常常被广泛应用到缓存之中。

redis除了用作缓存,还可以干什么?

  1. 计数器
  2. 排行榜 (排序)
  3. 数据排重 (重复数据)
  4. 可以发布、订阅的实时消息系统
  5. 消息队列 (list先进先出)
  6. 分布式锁

一、Redis 线程模型

1、Redis是单线程模型还是多线程模型

redis6.x版本之前,属于彻彻底底的单线程,redis中监听客户端连接、读写数据操作,都是由一个单线程来完成的,效率低。

redis6.x之后,引入了多线程。将客户端网络请求,由多线程来负责完成,数据读写操作仍然是单线程。(单线程操作不会出现并发安全问题,保证了操作的原子性)

2、为什么设计为单线程模型速度也很快?
  1. Redis是基于内存操作的,所有的运算都是内存级别的,所以性能比较高
  2. 底层是一个hash表结构,查找和操作的时间复杂度是O(1)
  3. IO多路复用和非阻塞 I/O(后面会补充,属于操作系统级别的IO)
  4. 单线程避免了线程间的切换

redis的瓶颈不是cpu,而是内存大小、网络速度,本身速度就很快。

3、全局hash表

Redis底层是一个hash表结构,时间复杂度是O(1)

hash可以在O(1)的时间内计算出hash值并且找到对应的entry位置,entry里面是一个一个key指针和value指针,其实还有其他信息。这也是redis之所以性能高的原因之一。

Redis进阶_第1张图片

二、Redis数据持久化

因为redis数据平常存储在内存中,一旦机器故障可能数据就会丢失。Redis还提供了数据持久化的机制,把内存中的数据,根据一定规则写入到硬盘中的文件,分别是RDB和AOF。

  • 点赞-->存储在redis内存中--->定期的将数据写入到文件中。定时任务:每天晚上0点,把redis的数据写入到mysql

在我们安装了redis之后,所有的配置都是在redis.conf文件中,里面保存了RDB和AOF两种持久化机制的各种配置。当符合一定条件时,Redis会自动将内存中的数据进行快照并持久化到硬盘。

1、RDB方式(Redis DataBase)

在redis.conf文件中可以进配置,是否开启rdb持久化。在满足一定的条件时,定期的将redis中的数据(数据快照)保存到一个dump.rdb文件中,在redis 重新启动时,会将数据还原回来,将键值存储到rdb文件中。

数据快照:内存中有许多key-value、key1-value1---->存储在dump.rdb文件

Redis进阶_第2张图片

rdb方式是redis默认的持久化方式,不需要配置开启,默认是支持的。

redis.conf文件中有触发rdb保存快照的条件

save:这里是用来配置触发Redis的RDB持久化条件,也就是什么时候将内存中的数据保存到硬盘。比如"save m n"。表示m秒内数据集存在n次。修改时,自动触发bgsave。

如下配置:

  • save 900 1:表示900秒钟内至少1个键被更改则进行快照。
  • save 300 10:表示300秒内至少10个键被更改则进行快照。
  • save 60 10000:表示60秒内至少10000个键被更改则进行快照。

Redis进阶_第3张图片

如果不需要持久化,那么你可以注释掉所有的save行来停用保存功能。

退出redis,也会产生 rdb 文件, 命令: shutdown save。在Redis客户端模式下,关闭Redis服务时会保存快照,重新启动Redis服务时,会将dump.rdb文件中的数据还原回来。

Redis进阶_第4张图片

2、AOF方式(Append Only File)

日志的方式来记录所有写操作的命令(读操作不记录)。redis重启的话,会还原数据,会将日志文件中写命令从前到后执行一次。

set name jim

set name tom

如果是RDB方式,最终记录name的值为tom;而AOP方式记录所有的

Redis默认是关闭的,修改redis.conf配置文件,来开启AOF机制

appendonly no #默认是不开启aof模式的,改为yes开启。

appendfilename appendonly.aof #默认的文件名是 appendonly.aof,可以通过appendfilename参数修改 AOF 同步机制。

appendfsync always #每次修改都会同步,消耗性能。

appendfsync everysec #每秒会同步一次,可能会丢失这1s的数据(默认)

appendfsync no #不同步

修改完之后,重启redis才生效。

三、Redis事务

redis事务:是将多条命令打包为一个整体执行(在同一个事务中),这样执行的过程中其他客户端命令就不能执行了。但是不保证命令的原子性(中间有一条命令报错,不影响其他命令的执行)。

redis 的事务操作:

  • 开启事务(multi)
  • 执行命令, 命令入队(把命令加入到一个队列中,并没有立即执行)
  • 执行前可以放弃事务(discard)
  • 执行事务(exec)

实例:

  • multi 开启事务
  • set a aa 添加命令
  • set b bb 添加命令
  • incr b 添加命令
  • exec 执行事务

Redis进阶_第5张图片

Redis进阶_第6张图片

但是事务不保证同一事物中多条命令执行的原子性,即使命令有错误也会添加到队列中,执行报错也不影响其他命令执行。  

redisTemplate.multi();//开启事务
    ValueOperations valueOperations = redisTemplate.opsForValue();
    valueOperations.set(a,aa);
    valueOperations.set(b,bb);
redisTemplate.exec();//执行事务

四、主从复制

主从复制,是指将一台Redis服务器的数据复制到其他的Redis服务器。前者称为主节点(master),后者称为从节点(slave),数据的复制是单向的,只能由主机到从机。

redis集群--->多台服务构成

Redis为了数据能够备份,实现读写分离(写命令找主机,读命令找从机)。有一台服务作为主机、多台服务作为从机,一台Redis服务器的数据复制到其他的Redis服务器。主机负责写数据,将数据备份到多台从机,从机负责读操作。

即使期间,有一台服务器出现问题,其他redis服务也可以正常工作。当有问题的服务故障排除后,可以继续在集群中工作。即使是主机故障,也可以从多台从机中,选举出一台服务作为主机(哨兵机制)

主从复制的作用主要包括:
  1. 必将存在数据冗余、服务冗余。主机的数据备份到从机中。
  2. 负载均衡(有多台服务,有很多请求到达后,可以根据一些机制让多个请求到达不同的服务器),读写分离,多台从机分担读操作。
  3. 实现高可用,是哨兵和集群实施的基础。
主从复制配置

主从复制时只需要配置从库即可,其默认为主库模式。打开redis客户端登录,使用命令info replication查看。

Redis进阶_第7张图片

主从复制可以搭建真集群,也可以搭建伪集群。

真集群:有多台主机、每台主机安装一个 redis。

redis伪集群:可以在一台机器上,配置多个redis端口,启动多个redis实例。配置方式两者相同。

主从复制实例

1.复制多份配置文件,一主二从

Redis进阶_第8张图片

主机配置

  • bind 0.0.0.0 #任何 ip 都可以访问
  • daemonize yes #后台运行
  • pidfile /var/run/redis_6379.pid #进程号文件
  • logfile "6379.log" #日志文件 注意文件名修改只是为了区分
  • dbfilename dump6379.rdb #数据文件
  • requirepass root #主机密码

从机配置

  • #bind 注释
  • daemonize yes #后台运行
  • port 6380 #修改端口
  • pidfile /var/run/redis_6380.pid #进程号文件
  • logfile "6380.log" #日志文件
  • dbfilename dump6380.rdb #数据文件
  • replicaof 主机ip 主机端口
  • masterauth 主机密码

从机进入客户端模式 ./redis-cli -p 从机端口

Redis进阶_第9张图片

主机  

Redis进阶_第10张图片

测试主写从读

Redis进阶_第11张图片

五、哨兵机制

哨兵是一个独立的进程,独立运行。

哨兵定期的向redis集群中发送请求,等待Redis服务器响应。如果收不到回复,就说明redis服务有问题,会通过一套选举机制,在多台从机中选取一台作为主机;当主机故障恢复后,临时主机又变为从机角色。

单哨兵

Redis进阶_第12张图片

哨兵集群  

 Redis进阶_第13张图片

六、Key过期策略(删除策略)

Redis中的key,是可以设置有效时间的。不是时间到期后就会自动删除的;当时间到了后,redis中有一套机制来删除过期的key。

Redis提供了两种删除策略:

1、惰性删除

key到期后不立即删除,只是使用一个字典记录此key已经过期,在下次使用此key时才会删除。

浪费内存空间,但节省CPU

2、定时删除

每隔指定的时间后,字典中记录过期的key,定期的删除过期的key。

redis使用的过期键值删除策略是:惰性删除加上定期删除,两者配合使用

七、如何保证Redis和mysql数据一致

采用延时双删机制:两次删除Redis中的数据,一次是在更新mysql前删除Redis数据,此时mysql还没有真正更新,有可能其他线程去mysql中查询到没有更新前的数据,所以需要在更新完mysql中数据后,定时再次删除Redis中的数据,这样其他请求就可以读到与mysql中一致的数据。

八、Redis底层数据结构——跳表

Redis数据类型(String、哈希、list、set、zset)

跳表是一种特殊的有序链表,可以维护一些区间。查询一个元素时,不需要从头一个一个查询,先确定元素在调表中的区间范围,可以提高查询效率。

Redis进阶_第14张图片

先分成大区间,再分成小区间  

九、缓存穿透、缓存击穿、缓存雪崩

redis可以用来缓存数据,访问量大的时候可以缓解mysql的压力。如果Redis使用不当,也会造成新的问题。

缓存处理流程

前台请求,后台先从缓存中取数据,取到直接返回结果,取不到时从数据库中取,数据库取到更新缓存并返回结果,数据库没取到直接返回空结果。

Redis进阶_第15张图片

1、缓存穿透

数据在mysql中本身就不存在,这样redis中也没有,每次查询时,都会访问mysql,大量访问会压垮mysql。

Redis进阶_第16张图片

解决办法:

  1. 在Redis中设置一个key为null的键值 -1:null。下次再请求的时候,就可以从缓存里边获取了。这种情况我们一般会将空对象设置一个较短的过期时间。
  2. 对参数进行校验,不合法参数进行拦截。
2、缓存击穿

mysql中有数据,在Redis中的某个时刻key到期了。此时刚好有大量请求到达,这时没有做任何的控制,大量请求查询redis,但是redis中没有数据,请求到达mysql,导致mysql被压垮。

Redis进阶_第17张图片

解决办法:

  1. 合理设置key的过期时间
  2. 加锁,查询mysql时,进行加锁处理
3、缓存雪崩

大量的key过期或者Redis服务器出现故障,导致大量的请求到达mysql(更严重的击穿)。

Redis进阶_第18张图片

解决办法:

  1. 随机设置key失效时间,避免大量key集体失效。setRedis(Key,value,time+Math.random() * 10000);
  2. 把热点key放在不同的从机。
  3. 不设置过期时间。
  4. 定时任务,将快过期的key,重新放入到缓存。

你可能感兴趣的:(redis,数据库,缓存)