侧边栏壁纸
博主头像
帮主の后花园博主等级

欢迎光临,开开心心每一天

  • 累计撰写 21 篇文章
  • 累计创建 5 个标签
  • 累计收到 3 条评论

目 录CONTENT

文章目录

Redis概述

Gxbalun
2023-11-08 / 0 评论 / 1 点赞 / 148 阅读 / 24662 字

Redis

概述

Redis是一个开源、使用C语音编写、支持网络交互、内存中的key-value数据结构存储系统。它可以作为数据库、缓存和消息中间件。

它支持多种类型的数据结构,如字符串(String)、散列(hashes)、列表(list)、集合(set)、有序集合(sorted set)与范围查询,bitmaps,hyperloglogs和地理空间(geospatial)索引半径查询。

关系型数据库和非关系型数据库

关系型数据库

采用关系模型来组织数据的数据库,关系模型就是二维表格模型。一张二维表的表名就是关系,二维表中的第一行就是一条记录,二维表中的一列就是一个字段。

优点:

  • 容易理解

  • 使用方便,通用的sql语言

  • 易于维护,丰富的完整性(实体完整性、参照完整性和用户定义的完整性),大大降低了数据冗余和数据不一致的概率缺点

缺点:

  • 磁盘I/O是并发的瓶颈

  • 海量数据查询效率低

  • 横向扩展困难,无法简单的通过添加硬件和服务节点来扩展性能和负载能力

  • 当需要对数据库进行升级和扩展时,需要停机维护和数据迁移

  • 多表的关联查询以及复杂的数据分析的复杂sql查询,性能欠佳。因为要保证ACID。

非关系型数据库

非关系型,分布式,一般不保证遵循ACID原则的数据存储系统。键值对存储,结构不稳定。

优点:

  • 根据需要添加字段,不需要多表联查。仅需要id取出对应的value

  • 严格上讲不是一种数据库,而是一种数据结构化存储方法的集合

缺点:

  • 只适合存储一些较为简单的数据

  • 不适合复杂查询的数据

  • 不适合持久存储海量数据

Linux远程连接命令

 redis-cli -h HOST -p PORT -a PASSWD

HOST(ip 例:127.0.0.1)

PORT (端口号)

PASSWD (redis密码)

Redis数据类型

Redis支持的5种数据类型:

string(字符串)

hash(哈希)

list(列表)

set(集合)

zset(sorted set:有序集合)

String(字符串)

string是redis最基本的类型,一个key对应一个value。

string类型是二进制安全的。意思是Redis的string可以包含任何数据。比如jpg图片或序列化的对象。

string类型的值最大能存储512MB。

实例:

image-20210716203912884

在以上实例中使用了Redis的SET和GET命令。键为name,对应的值是balun。

Hash(哈希)

redis hash是一个键值(key=>value)对集合。

redis hash是一个string类型的field和value的映射表,hash特别适合用于存储对象。

存的是字符串和字符串之间的映射,如L一个用户要存储全名、姓氏、年龄等等。

实例:

image-20210716205106880

image-20210716210556444

HMSET设置了两个filed=>value对,HGET获取对应field对应的value。

每个hash可以存储231-1 键值对(40多亿)。

常用指令:

  • HLEN keyName (查看指定Hash表的键值对数量)

  • HKEYS keyName (查看指定Hash表中的所有键)

  • HVALS keyName (查看指定Hash表中的所有值)

  • HGET keyName field (查看Hash表中指定键对应的值)

List(列表)

Redis列表是最简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列的头部或者尾部。

image-20210716211359143

image-20210716211429415

Set(集合)

Redis的Set是string类型的无序集合。

集合是通过哈希表实现的,所以添加、删除、查找的复杂度都是O(1)。

sadd命令

添加一个string元素到key对应的set集合中,成功返回1,如果元素已经在集合中,则返回0.

 sadd key member

实例:

image-20210716212439001

image-20210716212455293

以上实例中,Miss.Liu添加了两次,但根据集合内元素的唯一性,第二次插入的元素将被忽略。最大成员数为232 -1(约40多亿个)。

zset(sorted set:有序集合)

Redis zset和set一样也是string类型元素的集合,且不允许重复元素。

不同的是每个元素都会关联一个double类型的分数。Redis正是通过分数来为集合中的元素进行从小到大排序。

zset中的元素是唯一的,但分数可以重复

zadd命令

添加元素到集合,元素在集合中存在则更新对应的分数(score)

 zadd key score member

实例:

image-20210717083047665

image-20210717083109177

设置失效时间

有时候我们并不希望redis的key一直存在。例如缓存、验证码等数据,我们希望它们在一定时间后自动销毁。redis提供了一些命令,能够对key设置过期时间,让key过期之后自动删除。

设置值时直接设置有效时间

image-20210717211455461

EX表示以秒为单位

