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. 定时任务,在缓存失效前刷新缓存
相关推荐
iVictor12 分钟前
Redis 大 Key 分析利器:支持 TOP N、批量分析与从节点优先
redis
夜泉_ly2 小时前
MySQL -安装与初识
数据库·mysql
qq_529835353 小时前
对计算机中缓存的理解和使用Redis作为缓存
数据库·redis·缓存
月光水岸New6 小时前
Ubuntu 中建的mysql数据库使用Navicat for MySQL连接不上
数据库·mysql·ubuntu
狄加山6756 小时前
数据库基础1
数据库
我爱松子鱼6 小时前
mysql之规则优化器RBO
数据库·mysql
chengooooooo6 小时前
苍穹外卖day8 地址上传 用户下单 订单支付
java·服务器·数据库
Rverdoser7 小时前
【SQL】多表查询案例
数据库·sql
Galeoto7 小时前
how to export a table in sqlite, and import into another
数据库·sqlite
希忘auto8 小时前
详解Redis在Centos上的安装
redis·centos