Redis知识点

Redis

文章目录

NoSQL

NoSQL:(not only SQL)不仅仅是SQL语句,泛指非关系型的数据库,区别于关系数据库。随着互联网 web2.0 网站的兴起,传统的关系数据库在处理 web2.0网站,特别是超大规模和高并发动态网站已经显得力不从心,出现了很多难以克服的问题,而非关系型的数据库则由于其本身的特点得到了非常迅速的发展。

NoSQL的优势

易扩展,数据之间无关系,这样就非常容易扩展,无形之间也在架构的层面上带来了可扩展的能力。

高性能,NoSQL 数据库都具有非常高的读写性能,尤其在大数据量下,同样表现优秀。这得益于它的无关系性,数据库的结构简单。

灵活的数据模型 NoSQL 无须事先为要存储的数据建立字段,随时可以存储自定义的数据格式。

Redis

Redis(远程字典服务),是NoSQL的一种,是利用C语言编写的开源的,以Key---value数据结构存储系统。可以作为数据库、缓存和消息中间件。

它支持多种数据类型,如:字符串(String)、散列值(hash)、列表(list)、集合(set)、有序集合(sorted set),Key---value中key是string类型的数据。

key---value是利用dict结构体进行存储的。

dict :hash字典

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-K1Ghp2R2-1691936074904)(C:\Users\wdy_1\AppData\Roaming\Typora\typora-user-images\1691844349338.png)]

dict中维护了一个dictht ht[2] 两个hash表,ht[1]主要用于发生冲突后进行rehash的时候使用,ht[0]是常用的hash表。

redis的rehash并非像我们传统的那样:一次性做完所有的数据迁移工作。Redis将扩容后的rehash操作分散到了它的CRUD操作中,并非一步到位,而且每次rehash遵循少量多次原则,在它的查找、添加、删除都有rehash的体现,称之为渐进式rehash。当ht[0]中的数据完全迁移完成之后,先让ht[0]hash数组清空,然后让ht[0]的指针指向ht[1],这样下次rehash的时候又可以重复操作。

Redis与其他的Key---value(Map)相比的区别?

  1. Redis支持数据的持久化,可以将内存中的数据保存到磁盘中,重启后,再次加载就可以使用。Map是内存对象,程序关闭后就清除了。
  2. Redis可以用几十G来做缓存,Map不行。
  3. Redis可以实现分布式的缓存,Map只能存在创建它的程序中。
  4. Redis可以处理每秒百万级的并发,是专业的缓存服务,Map只是普通的对象。
  5. Redis缓存有过期机制,Map本身没有这个功能。

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

关系型数据库

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

优点

  • 容易理解;
  • 使用方便,直接使用SQL语句
  • 易于维护

缺点

  • 磁盘IO是并发的瓶颈
  • 海量数据查询效率低
  • 横向扩展困难
  • 多张表关联查询的复杂SQL查询,性能欠佳。

非关系型数据库

非关系型,一般不保证ACID原则的数据存储系统。键值对存储。

优点

  • 性能好
  • 结构简单
  • 灵活的数据模型

缺点

  • 只适合存储一些简单的数据
  • 不适合持久存储海量数据

Redis数据类型

常用的五种数据类型:字符串(String)、散列值(hash)、列表(list)、集合(set)、有序集合(sorted set)。

底层共有六种数据结构:简单动态字符串、双向链表、压缩列表、哈希表、跳表和整数数组。

跳表

是由有序链表优化而来,链表的查询效率不高。可以把每两个元素的第一个元素提上一层,建立一些冗余索引。进而可以支持快速的插入、删除、查找操作。

查找32,类似这般查找。

压缩表

类似数组,由一系列特殊编码的连续内存块组成的顺序型数据结构。

String(字符串)

string是Redis最基本的类型,一个key对应一个value。底层使用简单动态字符串(sds)实现。最大能存储512MB

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

44字节一下:OBJ.ENCLUDING.EMBSTR(地层是连续的),44字节以上:OBJ.ENCLUDING.RAW(地层是不连续的),数值型:OBJ.ENCLUDING。INT

使用场景

  1. 计数器功能,我们可以使用incr命令实现自增操作,来计数,例如统计文章阅读量,点赞量,粉丝数等。
  2. 存储Token信息。
  3. session共享,在分布式系统中,由于有多台服务器,请求分发每次发送到的目标服务器肯能不同,name此时就需要一个中间件来保存session的状态,可以把session保存在redis中
  4. 限流,就是有时候我们需要对某些用户、某些接口进行限流,即比如只能访问多少次等。

Hash(哈希)

底层使用压缩表和哈希表

Hash和String都可以存储对象,但是String是将对象转换称为json对象,适合用于不经常修改的字符串,如果是那种需要经常修改的,建议使用Hash存储。

哈希冲突较多时

使用场景

  1. 存储对象信息
  2. 购物车。使用用户ID作为缓存key,使用商品编号作为hashKey,使用商品信息作为hashValue