PX表示以毫秒为单位 EX和PX不区分大小写

 set name balun EX 30    设置失效时间为30秒
 ttl 查看剩余时间(秒)
 pttl    查看剩余时间(毫秒)

设置值后设置有效时间

 expire  (秒)
 pexpire (秒)

过期key删除策略

1.定时删除

在设置key的过期时间的同时,为该key创建一个定时器,让定时器在key过期时对key进行删除。

优点:

定时删除策略对内存是友好的,使用定时器可以保证过期键会尽快被删除,释放占用内存。

缺点:

对CPU不友好,在过期键比较多的情况下,删除过期键可能会占用一部分CPU时间,在内存不紧张但是CPU紧张的情况下,将CPU时间用在删除和当天任务无关的过期键上,无疑会对服务器的响应时间和吞吐量造成影响。

创建一个定时器需要用到Redis服务器中的时间事件,而当前时间事件的实现方式——无序链表,查找一个事件的时间复杂度为O(N),并不能高效处理大量时间事件。

2.惰性删除

每次从数据库获取key的时候去检查是否过期,如果过期,就删除该键,否则就返回该键。

优点:

惰性删除策略对CPU是有好的,程序会在获取键时才对键进行过期检查,并且删除的目标仅限于当前处理的键,这个策略不会再删除其他无关的过期键上花费CPU时间。

缺点:

对内存不友好,如果一个键以及过期,只要这个键不被删除,它所占用的内存就不会被释放。如果数据库有很多过期键,而这些过期键又没有被访问到的话,那么他们永远不会被删除,除非手动执行flushdb。

3.定期删除

每隔一段时间,程序就对数据库进行检查,删除里面的过期键。

优点:

定期删除策略是前两种策略的一种整合和折中:

  • 定期删除策略每隔一段时间执行一次删除过期键的操作,并通过限制删除操作执行的时长和频率来减少操作对CPU时间的影响。

  • 定期删除策略有效的减少了因为过期键而带来的内存浪费。

缺点:

  • 如果删除操作执行的太频繁,或执行时间太长,定期删除策略就退化为定时删除策略,以至于CPU时间过多的消耗在删除过期键上。

  • 如果删除操作执行的太少,或者执行的时间太短,定期删除策略又会和惰性删除策略一样,出现浪费内存的情况。

Redis采用的过期键删除策略

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

主从复制

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

使用一个Redis实例作为主机,其余的作为备份机。主机和备份机的数据完全一致,主机支持数据的写入和读取各项操作,而从机则只支持与主机数据的同步和读取。也就是说客户端可以将数据写入主机中,由主机自动将数据的写入操作同步到从机。主从模式很好的解决了数据备份的问题,并且由于主从服务数据几乎是一致的,因而可以将写入数据的命令发送给主机执行,而读取数据的命令发送给不同的从机执行,从而达到读写分离的目的。

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

  1. 数据冗余:主从复制实现了数据的热备份,使持久化之外的一种数据冗余方式。

  2. 故障恢复:当主节点出现问题时,可以有从节点提供服务,实现快速的故障恢复;实际上是一种服务的冗余。

  3. 负载均衡:在主从机的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务(即写Redis数据时应用连接主节点,读Redis数据时应用连接从节点),分担服务器负载;尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高Redis服务器的并发量。

  4. 高可用(集群)基石:除了上述作用以外,主从复制还是哨兵和集群能够实施的基础,因此说主从复制是Redis高可用的基础。

image-20210718095236806

哨兵机制

概述

哨兵模式是一种特殊的模式,首先Redis提供了哨兵的命令,哨兵是一个独立的进程,作为进程,它会独立运行。其原理是哨兵通过发送命令,等待Redis服务器响应,从而监控运行的多个Redis实例。

单哨兵

image-20210718173431005

哨兵集群

image-20210718173448925

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

缓存处理流程

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

image-20210718173735914

缓存穿透

key对应的数据在数据库中并不存在,每次针对此key的请求从缓存中获取不到,请求都会到数据库,从而可能压垮数据库。比如:用一个不存在的用户id获取用户信息,不论缓存还是数据库都没有,若黑客利用此漏洞进行攻击,可能压垮数据库。(数据库没有,缓存没有)

image-20210718174215844

解决办法:

  1. 使用布隆过滤器(BloomFilter)或压缩filter提前拦截。

  2. 将这个空对象设置到缓存中取。下次在请求的时候直接从缓存中获取。(这种情况我们一般会将空对象设置一个较短的过期时间)。

  3. 拉黑该IP地址。

  4. 对参数进行校验,不合法参数进行拦截。

缓存击穿

某个key对应的数据库中存在,但是在redis中的某个时间节点过期了,此时若有大量并发请求过来,这些请求发现缓存过期,都会从后端DB加载数据并回设到缓存,这时大量并发请求可能会瞬间把后端DB压垮。(热点key突然过期)

image-20210718174810426

