首页
>教学工作>资源下载

MySQL+MongDB+Redis数据库知识问答

发布日期:2022-07-16信息来源:计算中心访问次数:字号:[ ]

Q:

SQL 的 select 语句完整的执行顺序?

1、from 子句组装来自不同数据源的数据;

2、where 子句基于指定的条件对记录行进行筛选;

3、group by 子句将数据划分为多个分组;

4、使用聚集函数进行计算;

5、使用 having 子句筛选分组;

6、计算所有的表达式;

7、select 的字段;

8、使用 order by 对结果集进行排序。

Q:

 左连接和右连接的区别?

外连接:

左连接(左外连接):以左表作为基准进行查询,左表数据会全部显示出来,右表如果和左表匹配的数据则显示相应字段的数据,如果不匹配则显示为 null。

右连接(右外连接):以右表作为基准进行查询,右表数据会全部显示出来,左表如果和右表匹配的数据则显示相应字段的数据,如果不匹配则显示为 null。

全连接:

先以左表进行左外连接,再以右表进行右外连接

内连接:

显示表之间有连接匹配的所有行。

Q:

什么是sql注入?如何防止sql注入?

sql注入

通过在 Web 表单中输入(恶意)SQL 语句得到一个存在安全漏洞的网站上的数据库,而不是按照设计者意图去执行 SQL 语句。

举例:当执行的 sql 为 select * from user where username = "admin" or "a"="a"时,sql 语句恒成立,参数 admin 毫无意义。

防止 sql 注入的方式:

预编译语句:如,select * from user where username = ?,sql 语句语义不会发生改变,sql 语句中变量用?表示,即使传递参数时为"admin or 'a'= 'a'",也会把这整体当做一个字符创去查询。

Mybatis 框架中的 mapper 方式中的 # 也能很大程度的防止 sql 注入($无法防止 sql 注入)。

Q:

有哪些sql优化方法?

1、当只要一行数据时使用 limit 1

查询时如果已知会得到一条数据,这种情况下加上 limit 1 会增加性能。因为 mysql 数据库引擎会在找到一条结果停止搜索,而不是继续查询下一条是否符合标准直到所有记录查询完毕。

2、选择正确的数据库引擎

Mysql 中有两个引擎 MyISAM 和 InnoDB,每个引擎有利有弊。

MyISAM 适用于一些大量查询的应用,但对于有大量写功能的应用不是很好。甚至你只需要update 一个字段整个表都会被锁起来。而别的进程就算是读操作也不行要等到当前 update 操作完成之后才能继续进行。另外,MyISAM 对于 select count(*)这类操作是超级快的。

InnoDB 的趋势会是一个非常复杂的存储引擎,对于一些小的应用会比 MyISAM 还慢,但是支持“行锁”,所以在写操作比较多的时候会比较优秀。并且,它支持很多的高级应用,例如:事务。

3、用 not exists 代替 not in

Not exists 用到了连接能够发挥已经建立好的索引的作用,not in 不能使用索引。Not in 是最慢的方式要同每条记录比较,在数据量比较大的操作时不建议使用这种方式。

4、对操作符的优化,尽量不采用不利于索引的操作符

如:in not in is null is not null <>等

某个字段总要拿来搜索,为其建立索引:

Mysql 中使用 alter table 语句来为表中的字段添加索引:alter table 表明 add index (字段名);

Q:

Mysql 存储引擎有哪些?

1.InnoDB 存储引擎

InnoDB 是事务型数据库的首选引擎,支持事务安全表(ACID),支持行锁定和外键,InnoDB 是默认的MySQL引擎。

2.MyISAM 存储引擎

MyISAM 基于 ISAM 存储引擎,并对其进行扩展。它是在 Web、数据仓储和其他应用环境下最常使用的存储引擎之一。MyISAM 拥有较高的插入、查询速度,但不支持事物。

3.MEMORY 存储引擎

MEMORY 存储引擎将表中的数据存储到内存中,未查询和引用其他表数据提供快速访问。

