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

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

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

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

一、Redis 线程模型

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

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

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

2、为什么设计为单线程模型速度也很快?

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

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

3、全局hash表

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

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

二、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文件

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个键被更改则进行快照。

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

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

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 执行事务

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

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服务也可以正常工作。当有问题的服务故障排除后,可以继续在集群中工作。即使是主机故障,也可以从多台从机中,选举出一台服务作为主机(哨兵机制)

主从复制的作用主要包括:

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

主从复制配置

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

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

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

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

主从复制实例

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

主机配置

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

单哨兵

哨兵集群  

 

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

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

Redis提供了两种删除策略:

1、惰性删除

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

浪费内存空间,但节省CPU

2、定时删除

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

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

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

采用延时双删机制:先删除Redis数据,再更新Mysql,延迟几百毫秒再删除Redis数据。这样就算在更新Mysql时,有其他线程读了没有更新的Mysql数据,把老数据读到了Redis中,那么也会被删除掉,从而保持数据一致。

(第一个线程要对mysql进行操作的时候,要先把Redis数据删掉,去更新mysql,在此没有实际更新之前,另一个线程看Redis中没有,去mysql中拿到没有更新的数据,写到Redis中。但是没有关系,在mysql更新之后立即把Redis数据删掉,这样保证Redis和mysql数据一致)

八、跳表

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

跳表是zset的底层实现之一,是一种将有序链表改造为支持近似"折半查找"算法。查询一个元素时,不需要从头一个一个查询,先确定元素在调表中的区间范围,可以提高查询效率。

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

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

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

缓存处理流程

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

1、缓存穿透

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

解决办法:

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

2、缓存击穿

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

解决办法:

合理设置key的过期时间加锁,查询mysql时,进行加锁处理

3、缓存雪崩

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

解决办法:

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

文章链接

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: