第五篇:数据存储(Mysql、Redis、MongoDB)

目录

一. MySQL

1. 数据库三大范式是什么?

2. MyISAM和InnoDB存储引擎的区别?

3. 什么是MVCC?有什么作用?怎么实现的? 

4. 什么字段适合作为索引?

5. 索引的结构有哪些?

6. 为什么数据库主要使用B+树?B树和B+树有什么区别?

7. hash存储结构和B+树存储结构有什么优劣?

8. B+树的具体实现是什么样的?

9. 联合索引在B+树中怎么存储?

10. 最左匹配原则

11. 百万级的数据怎么删除

12. 什么是数据库事务?事务的四大特性ACID介绍一下

13. 什么是脏读、不可重复读、幻读?

14. 事务的隔离级别?怎么实现的(加了什么锁)?MySQL默认的隔离级别是什么?

15. 数据库的行锁和表锁是怎么实现的?

16.  如何定位sql语句的性能问题?如何解决?

17. 超大分页怎么处理?

18. 怎么排查慢sql?对于慢sql怎么优化?

19. MySQL数据库CPU飙升到500%怎么处理?

20. 千万数据的表,CRUD特别慢,怎么优化?

21. 数据库是怎么进行主从复制的?

22. count(*)、count(1)、count(列名)有什么区别?

23. 频繁的增删数据量某个表,数据库最终数据只有几万或者更少,为什么查询会变慢

24.  mysql执行sql流程?

25. 什么情况下会索引失效?

26. 分库分表的方案?

二. Redis

1. redis有哪些数据类型?

2. redis的适用场景?项目中哪里用过redis?

3. redis为什么快?

4. redis为什么单线程还快?

5. redis的持久化机制是什么?优缺点是什么?

6. redis过期键的删除策略?

7. 有2000万mysql数据,redis只能存储20w数据,怎么保证redis存储的都是热点数据?

8. redis支持事务吗?

9. redis事务的命令有哪些?

10. redis哨兵机制是什么?

11. redis集群模式(redis cluster)的工作原理知道吗?

12. redis是如何进行主从复制的?

13. 缓存异常

14. 如何用redis实现分布式锁?

15. 假设redis中有一亿数据,有10w个前缀都是一样的,如何把他们找出来?

16. 有10万条数据,要插入到redis中,如何操作?

17. 如何使用redis做异步队列?

18. 如何使用redis做延迟队列?

19. redis的回收线程是怎么工作的?

20. redis回收使用的是什么算法?

三.MongoDB

1. 你们项目中MongoDB中存储是什么数据?

2. MySQL和MongoDB和redis的特点、区别、使用场景?


一. MySQL

1. 数据库三大范式是什么?

  • 第一范式:每一列都不可拆分;
  • 第二范式:在第一范式基础上,非主键完全依赖主键,而非依赖主键的一部分;
  • 第三范式:在第二范式基础上,非主键只依赖主键,不依赖其他非主键。

2. MyISAM和InnoDB存储引擎的区别?

  • 从功能上来说,InnoDB支持事务和行级锁,MyISAM不支持事务和行级锁,只支持表级锁;
  • 从索引来说,InnoDB的索引是聚簇索引,MyISAM是非聚簇索引。InnoDB主键索引的叶子节点存放的是行数据,因此用主键查询非常快;非主键索引的叶子节点存放的是主键索引和其他非主键索引,因此索引覆盖查询非常快。MyISAM索引的叶子节点存放的是行数据地址。

什么是存储引擎?

存储引擎定义了如何存储数据、如何为存储的数据建立索引、如何查询更新数据等技术的查询方法。

如何选择存储引擎?

  • 当插入和查询比较多时,且对事务,并发性要求不高时使用MyISAM,因为MyISAM查询比较快。比如博客系统,新闻门户网站。
  • 当需要用到事务,行级锁时,都是用InnoDB存储引擎。

为什么MyISAM查询比InnoDB快?

从功能上来说,InnoDB支持事务,会有一个MVVC(多版本并发控制)比较,会消耗性能,以及行级锁也会有性能开销。

从索引上来说,InnoDB的非聚簇索引查询数据会有一个回表的过程。先从非聚簇索引查到聚簇索引,然后再定位到行数据。而MyISAM直接能用索引定位到行数据。

3. 什么是MVCC?有什么作用?怎么实现的? 

详情讲解链接:https://www.jianshu.com/p/8845ddca3b23