4.NDB 存储引擎

DB 存储引擎是一个集群存储引擎,类似于 Oracle 的 RAC,但它是 Share Nothing 的架构,因此能提供更高级别的高可用性和可扩展性。NDB 的特点是数据全部放在内存中,因此通过主键查找非常快。

关于 NDB,有一个问题需要注意,它的连接(join)操作是在 MySQL 数据库层完成,不是在存储引擎层完成,这意味着,复杂的 join 操作需要巨大的网络开销,查询速度会很慢。

5.Memory (Heap) 存储引擎

Memory 存储引擎(之前称为 Heap)将表中数据存放在内存中,如果数据库重启或崩溃,数据丢失,因此它非常适合存储临时数据。

6.Archive 存储引擎

正如其名称所示,Archive 非常适合存储归档数据,如日志信息。它只支持 INSERT 和 SELECT 操作,其设计的主要目的是提供高速的插入和压缩功能。

7.Federated 存储引擎

Federated 存储引擎不存放数据,它至少指向一台远程 MySQL 数据库服务器上的表,非常类似于 Oracle 的透明网关。

8.Maria 存储引擎

Maria 存储引擎是新开发的引擎,其设计目标是用来取代原有的 MyISAM 存储引擎,从而成为 MySQL 默认的存储引擎。

上述引擎中,InnoDB 是事务安全的存储引擎,设计上借鉴了很多 Oracle 的架构思想,一般而言,在 OLTP应用中,InnoDB 应该作为核心应用表的首先存储引擎。InnoDB 是由第三方的 Innobase Oy 公司开发,现已被Oracle 收购,创始人是 Heikki Tuuri,芬兰赫尔辛基人,和著名的 Linux 创始人 Linus 是校友。

Q:

事务的四大特征是什么?

数据库事务 transanction 正确执行的四个基本要素。ACID,原子性(Atomicity)、一致性(Correspondence)、隔离性(Isolation)、持久性(Durability)。

原子性:整个事务中的所有操作,要么全部完成,要么全部不完成,不可能停滞在中间某个环节。事务在执

行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。

一致性:在事务开始之前和事务结束以后,数据库的完整性约束没有被破坏。

隔离性:隔离状态执行事务,使它们好像是系统在给定时间内执行的唯一操作。如果有两个事务,运行在相

同的时间内,执行 相同的功能,事务的隔离性将确保每一事务在系统中认为只有该事务在使用系统。这种属性有时称为串行化,为了防止事务操作间的混淆, 必须串行化或序列化请 求,使得在同一时间仅有一个请求用于同一数据。

持久性:在事务完成以后,该事务所对数据库所作的更改便持久的保存在数据库之中,并不会被回滚。

Q:

MySQL 索引的“使用”要注意什么?

1.避免在 WHERE 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描。优化器将无法通过索引来确定将要命中的行数,因此需要搜索该表的所有行。

2.避免在 WHERE 子句中使用 OR 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描,如:SELECT id FROM t WHERE num = 10 OR num = 20 。

3.避免在 WHERE 子句中对字段进行表达式操作,这将导致引擎放弃使用索引而进行全表扫描。

4.避免在 WHERE 子句中对字段进行函数操作,这将导致引擎放弃使用索引而进行全表扫描。

5.LIKE 查询,% 不能在前,因为无法使用索引。如果需要模糊匹配,可以使用全文索引。

Q:

为什么mysql建议使用自增主键?

1、如果我们定义了主键(PRIMARY KEY),那么InnoDB会选择主键作为聚集索引。

如果没有显式定义主键,则InnoDB会选择第一个不包含有NULL值的唯一索引作为主键索引。

如果也没有这样的唯一索引,则InnoDB会选择内置6字节长的ROWID作为隐含的聚集索引(ROWID随着行记录的写入而主键递增,这个ROWID不像ORACLE的ROWID那样可引用,是隐含的)。

2、数据记录本身被存于主索引(一颗B+Tree)的叶子节点上,这就要求同一个叶子节点内(大小为一个内存页或磁盘页)的各条数据记录按主键顺序存放。

