秋春招总结之Redis

文章目录

基础

什么是Redis

首先大体理解:Redis是一个基于内存,通过键值对(key-value)的形式来存储数据的NoSQL数据库。和其相相对应的是MySQL,一种SQL类型的数据库。

它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些[数据类型]都支持push/popadd/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。

在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中(所以也就避免了对硬盘的频繁操作)。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。

为什么要使用Redis

前面提到了对于Redis来说一是支持的类型比较多,二是由于将信息存储在内存上,所以速度上会比SQL类型的数据库快上很多。

实际上,对于Redis来说读取速度能够达到110000次/s,写入的速度是81000次/s,能够满足我们更高频率的请求与承担更高的并发,在一些大型网站,也都会使用到redis进行数据的缓存处理,无论是采用到原生的数据类型(使用到redis自带的一些方法),或是封装成自己需要的缓存结构(进行二次的封装,这里可以参见我的博客Redis数据封装)ps:后续会进行修正与完善,在面对当下的高并发请求,都能够起到比较好的效果。

下面从两个具体的方面进行讲解:

缓存提高访问速度

一般我们对于存储在数据库中的数据的请求,都是前端页面发送请求信息,后端接收请求,并对数据进行封装和处理,最后再调用SQL语句,执行sql语句取到具体的信息。但是其实对于MySQL来说数据都是存储在硬盘上,进行数据的读取势必会消耗一定时间,但是计算机的运行速度比我们想象的要快很多,很多时候数据都是在极短的时间里面就能够查询出来,并返回给前端页面。

但是我们需要思考的是对于用户的每一次请求都需要从数据库中进行读取,当请求过于庞大时候,就会导致数据的读取和页面的相应不能够成正比,最后的结果就是,在一些特殊的情况下,根本就不能够在短时间内获取到信息。

对于Redis而言,主要就是读取速度快,而且数据类型丰富,所以就可以使用Redis来做缓存,主要过程见下图:这个时候,在下一次缓存还没过期时间内再此进行同样的请求就可以减少检索的时间,提高访问的速度。

image-20200728141537638

缓存支持高并发

缓存不仅能够提高访问的速度还有一点就是能够帮助我们减轻高并发情况下的数据库压力:

image-20200728142816623

一般用在什么地方(不考虑五种数据结构)

  1. 用作对MySQL数据库中数据的缓存,在请求到达时候,先判断缓存中是否有对应的数据,没有数据时候再请求到数据库中,然后将数据同步到Redis中,供下一次的请求到达时候,能够在数据不更改时候直接请求到Redis缓存,来减轻数据库的压力,例如对于某明星的具体个人信息,可以将其存取在缓存中,对于此类数据不需要每次都去请求数据库,可以将对数据库的访问留给跟紧急的数据。
  2. 在秒杀场景下,通过进行设置,将商品的信息预先加载到缓存中,通过异步加载的方式,先将数据库中商品的剩余数目加载出来,展示到页面上,同时也能够防止超卖的情况出现。
  3. 可以进行对整个页面的预先加载和缓存到Redis中,在用户进行访问时候,先将页面整体信息加载出来,然后加载数据。

数据类型与各自使用场景

数据类型

你只要说你看过Redis,或者是用过Redis,面试官一般都是问这个问题来检测你是只会数据的SetGet,还是对Redis的数据都有所了解与学习,所以在这个问题尽管看起来很简单,将有几种数据结构回答出来,然后各自的使用场景举例出来,但是要回答具体且对于有些特殊数据类型的底层实现进行了解和阐述还是有一定难度的,所以对于这个问题要重视起来。

首先是五种的数据类型: 包括StringListSetZsetHash。下面是具体情况的具体操作。