MVCC(Multi-Version Concurrency Control)是多版本并发控制。MVCC能够代替行级锁,并发控制时系统性能消耗更少。

MVCC是用两个隐藏的列和undoLog实现的。两个隐藏的列分别是 当前事务的版本号 和 回滚指针(指向undolog中的版本记录)。

MVCC多版本控制的过程:

事务执行更新操作时,会先给行数据加排它锁,然后把当前数据快照存在undolog中,拷贝完毕后,再修改行数据,并把回滚指针指向undolog中的版本记录。事务执行期间只需要读版本记录即可。

undolog:保存了事务发生前的数据的一个版本,可以用于回滚,同时可以提供多版本并发控制下的读。

redolog:数据库操作数据的时候会先写入缓存,然后再写入数据库。但是如果写入缓存成功,但是数据库宕机,数据就丢失了。因此有了redolog,每次写入缓存后必须在redolog中记录该操作(对 XXX表空间中的XXX数据页XXX偏移量的地方做了XXX更新),这样即使数据库宕机,等数据库恢复后,仍然能把数据从redolog刷盘到数据库。

4. 什么字段适合作为索引?

频繁使用的字段、区分度高的字段、外键

5. 索引的结构有哪些?

Hash、BTree(Blance Tree)、B+Tree。在MySQL的InnoDB存储引擎中,主要使用的是B+树。

B树讲解:什么是B树_石楠烟斗的雾的博客-CSDN博客

B+树讲解:什么是B+树_石楠烟斗的雾的博客-CSDN博客

6. 为什么数据库主要使用B+树?B树和B+树有什么区别?

  • B+树所有的叶子节点形成了一个有序链表,范围查询只需要遍历链表,特别方便快捷。B树范围查询就需要遍历整个树,特别慢
  • B+树一个磁盘页能存储更多的节点,IO次数更少。能存储更多数据是因为B+树的中间节点只存储索引,不存卫星数据。
  • B+树每次查询都查询到叶子节点,更稳定。

磁盘页:假设一次IO能读8K的数据,那么8K就是一个磁盘页

B树和B+树的区别?

  • B+树的叶子节点形成了有序链表,每个节点都有指向下一个节点的指针,范围查询更方便
  • B树的每个节点都存储卫星数据,而B+树中间节点只存储索引,所以一个磁盘也可以存更多的节点。叶子节点包含了全量的元素,并存储了卫星数据(索引指向的数据记录,比如数据库的某一行)

需要指出的是:聚簇索引的叶子节点存储了卫星数据,非聚簇索引存储的是指向卫星数据的指针。

B树:

第五篇:数据存储(Mysql、Redis、MongoDB)_第1张图片

B+树:

第五篇:数据存储(Mysql、Redis、MongoDB)_第2张图片

7. hash存储结构和B+树存储结构有什么优劣?

  • hash存储底层是Hash表,等值查询比较快,但无法进行范围查询,因为用hash算法构建的索引不能和原顺序保持一致;B+树叶子节点的链表天然有序,因此支持范围查询。
  • hash索引在某个键大量重复时,会出现hash冲突,此时效率极差;B+树都是从根节点到叶子节点,查询效率稳定。

因此一般情况下,用B+树就能获得稳定快速的查询

8. B+树的具体实现是什么样的?

每个中间节点都只存储索引,叶子节点包含全量的元素,并存储了卫星数据。

聚簇索引的B+树结构: 叶子节点存储的是卫星数据; 非聚簇索引的B+树结构: 叶子节点存储的是指向卫星数据的指针。

9. 联合索引在B+树中怎么存储?

联合索引主要是用索引第一列构建的树,因此第一列是有序的,其他列是无序的。但是当第一列确定时,其他列相对有序。最左匹配原则也由此而来。

10. 最左匹配原则

以最左边为起点,连续的索引都能匹配上,遇到范围查询(> < between like)就会终止。

例如:建立联合索引(a,b,c,d),where a=1 and b=b and c>1 and d=1 则d用不到索引,因为c是范围查询。

最左匹配原则原理:

索引的底层是B+树,联合索引也是。但是联合索引是用最左边的字段来构建B+树,因此最左边的字段是有序的,后边的字段都是无序的。但是当最左边字段确定时,后边字段相对有序。

第五篇:数据存储(Mysql、Redis、MongoDB)_第3张图片