因此每当有一条新的记录插入时,MySQL会根据其主键将其插入适当的节点和位置,如果页面达到装载因子(InnoDB默认为15/16),则开辟一个新的页(节点)

3、如果表使用自增主键,那么每次插入新的记录,记录就会顺序添加到当前索引节点的后续位置,当一页写满,就会自动开辟一个新的页。

4、如果使用非自增主键(如果身份证号或学号等),由于每次插入主键的值近似于随机,因此每次新纪录都要被插到现有索引页得中间某个位置,此时MySQL不得不为了将新记录插到合适位置而移动数据,甚至目标页面可能已经被回写到磁盘上而从缓存中清掉,此时又要从磁盘上读回来,这增加了很多开销,同时频繁的移动、分页操作造成了大量的碎片,得到了不够紧凑的索引结构,后续不得不通过OPTIMIZE TABLE来重建表并优化填充页面。

Q:

 mysql rr级别如何解决幻读问题?

该隔离级别是 MySQL 默认的隔离级别,在同一个事务里,select 的结果是事务开始时时间点的状态,因此,同样的 select 操作读到的结果会是一致的,但是,会有幻读现象。

MySQL 的 InnoDB 引擎可以通过 next-key locks 机制来避免幻读。InnoDB 存储引擎使用三种行锁的算法用来满足相关事务隔离级别的要求:

Record Locks

该锁为索引记录上的锁,如果表中没有定义索引,InnoDB 会默认为该表创建一个隐藏的聚簇索引,并使用该索引锁定记录。

Gap Locks

该锁会锁定一个范围,但是不括记录本身。可以通过修改隔离级别为 READ COMMITTED 或者配置 innodb_locks_unsafe_for_binlog 参数为 ON。

Next-key Locks

该锁就是 Record Locks 和 Gap Locks 的组合,即锁定一个范围并且锁定该记录本身。InnoDB 使用 Next-key Locks 解决幻读问题。需要注意的是,如果索引有唯一属性,则 InnnoDB 会自动将 Next-key Locks 降级为 Record Locks。

举例:如果一个索引有 1, 3, 5 三个值,则该索引锁定的区间为 (-∞,1], (1,3], (3,5], (5,+ ∞)。

 

Q:

MySQL 主从复制的流程是怎么样的?

1、Master 上面的 binlog dump 线程,该线程负责将 master 的 binlog event 传到 slave。

2、Slave 上面的 IO 线程,该线程负责接收 Master 传过来的 binlog,并写入 relay log 。

3、Slave 上面的 SQL 线程,该线程负责读取 relay log 并执行。

4、如果是多线程复制,无论是 5.6 库级别的假多线程还是 MariaDB 或者 5.7 的真正的多线程复制, SQL 线程只做 coordinator ,只负责把 relay log 中的 binlog 读出来然后交给 worker 线程, woker 线程负责具体 binlog event 的执行。

Q:

 Mysql 中 MyISAM 和 InnoDB 的区别有哪些?

1、InnoDB支持事务,MyISAM不支持

对于InnoDB每一条SQL语言都默认封装成事务,自动提交,这样会影响速度,所以最好把多条SQL语言放在begin和commit之间,组成一个事务;

2、InnoDB支持外键,而MyISAM不支持。对一个包含外键的InnoDB表转为MYISAM会失败;

3、InnoDB是聚集索引,数据文件是和索引绑在一起的,必须要有主键,通过主键索引效率很高。

但是辅助索引需要两次查询,先查询到主键,然后再通过主键查询到数据。因此主键不应该过大,因为主键太大,其他索引也都会很大。

而MyISAM是非聚集索引,数据文件是分离的,索引保存的是数据文件的指针。主键索引和辅助索引是独立的。

4、InnoDB不保存表的具体行数,执行select count(*) from table时需要全表扫描。而MyISAM用一个变量保存了整个表的行数,执行上述语句时只需要读出该变量即可,速度很快;