List(列表)

是一个简单的列表,可以重复,保证添加顺序。

用于消息队列,评论中按照时间先后的评论记录

使用场景

  1. 消息队列。可以使用lpush+brpop命令实现阻塞队列
  2. 文章评论按照时间先后排序

set

元素不重复,不保证添加顺序。

快速定位需要查找的元素,可以用来实现点赞收藏等功能,共同好友推荐,

使用场景

  1. 社交类软件的共同好友
  2. 抽奖功能,返回随机数
  3. 统计访问网站的ip地址

Zset有序集合

有序集合,值是Map<Object , Double>,每一个元素都会有一个分值,值不能重复,但是分数可以重复。

使用场景

  1. 排行榜功能

Redis为什么快?

  • Redis运行在内存中
  • 数据结构简单
  • 使用多路IO复用技术
  • 单线程实现,单线程避免了线程切换、锁等造成的性能开销。

Redis是单线程还是多线程?

Redis6之前是单线程,为什么呢?

简单来说,就是Redis官方认为没有必要,单线程的Redis的瓶颈通常在CPU的IO,而在使用Redis时几乎不存在CPU成为瓶颈的情况。使用Redis主要的瓶颈在于内存和网络,并且使用单线程也存在一些优点,比如避免了并发读写带来的一些列问题。

为什么6.0之后引入了多线程?

单线程的瓶颈在内存和网咯,Redis6.0引入多线程主要是为了解决网络IO读写这个瓶颈,执行命令还是单线程执行的,所以不存在线程安全问题。

Redis6.0默认是否开启了多线程?

没有,需要修改配置redis.conf: io-threads-do-redis no,中的no改为yes

Redis过期键的删除策略

  1. 立即删除。在设置键的过期时间时,创建一个回调事件,当过期时间达到时,有时间处理器自动执行键的删除操作。立即删除能保证内存中数据的最大新鲜度,因为它保证过期键值会在过期后马上被删除,其所占用的内存也会随之释放。但是立即删除对CPU不是最友好的,因为删除操作会占用CPU时间。
  2. 惰性删除。惰性删除是指,某个键值过期后,此键值不会马上被删除,而是等到下次使用的时候,才会被检查到过期,此时才能得到删除。所以惰性删除的缺点是浪费内存,如果大量过期的键没有被访问就会一直占用着内存。
  3. 定期删除。每隔一段时间,就会对键进行检查,删除其中过期的键,该策略是惰性删除和立即删除的一个折中,既避免了大量占用CPU资源又避免了出现大量过期键不被删除占用内存的情况。

Redis持久化

Redis是一个内存数据库,数据保存在内存中,但是我们都知道内存的数据变化很快,也容易丢失。Redis还为我们提供了持久化的机制,分别是RDB(Redis DataBase)和AOF(Append Only File)。

RDB方式

RDB持久化是指在指定的时间间隔内将内存数据中数据集快照写入磁盘。也就是默认的持久化方式,这种方式就是将内存中数据以快照的方式写入到二进制文件中,默认的文件名为dump.rdb。恢复时是将快照读取到内存中。

触发快照的时机

save的规则满足的情况下,会触发RDB规则。

save 20 10 就是在20秒之内对10个键值进行操作,会触发持久化;

也可以在关闭Redis的时候使用shutdown save命令持久化到RDB中。

优点

  • 适合对大规模的数据恢复
  • 只有一个文件dump.rdb,方便持久化
  • 性能最大化。

缺点

  • 数据安全性低,在一定时间间隔内做一次备份,如果redis突然宕机,会丢失最后一次快照之后的数据

AOF方式

AOF持久化以日志的形式记录服务器所处理的每一个写,删除操作,查询操作不会记录,以文本的方式记录,可以打开文件看到详细的操作记录。

优点

  • 具备更高的安全性,Redis提供了三种同步策略,分别是每秒同步、每修改同步和不同步。相比RDB突然宕机丢失的数据会更少。
  • 由于此机制中对日志文件的写入操作是append模式,因此即使在写的过程中出现宕机情况,也不会影响到已经保存的日志内容。
  • AOF包含一个格式清晰、易于理解的日志文件用于记录所有的修改操作,可以通过该文件完成数据的重建。

缺点

  • 对于相同数量的数据而言,AOF文件通常要大于RDB文件。RDB在恢复大数据集时的速度更快。
  • 根据AOF选择同步策略的不同,效率也不同,但AOF在运行效率上一般会慢与RDB。

Redis的事务

Redis事务本质是一组指令的集合,一个事务中的所有指令都会被序列化,在事务执行过程中,会按照顺序执行。Redis事务的主要作用就是串联多个指令防止别的指令插队

所有的指令在事务中,并没有直接被执行。只有发起执行exec指令的时候才执行。

事务在执行的过程中,不会被其他客户端发送来的指令请求打断。

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

事务执行的三个阶段

Redis的事务操作:

  • 开启事务(multi),

  • 执行命令、命令入队,

  • 执行事务(exec),

  • 放弃事务(discard)。