11. 百万级的数据怎么删除

删除数据需要的时间和索引数量成正比,因为维护索引需要成本。

因此删除百万级数据的时候,应该先删除索引,然后删除不用的数据,最后重新建立索引。这样绝对比直接删除快的多。

12. 什么是数据库事务?事务的四大特性ACID介绍一下

事务是一组操作,要么都执行,要么都不执行。

  • 原子性:要么都执行,要么都不执行
  • 一致性:数据前后一致,比如转账操作,转账前两个账户共2000元,转完后也应是2000元
  • 隔离性:各个事务之间互不影响
  • 持久性:事务一旦提交,改变就是永久性的

13. 什么是脏读、不可重复读、幻读?

  • 脏读:读到了未提交的数据
  • 不可重复读:一个事务中,前后两次读到的数据不一致
  • 幻读:一个事务中,前后两次读到的行数不一致

14. 事务的隔离级别?怎么实现的(加了什么锁)?MySQL默认的隔离级别是什么?

  • 读未提交:可以读没有提交的数据。没有加锁。
  • 读已提交:可以读已经提交的数据。在读操作中,加的是共享锁,语句执行完毕就释放锁。
  • 可重复读:一个事务前后两次读到的数据必然相同。在读操作中,加共享锁,事务不执行完毕不释放锁。
  • 可串行化:最高隔离级别,各个事务之间依次执行,不可能相互影响。对整个范围内的键都加锁,事务执行完毕才释放锁。

MySQL默认的隔离级别是 可重复读;Oracle是 读已提交。

15. 数据库的行锁和表锁是怎么实现的?

行锁是对索引进行加锁,没有索引不能用行锁,会升级到表锁。并且如果两条数据的索引相同,另一条数据也会被锁住。

例如:select * from table where id = 1 for update;如果id是索引,则加的是行锁;如果不是,则加的是表锁。

行锁和表锁如何使用?

行锁:

数据库会默认给UPDATE、DELETE、INSERT加排它锁,SELECT语句不会加任何锁,但是用户可以通过如下语句自行加锁

  • 加共享锁:select * from table where xxx LOCK IN SHARE MODE;
  • 加排它锁:select * from table where xxx FOR UPDATE;

表锁:

表锁必须手动释放,但是在事务提交前不要释放锁,因为UNLOCK TABLE隐含提交事务。如果要对t1写,对t2读,则按如下操作:

LOCK TABLES t1 WRITE, t2 READ;

dosomething......

COMMIT;

UNLOCK TABLES;

16.  如何定位sql语句的性能问题?如何解决?

定位性能问题用explain命令查看执行计划。有几个关键的字段:

  • possible_keys:可能会用到的索引
  • key:用到的索引
  • type:访问类型(如:ALL-全表扫描、index-遍历索引、ref-使用非唯一索引查询、range-索引范围查询、fulltext-全文索引)
  • rows:估算的结果集数目
  • Extra:额外信息(如:Using index-使用索引覆盖、Using where-使用where、Using filesort-使用文件排序、Using temporary-使用临时表)

优化:

  • 看是否加载了额外的行或列,尽量缩小查询范围
  • 看是否能调整sql命中索引,或添加索引
  • 如果是长难sql,看是否能拆开查询,然后在内存中聚合处理

17. 超大分页怎么处理?

比如:select * from table where age>20 limit 1000000,10;  这样相当于把前一百万条数据抛弃了,取了后续10条,这样非常慢。

【优化方案一】数据库角度:

  • 如果有自增长的id,则可以优化为:select * from table where id>1000000 limit 10; 记录上一次查询的最大id,下一次查询直接从该id开始
  • 如果没有自增长id,可以用子查询索引覆盖:select * from table where id in ( select id from table where  age > 20 limit 1000000,10); 子查询索引覆盖,会快很多。

【优化方案二】需求角度:尽量不做这样的需求,问业务方这是强需求吗?是什么样的场景导致一定要这样做?是否可以限制用户的查询轨迹,只允许逐页查看之类的。

18. 怎么排查慢sql?对于慢sql怎么优化?

可以登录mysql配置开启慢查询日志,当有慢查询时,慢查询日志就会记录该sql。但是一般这个功能都是公司DBA做的,业务方可以在平台上查看慢sql耗时。

配置开启慢查询日志:set slow_query_log = on

配置临界时间:set long_query_time = 0.5