5、Innodb不支持全文索引,而MyISAM支持全文索引,查询效率上MyISAM要高;

表并优化填充页面。

Q:

 mysql事务隔离级别?

Read Uncommitted(读取未提交内容)

在该隔离级别,所有事务都可以看到其他未提交事务的执行结果。本隔离级别很少用于实际应用,因为它的性能也不比其他级别好多少。读取未提交的数据,也被称之为脏读(Dirty Read)。

Read Committed(读取提交内容)

这是大多数数据库系统的默认隔离级别(但不是MySQL默认的)。它满足了隔离的简单定义:一个事务只能看见已经提交事务所做的改变。这种隔离级别 也支持所谓的不可重复读(Nonrepeatable Read),因为同一事务的其他实例在该实例处理其间可能会有新的commit,所以同一select可能返回不同结果。

Repeatable Read(可重读)

这是MySQL的默认事务隔离级别,它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。不过理论上,这会导致另一个棘手的问题:幻读 (Phantom Read)。简单的说,幻读指当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的“幻影” 行。

InnoDB和Falcon存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)机制解决了该问题。

Serializable(可串行化)

这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争。

Q:

 MVCC的流程?

mvcc根据undo log来实现

RR级别下,事务中的第一个SELECT请求才开始创建read view;

RC级别下,事务中每次SELECT请求都会重新创建read view;

ReadView 中是当前活跃的事务 ID 列表,称之为 m_ids,其中最小值为 up_limit_id,最大值为 low_limit_id,事务 ID 是事务开启时 InnoDB 分配的,其大小决定了事务开启的先后顺序,因此我们可以通过 ID 的大小关系来决定版本记录的可见性,具体判断流程如下:

如果被访问版本的 trx_id 小于 m_ids 中的最小值 up_limit_id,说明生成该版本的事务在 ReadView 生成前就已经提交了,所以该版本可以被当前事务访问。

如果被访问版本的 trx_id 大于 m_ids 列表中的最大值 low_limit_id,说明生成该版本的事务在生成 ReadView 后才生成,所以该版本不可以被当前事务访问。需要根据 Undo Log 链找到前一个版本,然后根据该版本的 DB_TRX_ID 重新判断可见性。

如果被访问版本的 trx_id 属性值在 m_ids 列表中最大值和最小值之间(包含),那就需要判断一下 trx_id 的值是不是在 m_ids 列表中。如果在,说明创建 ReadView 时生成该版本所属事务还是活跃的,因此该版本不可以被访问,需要查找 Undo Log 链得到上一个版本,然后根据该版本的 DB_TRX_ID 再从头计算一次可见性;如果不在,说明创建 ReadView 时生成该版本的事务已经被提交,该版本可以被访问。

此时经过一系列判断我们已经得到了这条记录相对 ReadView 来说的可见结果。此时,如果这条记录的 delete_flag 为 true,说明这条记录已被删除,不返回。否则说明此记录可以安全返回给客户端。

 

Q:

 mysql什么时候会出现数据页预读?

1、有一个参数是innodb_read_ahead_threshold,他的默认值是56,意思就是如果顺序的访问了一个区里的多个数据页,访问的数据页的数量超过了这个阈值,此时就会触发预读机制,把下一个相邻区中的所有数据页都加载到缓存里去

2、如果Buffer Pool里缓存了一个区里的13个连续的数据页,而且这些数据页都是比较频繁会被访问的,此时就会 直接触发预读机制,把这个区里的其他的数据页都加载到缓存里去 这个机制是通过参数innodb_random_read_ahead来控制的,他默认是OFF,也就是这个规则是关闭的

3、全表扫描

Q:

 mysql有哪些binlog录入格式?

statement,statement模式下,记录单元为语句。即每一个sql造成的影响会记录。由于sql的执行是有上下文的,因此在保存的时候需要保存相关的信息,同时还有一些使用了函数之类的语句无法被记录复制。