数据类型 底层的数据类型 可以存储的值 可以进行的操作 使用在哪些场景下面
String SDS(后续讲解) 字符串,整数,浮点数 对字符串或者其中的一部分进行系类的操作处理 使用最为频繁,一般就是用作简单的键值对的缓存处理作为key值1. 可以用于保存单个字符串或是JSON字符串类型。2. 因为string类型是二进制安全的所以可以把一个图片文件的内容 作为字符串来存储。3. 计算器进行使用时候,对微博数,粉丝数目进行增和减。4. increment 本身就具有原子操作的特性。
List 压缩列表 列表 1. 从两端压入或者弹出元素。2. 对单个或者多个元素进行修建,只保留一个返回内的元素 存储一些列表类型的数据结构。1. 消息队列 可以使用reids的lpush 与 brpop 来实现阻塞队列,保证负载均衡与高可用。2. 文章列表,每个用户都有数据自己的文章列表,需要分页展示文章列表,使用list 不但有序 还可以支持按照索引范围获取元素。最新消息排行等。
Set insert 无序不重复集合 添加、获取、移除单个元素检查一个元素是否存在于集合中计算交集、并集、差集从集合里面随机获取元素 1, 对于两个集合之间的数据进行交集,并集差集运算等。 2. 方便实现对于共同好友的采集,共同关注,二度好友等,对于以上说的集合操作,还可以使用不同的命令将结果返回给客户端或则是存放在一个新的集合里面。 3. 利用唯一性, 统计访问网站的所有独立IP信息。
Hash 压缩列表 键值对集合 添加、获取、移除单个键值对获取所有键值对检查某个键是否存在 1. 用于存储一个对象2. 存储用户用户的具体信息,年龄,生日等数据
Zset 跳表(后续讲解) 有序不重复集合 添加、获取、删除元素根据分值范围或者成员来获取元素计算一个键的排名 1.排行榜,比如在进行文章发布时候,可以将其发布时间作为score进行存储。这样时候获取时候就是自动按照时间排序好。2 可以在进行班级成绩排序时候,不需要再进行排序函数的排序,而是将学号作为value 将成绩作为score,这样就是自然的为我们排好序。3 进行权重的权衡 例如对于 微博热搜榜等

所以综上所述,在回答此问题时候,先说明具体的五种数据类型,也可以说出比较有特点的String和Zset的底层数据结构,然后表明具体都有什么特点最后再说明具体的使用的位置

String:

最简单的键值对的存储的键值,底层采用到sds实现,提高使用的效率,主要用在一些单点的数据上。

List:

有序的列表,对于文章的展示,或者是说国家的展示和省份的存储,利用其有序的特点。

Hash:

主要是用在对象的存储上,存储商品的信息,个人的具体住址,电话等。

Set:

无序的集合,主要使用在一些交集的查找,有哪些的共同好友,或者说是并集的使用,查询共同的关注,共同的兴趣爱好等。

Zset:

有序的集合,底层采用跳表的实现方式,拥有和set功能的功能的同时还能够及时的进行排序处理,或者说是在使用的时候,就可以利用其有序的特点进行省略排序的步骤

事务

对于事务来说,是数据库都不能够绕开的点,但是不同于MySQL中事务特点,对于Redis中的事务确实截然不同的。

Redis中的事务是什么样子

对于Redis中的事务来说:所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。

与其他事务一样也是一个原子操作:事务中的命令要么全部被执行,要么全部都不执行。

如何实现

在Redis中通过几个特殊的命令来实现事务,分别是MULTIEXECWATCHDISCARD,在事务执行的过程中,能够执行多条指令,但是一个事务中所有命令都会被序列化。在事务执行过程,会按照顺序串行化执行队列中的命令,其他客户端提交的命令请求不会插入到事务执行命令序列中。所以总结来说就是对于在Redis中的事务是顺序执行下去的一个队列命令。

实现的过程

首先来具体了解一下每条语句所对应的含义:

MULTI: 表示事务的开始,在redis中执行这条语句以后,表示事务的开启,这个时候,所输入的命令并不会立马执行下去,相反,在未出现EXEC特殊字符时候,所有命令的执行都会进入一个队列中。

EXEC:表示对进入到队列的语句进行一个执行操作,执行的是先进先出的原则。

WATCH: 表示监听,可以监听一个或多个健,是一个乐观锁,一旦其中有一个键被修改(或删除),之后的事务就不会执行,监控一直持续到EXEC命令

DISCARD: 表示清空事务队列,前面我们提到了事务在未被执行的过程中,都会进入到一个队列中,此条操作就会情况事务队列,并放弃执行事务。

所以执行的三个阶段:

  1. 事务开始 MULTI
  2. 命令入队
  3. 事务执行 EXEC

事务执行过程中,如果服务端收到有EXEC、DISCARD、WATCH、MULTI之外的请求,将会把请求放入队列中排队,如果收到以上的请求,就会跳出继续进入队列,进行执行相关联的语句。

遇到问题时候

  1. redis 不支持回滚,“Redis 在事务失败时不进行回滚,而是继续执行余下的命令”, 所以 Redis 的内部可以保持简单且快速。
  2. 如果在一个事务中的命令出现错误,那么所有的命令都不会执行
  3. 如果在一个事务中出现运行错误,那么正确的命令会被执行

ACID

原子性(Atomicity)
原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。

一致性(Consistency)
事务前后数据的完整性必须保持一致。

隔离性(Isolation)
多个事务并发执行时,一个事务的执行不应影响其他事务的执行

持久性(Durability)
持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响

具有的特性