在事务开启前还可以通过watch指令观测监听某个键的变化,如果在其他客户端将监听值修改,在事务中对某个键操作时,事务会失效。

Redis的集群、主从、哨兵

为什么要使用Redis集群?

Redis单机版有以下缺点:

  1. 不能保证该数据的可靠性,服务部署在一台服务器上,一旦服务器宕机服务就不可用。
  2. 性能瓶颈,内存容量有限,处理能力有限。

Redis集群就是为了解决Redis单机版的这些问题。

Redis集群的实现方案有哪些?

  • 主从模式
  • 哨兵模式
  • Redis自研

主从模式

单机版通过RDB或者AOF持久化机制将数据持久化到磁盘上,但数据都存储在一台服务器上,并且读写都在同一台服务器(读写不分离),如果磁盘出现问题,则会导致数据不可用,为了避免这种问题,Redis提供了复制功能,即主从复制

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

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

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

  1. 数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式
  2. 故障恢复:当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复;实际上是一种服务的冗余。
  3. 负载均衡:在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务(即写Redis数据时应用链接主节点,读Redis数据时应用链接从节点)分担服务器负载。

优点

  • 高可靠性。在主机数据出现故障后可以切换到从机。
  • 读写分离。

缺点

  • 不具备自动容错和恢复能力,主节点故障,从节点需要手动升级为主节点。

哨兵机制

为了解决主从模式的Redis集群不具备自动容错和恢复能力的问题,Redis2.6之后提供了哨兵模式。

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

单哨兵

哨兵集群

监听所有服务器是否正常运行:通过发送命令返回服务器的运行状态,除了监控主服务器、从服务器外,哨兵之间也相互监控。

故障切换:当哨兵检测到master宕机,会自动将slave切换称为master,然后通过发布订阅模式通知其他服务器修改配置文件,让它们切换master。同时那台有问题的旧主机也会变为新主机的从。

优点

是基于主从模式的,解决主从模式中master故障不可以自动切换故障的问题。

缺点

  • 浪费资源,集群里所有的节点保存的都是全数据,数据量过大时,主从同步会严重影响性能;
  • 只有一个master执行写请求,性能瓶颈。

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

缓存处理流程

在Redis缓存中,前台请求后,后台先从缓存中读取数据,取到就直接返回结果,取不到才会去数据库中查询,查询之后将结果更新到缓存中并且返回。

缓存穿透

穿透缓存和数据库。

key对应的数据在数据库中就不存在,缓存中肯定也没有,每次请求缓存中找不到,请求都会到数据库中,从而肯能压垮数据库。比如用一个不存在的用户id获取用户信息,不论缓存还是数据库都没有。

解决办法:

  1. 将这个空对象设置到缓存里边去,下次在请求的时候,就可以从缓存中获取了。这种情况我们一般会设置一个较短的过期时间。
  2. 对参数进行校验,不和法的参数进行拦截。

缓存击穿

击穿缓存

某key在缓存中,但是如果这个key刚好过期了,此时又刚好大量请求访问这个key,这些请求发现这个key已经过期了,都会去数据库中查询,数据库的压力就上升了。

解决办法:

  1. 热点数据设置永不过期;
  2. 加锁,上面的现象是因为多个线程同时访问同一个数据,那么可以用加锁的方式解决;

缓存雪崩

大量的击穿

缓存雪崩是指,在高并发下,大量的缓冲失效,或者缓存层出现故障。于是所有的请求都会访问数据库,数据库的调用就会暴增,造成数据库挂掉。

解决办法:

  1. 随机设置key的失效时间,避免大量key集体失效。
  2. 若是集群部署,可以将热点数据均匀分布在不同的Redis库中也可以避免key全部失效问题
  3. 不设置过期时间
  4. 定时任务,在缓存失效前刷新缓存
相关推荐
Ai 编码助手1 小时前
MySQL中distinct与group by之间的性能进行比较
数据库·mysql
陈燚_重生之又为程序员2 小时前
基于梧桐数据库的实时数据分析解决方案
数据库·数据挖掘·数据分析
caridle2 小时前
教程:使用 InterBase Express 访问数据库(五):TIBTransaction
java·数据库·express
白云如幻2 小时前
MySQL排序查询
数据库·mysql
萧鼎2 小时前
Python并发编程库:Asyncio的异步编程实战
开发语言·数据库·python·异步
^velpro^2 小时前
数据库连接池的创建
java·开发语言·数据库
荒川之神2 小时前
ORACLE _11G_R2_ASM 常用命令
数据库·oracle
IT培训中心-竺老师2 小时前
Oracle 23AI创建示例库
数据库·oracle
小白学大数据2 小时前
JavaScript重定向对网络爬虫的影响及处理
开发语言·javascript·数据库·爬虫
time never ceases3 小时前
使用docker方式进行Oracle数据库的物理迁移(helowin/oracle_11g)
数据库·docker·oracle