row,row级别下,记录单元为每一行的改动,基本是可以全部记下来但是由于很多操作,会导致大量行的改动(比如alter table),因此这种模式的文件保存的信息太多,日志量太大。

mixed,一种折中的方案,普通操作使用statement记录,当无法使用statement的时候使用row。

Q:

什么是MongoDB?

MongoDB是一个文档数据库,提供好的性能,领先的非关系型数据库。采用BSON存储文档数据。BSON()是一种类json的一种二进制形式的存储格式,简称Binary JSON. 相对于json多了date类型和二进制数组。

Q:

关系型数据库和非关系性数据库的区别?

关系型数据库

优点:

数据之间有关系,进行数据的增删改查的时候是非常方便的

关系型数据库是有事务操作的,保证数据的完整性和一致性。

缺点:

因为数据和数据是有关系的,底层是运行了大量的算法,大量算法会降低系统的效率,会降低性能

面对海量数据的增删改查的时候会显的无能为力

海量数据对数据进行维护变得非常的无力

非关系型数据库

优点:

海量数据的增删改查是可以的

海量数据的维护和处理非常轻松

缺点:

数据和数据没有关系,他们之间就是单独存在的

非关系数据库没有关系,没有强大的事务关系,没有保证数据的完整性和安全性

Q:

MongoDB支持哪些数据类型?

String 字符串

Integer 整型数值

Double 双精度浮点值

Boolean 布尔值

Object 用于内嵌文档

Object ID 对象 ID

Arrays 用于将数组或列表或多个值存储为一个键

Min/Max Keys 将一个值与 BSON(二进制的 JSON)元素的最低值和最高值相对比

Code 代码类型

Regular Expression

Q:

什么是命名空间?

mongodb存储bson对象在丛集(collection)中。数据库名字和丛集名字以句点连结起来叫做命名空间(namespace)。

一个集合命名空间又有多个数据域(extent),集合命名空间里存储着集合的元数据,比如集合名称,集合的第一个数据域和最后一个数据域的位置等等。而一个数据域由若干条文档(document)组成,每个数据域都有一个 头部,记录着第一条文档和最后一条文档的为知,以及该数据域的一些元数据。extent之间,document之间通过 双向链表连接。索引的存储数据结构是B树,索引命名空间存储着对B树的根节点的指针。

Q:

MongoDB如何执行事务?

Mongodb没有使用传统的锁或者复杂的带回滚的事务,因为他设计的宗旨是轻量级,快速以及可预计的高性能,可能把它类比成mysql myisam的自动提交模式,通过精简对事务的支持,性能得到了提升,特别是在一个可能会穿过多个服务器的系统里。

Q:

mongoDB会同步刷新数据到磁盘吗?

不会,磁盘写操作默认是延迟执行的,写操作可能在量三秒后到达磁盘,例如,如果一秒内数据库收到一千个对一个对象递增的操作,仅刷新磁盘一次。

Q:

mongoDB使用索引要注意什么?

1、索引很有用,但是它也是有成本的;它占内存,让写入变慢;

2、mongoDB通常在一次查询里使用一个索引,所以多个字段的查询或者排序需要复合索引才能更加高效;

3、复合索引的顺序非常重要

4、在生成环境构建索引往往开销很大,时间也不可以接受,在数据量庞大之前尽量进行查询优化和构建索引;

5、避免昂贵的查询,使用查询分析器记录那些开销很大的查询便于问题排查;

6、通过减少扫描文档数量来优化查询,使用explain对开销大的查询进行分析并优化;

7、索引是用来查询小范围数据的

不适合使用索引的情况:

每次查询都需要返回大部分数据的文档,避免使用索引

写比读多

Q:

MongoDB支持存储过程吗?

MongoDB支持存储过程,它是javascript写的,保存在db.system.js表中。

Q:

分析器在MongoDB中的作用是什么?

MongoDB中包括了一个可以显示数据库中每个操作性能特点的数据库分析器。通过这个分析器你可以找到比预期慢的查询(或写操作);利用这一信息,可以确定是否需要添加索引等。