慢sql优化:

  • 看是否加载了额外的行或列,尽量缩小查询范围
  • 看是否能调整sql命中索引,或添加索引
  • 如果是长难sql,看是否能拆开查询,然后在内存中聚合处理

19. MySQL数据库CPU飙升到500%怎么处理?

看一下有没有慢sql,用explain命令分析并优化慢sql

20. 千万数据的表,CRUD特别慢,怎么优化?

  • 缩小查询范围(行和列),比如只查近一个月的订单
  • 命中索引
  • 把热点数据放在缓存中
  • 分库分表

【分库分表】

垂直分表:把表按照某个维度(比如使用频率)垂直拆分开

  • 优点:一个数据页能存储更多的数据,能减少IO次数
  • 缺点:需要管理冗余列,有时候需要联表查询

水平分表:当数据超过200万行时,CRUD就会很慢,这时就需要用某种策略将数据水平分片

  • 优点:能够支撑大量的数据
  • 缺点:分布式事务难以处理、跨库的join、跨库的count orderby groupby等函数不好使用。后两个问题可以通过在应用程序中进行拼装来解决

21. 数据库是怎么进行主从复制的?

  • 主库把数据更改记录到binlog中
  • 通过IO把binlog传输到从库
  • 从库重新执行binlog中的语句就能实现主从复制了

22. count(*)、count(1)、count(列名)有什么区别?

执行结果上:count(*)、count(1)没有区别,count(列名)不统计为null的记录。

执行效果上:mysql会自动优化count(*),因此当有主键的时候count(*)比count(1)快;没有主键的时候,count(1)比count(*)快。如果列名是主键,则count(列名)最快。

23. 频繁的增删数据量某个表,数据库最终数据只有几万或者更少,为什么查询会变慢

原因是该表的空间大了,查询起来很慢。解决的方法是把该表所占用的表空间缩小,或者说释放表空间。
alter table XXXX move; 这样处理后就释放了表空间了。
但是释放表空间后,表的行号rowid会发生变化,而基于rowid的索引则会变成无效。因此该操作后必须重建索引。
否则会 提示“ORA-01502: 索引'SMP.ITEMLOG_MID_IDX'或这类索引的分区处于不可用状态”
而重建索引的方法当然可以先drop掉再create ,但是这样太麻烦了,
用alter index XXX rebuild 这样最快了,不会改变原来的索引结构

24.  mysql执行sql流程?

1、客户端先和sql服务器建立连接,客户端发生查询sql脚本给服务器

2、服务器先检查查询缓存,如果命中了缓存,则立刻返回存储在缓存中的结果。否则进入下一阶段。

3、服务器端进行SQL解析、预处理,再由优化器生成对应的执行计划。

4、MySQL根据优化器生成的执行计划,再调用存储引擎的API来执行查询。

5、将结果返回给客户端。

25. 什么情况下会索引失效?

  • 不满足最左匹配原则
  • 索引列使用了函数
  • like左边包含%
  • 使用了not in 或 not exist
  • 使用了or 关键字(如果使用了or关键字,那么它前面和后面的字段都要加索引,不然所有的索引都会失效)

26. 分库分表的方案?

概念:以某个字段为依据,按照一定策略,将一个表中的数据拆分到多个表中。
场景:单表的数据量太多,影响了SQL效率

工具:Sharding-JDBC

  • 选择分片键
  • 选择分片策略:取模、范围(Between AND)

二. Redis

1. redis有哪些数据类型?

  • String:字符串。set get mset(批量set) mget
  • Hash:包含键值对的无序散列表。hmset key filed1 value1 filed2 value2;   hget key filed1;
  • List:有序列表。lpush key value; rpush key value; lrange key 0 3;
  • set:无序不重复集合。sadd key value; smembers key;
  • zset:有序不重复集合,每个元素都关联分数,通过分数来排序。zset key score value; zrangebyscore 0 3;

redis中String底层的数据结构?

Redis六种底层数据结构_星空是梦想的博客-CSDN博客_redis 底层数据结构、图解redis五种数据结构底层实现(动图哦)

是简单动态字符串(SDS)。用char[]数组的形式保存String中每个字符,还有len属性保存字符串的长度,以及free属性保存未使用的字节数。

为什么要这样设计?

杜绝缓存区溢出。c字符串如果没有重新分配空间,直接修改字符串,可能会造成空间溢出。SDS会先判断空间是否够用,不够的话会扩展至所需大小。