解决办法:

  1. 热点数据设置永不过期。

  2. 加上互斥锁:上面的现象是多个线程同时取查询数据库的这条数据,那么我们可以在第一个查询数据的请求上使用一个互斥锁来锁住它。其它的线程走到这一步拿不到锁就等待,等第一个线程查询到了数据,然后将数据放到Redis缓存起来,后面的线程进来发现以及有缓存了,就直接走缓存。

缓存雪崩

在高并发的情况下,大量的缓存失效,或者缓存层出现故障。于是所有的请求都会到达数据库,数据库的调用量暴增,造成数据库挂掉的情况。(大量缓存失效)

image-20210718175414051

解决办法:

  1. 随机设置key失效时间,避免大量key集体失效。

  2. 若是集群部署,可将热点数据均匀分布在不同的Redis库中,也能避免key全部失效的问题。

  3. 不设置过期时间。

  4. 跑定时任务,在缓存失效前刷进新的缓存。

总结

雪崩是大面积的key缓存失效,穿透是Redis缓存里不存在的key,击穿是Redis某个热点key突然失效。

对于Redis宕机的情况,可以有以下思路:

事发前: 实现Redis的高可用(主从架构+哨兵)。尽量避免Redis挂掉。 事发中: 万一Redis挂了,可以设置本地缓存+限流。尽量避免数据库垮掉。 事发后: Redis持久化,重启后自动从磁盘加载数据,快速恢复缓存数据。

常见面试题

什么是Redis?

Redis是完全开源免费、遵守BSD协议的一个高性能key-value数据库。

Redis与其它key-value缓存产品有以下三个特点:

  1. Redis支持数据持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载使用。

  2. Redis不仅仅支持简单的key-value类型的数据,同时还提供list、set、zset、hash等数据结构的存储。

  3. Redis支持数据的备份,即master-slave模式的数据备份。

Redis的优势?

  1. 性能高

  2. 丰富的数据类型(Redis支持二进制案例的string、list、set、hash、zset等数据类型操作)。

  3. 原子性(Redis所有操作都是原子性的,就是要么成功执行要么失败完全不执行。单个操作也是原子性的。多个操作也支持事务)。

  4. 丰富的特性(Redis还支持publish/subscribe、通知、key过期等特性)。

Redis的数据类型?

Redis支持5种数据类型:string、hash、list、set及zset(有序集合)。

实际项目中比较常用的是string,hash。

使用Redis有哪些好处?

  1. 速度快,因为数据存在内存中,类似HashMap,HashMap的优势就是查找和操作时间复杂度都是O(1)。

  2. 支持丰富的数据类型,string、list、hash、set、zset等。

  3. 支持事务,操作都是原子性。

  4. 丰富的特性:可用于缓存、消息、设置key过期时间。

Redis是单进程单线程的?

Redis是单进程单线程的,redis团队利用技术将并发访问变为串行访问,消除了传统数据串行控制的开销。

一个字符串类型的值能存储最大容量是多少?

512M

持久化

什么是持久化?

持久化就是把内存的数据写到磁盘中去,防止服务宕机后内存数据丢失。

Redis的持久化机制是什么?各自的优缺点?

Redis提供了两种持久化机制RDB(默认)和AOF机制:

RDB:是Redis DataBase缩写快照

RDB是Redis默认的持久化方式。按照一定时间将内存的数据以快照的形式保存在硬盘中,对应产生的数据文件为dump.rdb。通过配置文件中的save参数来定义快照的周期。

image-20210718210147037

优点:

  1. 只有一个文件dump.rdb,方便持久化。

  2. 容灾性好,一个文件可以保存到安全的磁盘。

  3. 性能最大化,fork子进程来完成写操作,让主进程继续处理命令,所以是IO最大化。使用单独子进程进行持久化,主进程不会进行任何IO操作,保证了Redis的高性能。

  4. 相对于数据集大时,比AOF的启动效率更高。

缺点:数据安全性低。RDB是间隔一段时间进行持久化,如果持久化之前redis发生故障,会发生数据丢失。所以这种方式更适合数据要求不严谨的时候。

AOF:持久化

AOF持久化(Append only file),则是将Redis执行的每次写命令记录到单独的日志文件中,当重启Redis会重新将持久化的日志中文件恢复数据。

当两种方式同时开启时,数据恢复Redis会优先选择AOF恢复。

image-20210718211442806

优点:

  1. 数据安全,AOF持久化可以配置appendfsync属性,有always,每进行一次命令操作就记录到aof文件中一次。

  2. 通过append模式写文件,即使中途宕机,可以通过redis-check-aof工具解决数据一致性问题。

  3. AOF机制的rewrite模式。AOF文件没被rewrite之前(文件过大时会对命令进行合并重写),可以删除其中的某些命令(比如误操作的flushall)。

缺点:

  1. AOF文件比RDB文件大,且恢复速度慢。

  2. 数据集大的时候,比RDB启动效率低。

1

评论区