Q:

如果用户移除对象的属性,该属性是否从存储层中删除?

是的,用户移除属性然后对象会重新保存(re-save())。

Q:

MongoDB允许空值null吗?

对于对象成员而言,允许。

但是用户不能够添加空值(null)到数据库丛集(collection),因为空值不是对象。但是用户能够添加空对象{}。

Q:

mongoDB 主要使用在什么场景?

MongoDB 的应用已经渗透到各个领域,比如游戏、物流、电商、内容管理、社交、物联网、视频直播等,以下是几个实际的应用案例:

游戏场景,使用 MongoDB 存储游戏用户信息,用户的装备、积分等直接以内嵌文档的形式存储,方便查询、更新

物流场景,使用 MongoDB 存储订单信息,订单状态在运送过程中会不断更新,以MongoDB 内嵌数组的形式来存储,一次查询就能将订单所有的变更读取出来。

社交场景,使用 MongoDB 存储存储用户信息,以及用户发表的朋友圈信息,通过地理位置索引实现附近的人、地点等功能

物联网场景,使用 MongoDB 存储所有接入的智能设备信息,以及设备汇报的日志信息,并对这些信息进行多维度的分析

视频直播,使用 MongoDB 存储用户信息、礼物信息等

Q:

redis的数据类型有哪些?

String

常规的set/get操作,value可以是String也可以是数字。

应用:一般做一些复杂的计数功能的缓存。

hash

这里value存放的是结构化的对象,比较方便的就是操作其中的某个字段。

应用:单点登录,就是用这种数据结构存储用户信息,以cookieId作为key,设置30分钟为缓存过期时间,能很好的模拟出类似session的效果。

list

List的数据结构

应用:可以做简单的消息队列的功能。另外,可以利用lrange命令,做基于redis的分页功能,性能极佳,用户体验好。生产者和消费者的场景,LIST可以很好的完成排队,先进先出的原则。

set

因为set堆放的是一堆不重复值的集合。

应用:可以做全局去重的功能。为什么不用JVM自带的Set进行去重?因为我们的系统一般都是集群部署,使用JVM自带的Set,比较麻烦,难道为了一个做一个全局去重,再起一个公共服务,太麻烦了。另外,就是利用交集、并集、差集等操作,可以计算共同喜好,全部的喜好,自己独有的喜好等功能。

sorted set

sorted set多了一个权重参数score,集合中的元素能够按score进行排列。

应用:可以做排行榜应用,取TOP N操作。

Q:

Redis 内部结构有哪些?

dict

本质上是为了解决算法中的查找问题(Searching)是一个用于维护key和value映射关系的数据结构,与很多语言中的Map或dictionary类似。本质上是为了解决算法中的查找问题(Searching)。

sds

sds就等同于char * 它可以存储任意二进制数据,不能像C语言字符串那样以字符’\0’来标识字符串的结束,因此它必然有个长度字段。

skiplist  跳跃表

跳表是一种实现起来很简单,单层多指针的链表,它查找效率很高,堪比优化过的二叉平衡树,且比平衡树的实现。

ziplist 压缩表

ziplist是一个编码后的列表,是由一系列特殊编码的连续内存块组成的顺序型数据结构。

Q:

Memcache 与 Redis 的区别都有哪些?

存储方式不同:

Memcache 是把数据全部存在内存中,数据不能超过内存的大小,断电后数据库会挂掉。

Redis 有部分存在硬盘上,这样能保证数据的持久性。

数据支持的类型不同:

memcahe 对数据类型支持相对简单

redis 有复杂的数据类型。

使用底层模型不同:

它们之间底层实现方式 以及与客户端之间通信的应用协议不一样。

Redis 直接自己构建了 VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求。

支持的 value 大小不一样:

redis 最大可以达到 1GB

而 memcache 只有 1MB

Q:

为什么 redis 需要把所有数据放到内存中?