尽管Redis的事务也叫做事务,但是Redis的事务总是具有ACID中的一致性和隔离性,其他特性是不支持的。当服务器运行在AOF持久化模式下,并且appendfsync选项的值为always时,事务也具有持久性。

Redis持久化的两种方法

对于这个问题在面试的情况也是切身经历过,对于这个问题考察还是蛮有深度的,因为不仅仅是死死记住就行,需要自己切实理解其中的缘由与原理,因为这个题目衍生出来的问题比较多,所以只有自己全都是理解,才能够做到在面试时候不会被卡住:这部分想要具体详细了解可以参看《Redis设计与实现》。

什么是

Redis是一个支持持久化的内存数据库,通过持久化可以把在内存中的数据同步到硬盘上,来保证数据的持久化,当Redis在重启时候,可以通过加载硬盘文件重新加载数据到内存中,达到数据恢复的目的:

RDB

是Redis默认的持久化方法,按照一定的时间周期策略把位于内存中的数据保存为RDB文件(是一个二进制的文件)有两个命令可以进行RDB文件的生成:savaBGsave在执行save命令时候会阻塞Redis服务器进程,在执行过程中,Redis服务器不能够处理任何其他的请求。但是BGsave不同的是,在执行时候会派生出一个子进程由子进程完成RDB文件的创建,服务器父进程继续完成其他的响应。 bgrewriteaof
执行时候状态:

在BGSAVE命令执行期间,客户端发送的SAVE命令会被服务器拒绝,服务器禁止SAVE命令和BGSAVE命令同时执行是为了避免父进程(服务器进程)和子进程同时执行两个rdbSave调用,防止产生竞争条件。

其次,在BGSAVE命令执行期间,客户端发送的BGSAVE命令会被服务器拒绝,因为同时执行两个BGSAVE命令也会产生竞争条件。最后,BGREWRITEAOF和BGSAVE两个命令不能同时执行:

❑如果BGSAVE命令正在执行,那么客户端发送的BGREWRITEAOF命令会被延迟到BGSAVE命令执行完毕之后执行。

❑如果BGREWRITEAOF命令正在执行,那么客户端发送的BGSAVE命令会被服务器拒绝。因为BGREWRITEAOF和BGSAVE两个命令的实际工作都由子进程执行,所以这两个命令在操作方面并没有什么冲突的地方,不能同时执行它们只是一个性能方面的考虑——并发出两个子进程,并且这两个子进程都同时执行大量的磁盘写入操作,就很容易导致问题的出现。

优缺点
优点

1、只有一个文件 dump.rdb,方便持久化。
2、容灾性好,一个文件可以保存到安全的磁盘。
3、性能最大化,fork 子进程来完成写操作,让主进程继续处理命令,所以是 IO 最大化。使用单独子进程来进行持久化,主进程不会进行任何 IO 操作,保证了 redis 的高性能
4.相对于数据集大时,比 AOF 的启动效率更高。

缺点

1.是RDB是生产快照文件的 五分钟会生成一个快照文件,但是若是在这五分钟内出现了故障就会导致 数据的丢失会丢失五分钟之内的数据, 对于 AOF来说 最多 丢失一秒的数据

  1. 在生成数据快照的时候 如果文件很大 ,客户端可能会暂停执行几毫秒 此时若是正好在做秒杀活动的时候 fork一个子进程去生成一个大的快照 就会出现问题。

AOF

AOF持久化是通过保存redis服务器所指向的写命令来记录数据库状态。通过Write函数追加到文件的最后,当redis在重启时候会通过重新执行文件中保存的写命令来再内存中重建整个数据库内容。当两个同时开启时候,优先选择AOF进行数据库的恢复。对于 AOF来说是追加的方式,所以没有磁盘的寻址开销 会更快,像 mysql中 binlog。

优缺点
优点

1、数据安全,aof 持久化可以配置 appendfsync 属性,有 always,每进行一次 命令操作就记录到 aof 文件中一次。
2、通过 append 模式写文件,即使中途服务器宕机,可以通过 redis-check-aof 工具解决数据一致性问题。
3、AOF 机制的 rewrite 模式。AOF 文件没被 rewrite 之前(文件过大时会对命令 进行合并重写),可以删除其中的某些命令(比如误操作的 flushall))

缺点

一样的数据 时候 AOF 文件比 RDB 还要大,在AOF开启以后 Reids 支持写入的 APS会比 RDB支持下的要低 异步刷新一次日志 fsync 。

注意
AOF的日志是通过一个叫非常可读的方式记录的,这样的特性就适合做灾难性数据误删除的紧急恢复了,比如公司的实习生通过flushall清空了所有的数据,只要这个时候后台重写还没发生,你马上拷贝一份AOF

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 24
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 24
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值