减少内存重新分配。redis会进行空间预分配,减少了因为字符串修改导致的扩容;并且是惰性空间释放,如果字符串变短,不会直接回收,而是存到free中。

redis中list的底层数据结构?

redis中list的底层数据结构是一个双向链表。

redis中hash的底层数据结构?

hash的底层数据结构可以是ziplist(压缩列表)或者哈希表(数组加链表的结构)。

当hash对象可以同时满足一下两个条件时,哈希对象使用ziplist编码。

  • 哈希对象保存的所有键值对的键和值的字符串长度都小于64字节
  • 哈希对象保存的键值对数量小于512个

zipList的数据结构?

zipList:

zipEntry:

  • ziplist包括zip header、zip entry、zip end三个模块。
  • zip entry由prevlen、encoding&length、value三部分组成。
  • prevlen主要是指前面zipEntry的长度,coding&length是指编码字段长度和实际- 存储value的长度,value是指真正的内容。
  • 每个key/value存储结果中key用一个zipEntry存储,value用一个zipEntry存储。

redis中set的数据结构?

redis中set是一个intset或者hashtable的结构。当元素全为整数且元素数量不超过512个时用intset存储,否则用hashtable。

intset底层实际上是一个int数组。

zset底层的数据结构是什么?

漫画:什么是 “跳表”?、跳跃表及底层实现原理解析_Slayer_Zhao的博客-CSDN博客_跳跃表原理和实现

zset底层的存储结构包括压缩列表(ziplist)或者跳表(skiplist),在同时满足以下两个条件的时候使用ziplist,其他时候使用skiplist,两个条件如下:

  • 有序集合保存的元素数量小于128个
  • 有序集合保存的所有元素的长度小于64字节

  

压缩列表:

当ziplist作为zset的底层存储结构时候,每个集合元素使用两个紧挨在一起的压缩列表节点来保存,第一个节点保存元素的成员,第二个元素保存元素的分值。

第五篇:数据存储(Mysql、Redis、MongoDB)_第4张图片

跳表:

当skiplist作为zset的底层存储结构的时候,使用skiplist按序保存元素及分值,使用dict来保存元素和分值的映射关系。

跳表的结构如下图所示,跳表是在原始链表的基础上加了多层索引链表,索引链表的节点指向原始列表的节点,使得查询数据的效率更高。

第五篇:数据存储(Mysql、Redis、MongoDB)_第5张图片

插入:

2. redis的适用场景?项目中哪里用过redis?

  • 缓存热点数据:如缓存标的列表
  • 计数器:一个月内优惠券一万张,发一张就减一
  • 分布式锁:比如一个人在交易完成前不能再进行第二次操作,用分布式锁来保证。再比如抢标时标的金额递减,也用分布式锁来保证。用setnx实现的

3. redis为什么快?

  • redis基于内存,所以高性能
  • redis是单线程,不需要多线程竞争CPU资源,也不需要切换上下文,减少了很多性能损耗
  • redis使用了IO多路复用的模型,用一个选择器监听多个通道,当通道有事件发生时,线程就处理事件

4. redis为什么单线程还快?

因为redis使用了IO多路复用的模型,用一个选择器监听多个通道,当通道有事件发生时,线程就处理事件。相当于可以处理大量并发IO。

IO多路复用和多线程有什么区别?

  • IO多路复用适合处理IO密集型,IO等待的时间比较长,不需要太多CPU计算,单线程就处理计算逻辑了
  • 多线程适合处理CPU密集型,需要多线程使用多核CPU处理计算逻辑。

redis完全是单线程的吗?

不是。redis的读写命令是单线程的,但是处理网络IO是多线程的,因为redis的瓶颈主要是网络IO,所以 处理网络IO 用多线程可以解决这个问题,并且不会造成数据并发读写。

5. redis的持久化机制是什么?优缺点是什么?

RDB:按照一定的时间间隔把内存快照保存到磁盘中

  • 优点:性能好,保存内存快照是子进行进行的,不需要占用主进程IO;恢复数据快
  • 缺点:如果在保存间隔内redis宕机,会丢失数据

AOF:把所有的写操作记录到磁盘日志中

  • 优点:保存数据完整
  • 缺点:数据集大的时候,恢复数据慢