Redis 为了达到最快的读写速度将数据都读到内存中,并通过异步的方式将数据写入磁盘。所以 redis 具有快速和数据持久化的特征。如果不将数据放在内存中,磁盘 I/O 速度为严重影响 redis 的性能。在内存越来越便宜的今天,redis 将会越来越受欢迎。如果设置了最大使用的内存,则数据已有记录数达到内存限值后不能继续插入新值。

Q:

Redis 如何进行持久化?

Redis是一个支持持久化的内存数据库,通过持久化机制把内存中的数据同步到硬盘文件来保证数据持久化。当Redis重启后通过把硬盘文件重新加载到内存,就能达到恢复数据的目的。

实现:

单独创建fork()一个子进程,将当前父进程的数据库数据复制到子进程的内存中,然后由子进程写入到临时文件中,持久化的过程结束了,再用这个临时文件替换上次的快照文件,然后子进程退出,内存释放。

方式:

RDB是Redis默认的持久化方式。按照一定的时间周期策略把内存的数据以快照的形式保存到硬盘的二进制文件。即Snapshot快照存储,对应产生的数据文件为dump.rdb,通过配置文件中的save参数来定义快照的周期。( 快照可以是其所表示的数据的一个副本,也可以是数据的一个复制品。)

AOF:Redis会将每一个收到的写命令都通过Write函数追加到文件最后,类似于MySQL的binlog。当Redis重启是会通过重新执行文件中保存的写命令来在内存中重建整个数据库的内容。

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

Q:

RDB和AOF的优缺点有哪些?

RDB持久化

优点:RDB文件紧凑,体积小,网络传输快,适合全量复制;恢复速度比AOF快很多。当然,与AOF相比,RDB最重要的优点之一是对性能的影响相对较小。

缺点:RDB文件的致命缺点在于其数据快照的持久化方式决定了必然做不到实时持久化,而在数据越来越重要的今天,数据的大量丢失很多时候是无法接受的,因此AOF持久化成为主流。此外,RDB文件需要满足特定格式,兼容性差(如老版本的Redis不兼容新版本的RDB文件)。

AOF持久化

优点:支持秒级持久化、兼容性好

缺点:文件大、恢复速度慢、对性能影响大。

Q:

什么是缓存穿透?如何避免?

缓存穿透

一般的缓存系统,都是按照key去缓存查询,如果不存在对应的value,就应该去后端系统查找(比如DB)。一些恶意的请求会故意查询不存在的key,请求量很大,就会对后端系统造成很大的压力,就叫做缓存穿透。

避免

对查询结果为空的情况也进行缓存,缓存时间设置短一点,或者该key对应的数据insert了之后清理缓存。

对一定不存在的key进行过滤。可以把所有的可能存在的key放到一个大的Bitmap中,查询时通过该bitmap过滤。

Q:

什么是缓存雪崩?何如避免?

缓存雪崩

当缓存服务器重启或者大量缓存集中在某一个时间段失效,这样在失效的时候,会给后端系统带来很大压力。导致系统崩溃。

避免

在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待。

做二级缓存,A1为原始缓存,A2为拷贝缓存;A1失效时,可以访问A2,A1缓存失效时间设置为短期,A2设置为长期

不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀。

Q:

redis的淘汰策略有哪些?

noeviction:不删除策略,达到最大内存限制时,如果需要更多内存,直接返回错误信息。大多数写命令都会导致占用更多的内存(有极少数会例外)

allkeys-lru:所有key通用;优先删除最近最少使用(less recently used ,LRU) 的 key。

volatile-lru:只限于设置了 expire 的部分;优先删除最近最少使用(less recently used ,LRU) 的 key。

allkeys-random:所有key通用;随机删除一部分 key。

volatile-random:只限于设置了 expire 的部分;随机删除一部分 key。

volatile-ttl:只限于设置了 expire 的部分;优先删除剩余时间(time to live,TTL) 短的key。

Q:

Redis是单线程的,但为什么这么快?

1、完全基于内存,绝大部分请求是纯粹的内存操作,非常快速。数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1);

