全网最全Redis讲解(2W字总结免费送)

基础

什么是Redis

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

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

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

为什么要使用Redis

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

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

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

缓存提高访问速度

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

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

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

编辑切换为居中

添加图片注释,不超过 140 字(可选)

缓存支持高并发

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

编辑切换为居中

添加图片注释,不超过 140 字(可选)

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

  1. 用作对MySQL数据库中数据的缓存,在请求到达时候,先判断缓存中是否有对应的数据,没有数据时候再请求到数据库中,然后将数据同步到Redis中,供下一次的请求到达时候,能够在数据不更改时候直接请求到Redis缓存,来减轻数据库的压力,例如对于某明星的具体个人信息,可以将其存取在缓存中,对于此类数据不需要每次都去请求数据库,可以将对数据库的访问留给跟紧急的数据。

  2. 在秒杀场景下,通过进行设置,将商品的信息预先加载到缓存中,通过异步加载的方式,先将数据库中商品的剩余数目加载出来,展示到页面上,同时也能够防止超卖的情况出现。

  3. 可以进行对整个页面的预先加载和缓存到Redis中,在用户进行访问时候,先将页面整体信息加载出来,然后加载数据。

数据类型与各自使用场景

数据类型

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

首先是五种的数据类型: 包括String,List,Set,Zset,Hash。下面是具体情况的具体操作。

数据类型

底层的数据类型

可以存储的值

可以进行的操作

使用在哪些场景下面

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

String:

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

List:

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

Hash:

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

Set:

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

Zset:

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

事务

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

Redis中的事务是什么样子

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

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

如何实现

在Redis中通过几个特殊的命令来实现事务,分别是MULTI、EXEC、WATCH,DISCARD,在事务执行的过程中,能够执行多条指令,但是一个事务中所有命令都会被序列化。在事务执行过程,会按照顺序串行化执行队列中的命令,其他客户端提交的命令请求不会插入到事务执行命令序列中。所以总结来说就是对于在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文件的生成:sava 和BGsave。在执行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是生产快照文件的 五分钟会生成一个快照文件,但是若是在这五分钟

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 Python 中使用 Redis 数据库时,可以使用 `hgetall` 命令获取指定哈希表中的所有段和值。具体讲解如下: 1. 连接 Redis 数据库 首先需要使用 Redis 的 Python 客户端连接 Redis 数据库。可以使用 `redis` 模块中的 `Redis` 类来实现: ```python import redis # 创建 Redis 客户端对象 r = redis.Redis(host='localhost', port=6379, db=0) ``` 2. 添加哈希表数据 在获取哈希表数据之前,需要先向 Redis 数据库中添加一些数据。可以使用 `hmset` 命令添加哈希表数据: ```python # 添加哈希表数据 r.hmset('myhash', {'field1': 'value1', 'field2': 'value2', 'field3': 'value3'}) ``` 上述代码中,首先指定哈希表名称为 `myhash`,然后添加了三个段和对应的值。 3. 获取哈希表数据 使用 `hgetall` 命令可以获取指定哈希表中的所有段和值。具体使用方法如下: ```python # 获取指定哈希表中的所有段和值 result = r.hgetall('myhash') print(result) ``` 输出结果为: ``` {b'field1': b'value1', b'field2': b'value2', b'field3': b'value3'} ``` 上述结果中,键名和键值都以符串的形式输出,需要使用 `decode()` 方法将其转换为符串: ```python # 将符串转换为符串 result = {key.decode(): value.decode() for key, value in result.items()} print(result) ``` 输出结果为: ``` {'field1': 'value1', 'field2': 'value2', 'field3': 'value3'} ``` 上述代码中,使用典生成式将符串转换为符串,并将其存储在 `result` 变量中。 总结: `hgetall` 命令可以获取指定哈希表中的所有段和值,使用 Redis 的 Python 客户端可以轻松实现该功能。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值