6. redis过期键的删除策略?

  • 定时删除:给每个有过期时间的key都创建定时器,到过期时间就会清除;
  • 惰性删除:访问到key的时候,才判断有没有到过期时间,过期则清除;
  • 定期删除:每间隔一段时间,会扫描所有的key,清除已过期的key

redis使用:惰性删除 + 定期删除

7. 有2000万mysql数据,redis只能存储20w数据,怎么保证redis存储的都是热点数据?

当数据集上升到一定程度,就会使用淘汰策略。

淘汰策略用于处理 内存不足时需要申请额外空间的数据,有三种策略:

  • 随机移除
  • 移除使用最少的key
  • 移除更早过期的key

当内存用完的时候,写操作会返回错误,或者你可以配置内存淘汰策略

8. redis支持事务吗?

支持,redis的事务能保证一系列指令按顺序执行,中间不会插入其他语句。但是redis事务只支持隔离性,不支持原子性,不支持回滚。

当中间有语句执行失败时,会继续执行其他语句。

9. redis事务的命令有哪些?

  • MULTI:开启事务
  • EXEC:执行事务
  • WATCH:监控一个或多个键,一旦键被修改,事务就不会执行。本质是一个乐观锁,为事务提供CAS(compare and set)行为
  • DISCARD:清空事务队列,并放弃执行事务

10. redis哨兵机制是什么?

sentinel,哨兵,用于保证redis集群的高可用。它有四个作用:

  • 集群监控:监控redis master 和 slave 的可用性
  • 消息通知:如果master宕机,会报警通知运维管理员。(判断master宕机,需要一半以上的sentinel同意才行,涉及到分布式选举)
  • 故障转移:如果master故障,会从slave中选举出一个新的master
  • 配置中心:如果发生故障,会通知客户端新的master地址

哨兵机制不保证数据不丢失,只能保证redis集群高可用

11. redis集群模式(redis cluster)的工作原理知道吗?

redis集群使用了哈希槽的方式来进行数据存储和读取。

假设redis集群有3个分片,数据将分别存储在这三个分片上,三个分片上被均分了16384个哈希槽。数据具体存储在哪个分片上,是由哈希槽算法决定的。CRC16(key) % 16384就可以得知数据要被存储在哪个槽上了。

如果是服务端路由的方式,客户端把请求发送到任意分片节点,接收到请求的节点都会把请求转发到正确的节点上执行。

redis为什么不使用一致性哈希,而使用哈希槽?

因为哈希槽好扩容,如果要增加节点,只需要把其他分片上的哈希槽迁移一部分到新节点即可。

一致性哈希(哈希环)

        如果我们要确定一张图片要放在ABC哪台服务器上,普通做法是 图片的hash值%3(3台服务器),但是如果要再加一台服务器,所有图片的位置就都需要改变。

        所以我们用一致性hash,用 hash值 对 2^32 取模,并把2^32想象成一个环,ABC服务器则是环上三个点,图片的hash值必然落在弧形区间内,归为下一个最近的服务器。

        缺点:可能会数据分布不均匀,导致哈希倾斜。解法:把ABC服务器,多取几个hash值(A1A2A3)作为虚拟节点,虚拟节点越多,哈希倾斜带来的影响就越小。

什么是redis集群模式下的脑裂?如何解决脑裂?

脑裂是因为网络原因,导致master、slave、sentinel不在一个网络分区。此时sentinel感应不到master,就会从slave中重新选举一个master,两个master看起来就像master分裂成了两个。

集群脑裂问题中,如果客户端还继续往旧的master写数据,当网络恢复后,sentinel就会把之前master降为slave,此时再从新的master同步数据就会丢失大量数据。

解决方案:

redis有两个配置如下,如果slave节点少于3个,或者slave超过10秒都没连接到master,master就拒绝写请求

//配置slave节点最少有3个
min-slaves-to-write 3

//配置slave连接到master的最大延时为10秒
min-slaves-max-lag 10

12. redis是如何进行主从复制的?

  • 当一个slave启动的时候,会发送一个同步命令(PSYNC)给master
  • master生成一个RDB文件发给slave,并把期间收到的写命令缓存起来,然后把RDB文件和缓存的写命令发送给slave
  • slave把RDB文件先写到磁盘,然后写到缓存中,再执行写命令
  • 之后master收到的写命令都会同步给slave,从而保证数据的一致性

这样的主从复制模式有一个缺点,就是所有的复制同步都由master处理,导致master压力太大,可以使用主从从模式,slave同步到slacve