2、数据结构简单,对数据操作也简单,Redis中的数据结构是专门进行设计的;

3、采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗;

4、使用多路I/O复用模型,非阻塞IO;这里“多路”指的是多个网络连接,“复用”指的是复用同一个线程

5、使用底层模型不同,它们之间底层实现方式以及与客户端之间通信的应用协议不一样,Redis直接自己构建了VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求;

Q:

Redis的内存分为哪些?

数据

作为数据库,数据是最主要的部分;这部分占用的内存会统计在used_memory中。

进程本身运行需要的内存

Redis主进程本身运行肯定需要占用内存,如代码、常量池等等;这部分内存大约几兆,在大多数生产环境中与Redis数据占用的内存相比可以忽略。这部分内存不是由jemalloc分配,因此不会统计在used_memory中。

缓冲内存

缓冲内存包括客户端缓冲区、复制积压缓冲区、AOF缓冲区等;

客户端缓冲存储客户端连接的输入输出缓冲;

复制积压缓冲用于部分复制功能;

AOF缓冲区用于在进行AOF重写时,保存最近的写入命令。

在了解相应功能之前,不需要知道这些缓冲的细节;这部分内存由jemalloc分配,因此会统计在used_memory中。

内存碎片

内存碎片是Redis在分配、回收物理内存过程中产生的。例如,如果对数据的更改频繁,而且数据之间的大小相差很大,可能导致redis释放的空间在物理内存中并没有释放,但redis又无法有效利用,这就形成了内存碎片。内存碎片不会统计在used_memory中。

Q:

说说Redis事务?

Redis事务功能是通过MULTI、EXEC、DISCARD和WATCH 四个原语实现的

Redis会将一个事务中的所有命令序列化,然后按顺序执行。

redis 不支持回滚“Redis 在事务失败时不进行回滚,而是继续执行余下的命令”, 所以 Redis 的内部可以保持简单且快速。

如果在一个事务中的命令出现错误,那么所有的命令都不会执行;

如果在一个事务中出现运行错误,那么正确的命令会被执行。

命令

MULTI命令用于开启一个事务,它总是返回OK。MULTI执行之后,客户端可以继续向服务器发送任意多条命令,这些命令不会立即被执行,而是被放到一个队列中,当EXEC命令被调用时,所有队列中的命令才会被执行。

EXEC:执行所有事务块内的命令。返回事务块内所有命令的返回值,按命令执行的先后顺序排列。当操作被打断时,返回空值 nil 。

DISCARD:通过调用DISCARD,客户端可以清空事务队列,并放弃执行事务, 并且客户端会从事务状态中退出。

WATCH 命令可以为 Redis 事务提供 check-and-set (CAS)行为。可以监控一个或多个键,一旦其中有一个键被修改(或删除),之后的事务就不会执行,监控一直持续到EXEC命令。

Q:

Redis 常见的性能问题都有哪些?如何解决?

1.Master 写内存快照,save 命令调度 rdbSave 函数,会阻塞主线程的工作,当快照比较大时对性能影响是非常大的,会间断性暂停服务,所以 Master 最好不要写内存快照。

2.Master AOF 持久化,如果不重写 AOF 文件,这个持久化方式对性能的影响是最小的,但是 AOF 文件会不断增大,AOF 文件过大会影响 Master 重启的恢复速度。

Master 最好不要做任何持久化工作,包括内存快照和 AOF。

日志文件,特别是不要启用内存快照做持久化,如果数据比较关键,某个 Slave 开启 AOF 备份数据,策略为每秒同步一次。

3.Master 调用 BGREWRITEAOF 重写 AOF 文件,AOF 在重写的时候会占大量的 CPU 和内存资源,导致服务 load 过高,出现短暂服务暂停现象。

4.Redis 主从复制的性能问题,为了主从复制的速度和连接的稳定性,Slave 和 Master 最好在同一个局域网内

Q:

Redis 适合的场景有哪些?

会话缓存(Session Cache)

全页缓存(FPC)

队列

排行榜/计数器

发布/订阅