13. 缓存异常

【缓存雪崩】:同一时间内大面积缓存失效,导致请求全都打到服务器上。

解决方案:缓存预热,在服务器启动前把热点数据提前刷到缓存中,并且过期时间尽量设置的随机一些,避免同一时间失效

【缓存击穿】:缓存中没有数据库中有的数据(一般是缓存时间到期)

解决方案:一般有两种解决方案。第一是让热点数据用不过期,但是轻易不使用这种方式。第二种是用双重判空的方式,先去缓存中拿,缓存中没有再加锁,再判断缓存中有没有,没有的话再到数据库拿。

【缓存穿透】:缓存和数据库中都没有的数据

解决方案:可以在缓存中设置一个key,value是null,这样也就直接能从缓存拿到了

14. 如何用redis实现分布式锁?

  • 获取锁:SETNX(set if Not Exist), 设置成功返回1,设置失败返回0
  • 释放锁:DEL

如何获取分布式锁?怎么保证性能?

  • 可以用setnx()获取锁成功返回1,获取失败返回0;如果是获取成功则可以继续处理下边的业务,如果获取失败自旋5次,尝试去获取锁。
  • 如果要设置过期时间,用jedisClient.set(key, value, "NX", "EX", expireSecond);//NX是不存在时才set,XX是存在时才set,EX是秒,PX是毫秒

自旋比较消耗性能,如果不采用自旋的方式呢?

使用blpop。

redis和zk获取分布式锁有什么区别?

zk获取分布式锁是通过创建临时节点的方式,如果创建临时节点成功就获取锁,如果创建失败就用监听器监听这个临时节点,释放锁就是删除临时节点。

但是一般都不使用zk做分布式锁,很客观的原因是要用zk做分布式锁就得有zk集群,但是一般公司都没有zk集群,但是都有redis的集群,所以都用redis做分布式锁。

15. 假设redis中有一亿数据,有10w个前缀都是一样的,如何把他们找出来?

  • 使用keys指令,keys [前缀]*。缺点:redis是单线程的,keys指令会使线程阻塞一段时间,导致线上会停顿,直到该指令执行完毕。
  • 使用scan指令,scan指令是一个基于游标的迭代器。每次调用之后,都会返回一个新游标。用户下次可以使用这个游标继续迭代。

16. 有10万条数据,要插入到redis中,如何操作?

  • 可以使用管道,分批提交数据。比一个一个提交快,是因为省去了多次网络IO的时间。
  • 可以使用AOF的方式,把10万条数据变成set key value,set ket value的形式,加载到redis中

17. 如何使用redis做异步队列?

使用redis的list数据结构,blpush生产消息,brpop消费消息,brpop是阻塞的,没有消息就一直等待,直到消息到来。

18. 如何使用redis做延迟队列?

用redis的zset做延迟队列,消息作为value,时间戳作为score,用zrangebyscore来获取n秒前的消息。

19. redis的回收线程是怎么工作的?

当redis已使用内存达到阈值之上,如果有新请求进来,就会按照配置的淘汰策略进行回收。

20. redis回收使用的是什么算法?

LRU算法,淘汰最少使用的数据。

LRU算法具体实现?

LRU算法的核心思想是:

如果数据最近被访问过,那么将来被访问的几率也更高。

实现:

第五篇:数据存储(Mysql、Redis、MongoDB)_第6张图片

  • 新加入数据添加到链表头部
  • 被访问的数据也添加移动到链表头部
  • 当链表满时从底部淘汰数据

代价:命中需要遍历链表,找到命中的数据,并移动到链表头部

三.MongoDB

1. 你们项目中MongoDB中存储是什么数据?

费率、保单的扩展字段。

由于费率计算复杂,每个保司计算费率的条件也都不一样,这时候如果用数据库存储,就没办法设计表,因此采用MongoDB存储,可以灵活的存储非结构化数据。

2. MySQL和MongoDB和redis的特点、区别、使用场景?

MySQL是关系型数据库,常用于存储结构化数据,并且支持事务。

MongoDB和redis都是非关系型数据库,MongoDB当做数据库使用,如果不确定数据的结构,就可以使用MongoDB,便于扩展字段。

redis当做缓存使用,查询非常快速,比如可以存储热点数据,缩小给前端的返回时间。

3. 

你可能感兴趣的:(肖哈哈java自学笔记,mongodb,mysql,redis)