1. Redis 持久化机制
Redis是一个支持持久化的内存数据库,通过持久化机制把内存中的数据同步到硬盘文件来保证数据持久化。 当Redis重启后通过把硬盘文件重新加载到内存,就能达到恢复数据的目的。
实现:单独创建fork()一个子进程,将当前父进程的数据库数据复制到子进程的内存中,然后由子进程写入到 临时文件中,持久化的过程结束了,再用这个临时文件替换上次的快照文件,然后子进程退出,内存释放。
RDB是Redis默认的持久化方式。按照一定的时间周期策略把内存的数据以快照的形式保存到硬盘的二进制文件。即Snapshot快照存储,对应产生的数据文件为dump.rdb,通过配置文件中的save参数来定义快照的周 期。( 快照可以是其所表示的数据的一个副本,也可以是数据的一个复制品。)
AOF:Redis会将每一个收到的写命令都通过Write函数追加到文件最后,类似于MySQL的binlog。当Redis 重启是会通过重新执行文件中保存的写命令来在内存中重建整个数据库的内容。
当两种方式同时开启时,数据恢复Redis会优先选择AOF恢复。
2. memcache的工作原理
memcache是以key-value形式存储的,key会通过一个hash表转换成hash的key,便于查找对比。客户端通 过key的hash值确定数据的位置,然后向服务端发出请求,获取真实的数据
3. Memcache与Redis的区别
1)、存储方式 Memecache把数据全部存在内存之中,断电后会挂掉,数据不能超过内存大小。 Redis有部 份存在硬盘上,redis可以持久化其数据
2)、数据支持类型 memcached所有的值均是简单的字符串,redis作为其替代者,支持更为丰富的数据类型 ,提供list,set,zset,hash等数据结构的存储
3)、使用底层模型不同 它们之间底层实现方式 以及与客户端之间通信的应用协议不一样。 Redis直接自己 构建了VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求。
4). value 值大小不同:Redis 最大可以达到 512M;memcache 只有 1mb。
5)redis的速度比memcached快很多
6)Redis支持数据的备份,即master-slave模式的数据备份。
4. redis的内存占用情况怎么样?
100万个键值对(键是0到999999值是字符串“hello world”)在我的32位的Mac笔记本上用了100MB。同样的数据放到一个key里只需要16MB, 这是因为键值 有一个很大的开销。 在Memcached上执行也是类似的结果,但是相对Redis的开销要小一点点,因为Redis 会记录类型信息引用计数等等。
5. 单线程的redis为什么这么快
(一)纯内存操作
(二)单线程操作,避免了频繁的上下文切换
(三)采用了非阻塞I/O多路复用机制
6. Redis 为什么是单线程
因为Redis是基于内存的操作,CPU不是Redis的瓶颈,Redis的瓶颈最有可能是机器内存的大小或者网络带宽。既然单线程容易实现,而且CPU不会成为瓶颈,那就顺理成章地采用单线程的方案了(毕竟采用多线程会 有很多麻烦!)Redis利用队列技术将并发访问变为串行访问
1)绝大部分请求是纯粹的内存操作(非常快速)
2)采用单线程,避免了不必要的上下文切换和竞争条件
3)非阻塞IO优点:
1.速度快,因为数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1)
2. 支持丰富数据类型,支持string,list,set,sorted set,hash
3.支持事务,操作都是原子性,所谓的原子性就是对数据的更改要么全部执行,要么全部不执行
4. 丰富的特性:可用于缓存,消息,按key设置过期时间,过期后将会自动删除如何解决redis的并发竞争 key问题
同时有多个子系统去set一个key。这个时候要注意什么呢? 不推荐使用redis的事务机制。因为我们的生产环境,基本都是redis集群环境,做了数据分片操作。你一个事务中有涉及到多个key操作的时候,这多个key 不一定都存储在同一个redis-server上。因此,redis的事务机制,十分鸡肋。
(1)如果对这个key操作,不要求顺序: 准备一个分布式锁,大家去抢锁,抢到锁就做set操作即可
(2)如果对这个key操作,要求顺序: 分布式锁+时间戳。 假设这会系统B先抢到锁,将key1设置为{valueB 3:05}。接下来系统A抢到锁,发现自己的valueA的时间戳早于缓存中的时间戳,那就不做set操作了。以此 类推。
(3) 利用队列,将set方法变成串行访问也可以redis遇到高并发,如果保证读写key的一致性 对redis的操作都是具有原子性的,是线程安全的操作,你不用考虑并发问题,redis内部已经帮你处理好并发 的问题了。
7. 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操作。
8. redis的过期策略以及内存淘汰机制
redis采用的是定期删除+惰性删除策略。
什么不用定时删除策略?
定时删除,用一个定时器来负责监视key,过期则自动删除。虽然内存及时释放,但是十分消耗CPU资源。在大 并发请求下,CPU要将时间应用在处理请求,而不是删除key,因此没有采用这一策略.
定期删除+惰性删除是如何工作的呢?
定期删除,redis默认每个100ms检查,是否有过期的key,有过期key则删除。需要说明的是,redis不是每个100ms将所有的key检查一次,而是随机抽取进行检查(如果每隔100ms,全部key进行检查,redis岂不是 卡死)。因此,如果只采用定期删除策略,会导致很多key到时间没有删除。 于是,惰性删除派上用场。也就是说在你获取某个key的时候,redis会检查一下,这个key如果设置了过期时间那么是否过期了?如果过期了此时就会删除。
采用定期删除+惰性删除就没其他问题了么?
不是的,如果定期删除没删除key。然后你也没即时去请求key,也就是说惰性删除也没生效。这样,redis的 内存会越来越高。那么就应该采用内存淘汰机制。
在redis.conf中有一行配置
maxmemory-policy volatile-lru
9. Reids6种淘汰策略
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。
10. Redis内存模型
used_memory:Redis分配器分配的内存总量(单位是字节),包括使用的虚拟内存(即swap); used_memory_human只是显示更友好。
used_memory_rss:Redis进程占据操作系统的内存(单位是字节),与top及ps命令看到的值是一致的; 除了分配器分配的内存之外,used_memory_rss还包括进程运行本身需要的内存、内存碎片等,但是不包括 虚拟内存。
mem_fragmentation_ratio:内存碎片比率,该值是used_memory_rss used_memory的比值。
mem_allocator:Redis使用的内存分配器,在编译时指定;可以是 libc 、jemalloc或者tcmalloc, 默认是jemalloc。
11. Redis内存划分
数据:作为数据库,数据是最主要的部分;这部分占用的内存会统计在used_memory中。
进程本身运行需要的内存:Redis主进程本身运行肯定需要占用内存,如代码、常量池等等;这部分内存大约 几兆,在大多数生产环境中与Redis数据占用的内存相比可以忽略。这部分内存不是由jemalloc分配,因此 不会统计在used_memory中。
缓冲内存:缓冲内存包括客户端缓冲区、复制积压缓冲区、AOF缓冲区等;其中,客户端缓冲存储客户端连接 的输入输出缓冲;复制积压缓冲用于部分复制功能;AOF缓冲区用于在进行AOF重写时,保存最近的写入命令。 在了解相应功能之前,不需要知道这些缓冲的细节;这部分内存由jemalloc分配,因此会统计在 used_memory中。
内存碎片:内存碎片是Redis在分配、回收物理内存过程中产生的。例如,如果对数据的更改频繁,而且数据 之间的大小相差很大,可能导致redis释放的空间在物理内存中并没有释放,但redis又无法有效利用,这就 形成了内存碎片。内存碎片不会统计在used_memory中。
12. RDB和AOF的优缺点
RDB持久化
优点:RDB文件紧凑,体积小,网络传输快,适合全量复制;恢复速度比AOF快很多。当然,与AOF相比,RDB 最重要的优点之一是对性能的影响相对较小。
缺点:RDB文件的致命缺点在于其数据快照的持久化方式决定了必然做不到实时持久化,而在数据越来越重要 的今天,数据的大量丢失很多时候是无法接受的,因此AOF持久化成为主流。此外,RDB文件需要满足特定格 式,兼容性差(如老版本的Redis不兼容新版本的RDB文件)。
AOF持久化
与RDB持久化相对应,AOF的优点在于支持秒级持久化、兼容性好,缺点是文件大、恢复速度慢、对性能影响大。
13. 持久化策略选择
(1)如果Redis中的数据完全丢弃也没有关系(如Redis完全用作DB层数据的cache),那么无论是单机, 还是主从架构,都可以不进行任何持久化。
(2)在单机环境下(对于个人开发者,这种情况可能比较常见),如果可以接受十几分钟或更多的数据丢失, 选择RDB对Redis的性能更加有利;如果只能接受秒级别的数据丢失,应该选择AOF。
(3)但在多数情况下,我们都会配置主从环境,slave的存在既可以实现数据的热备,也可以进行读写分离分 担Redis读请求,以及在master宕掉后继续提供服务。
14. 为什么需要持久化?
由于Redis是一种内存型数据库,即服务器在运行时,系统为其分配了一部分内存存储数据,一旦服务器挂了,或者突然宕机了,那么数据库里面的数据将会丢失,为了使服务器即使突然关机也能保存数据,必须通过 持久化的方式将数据从内存保存到磁盘中。
15. Redis 集群方案应该怎么做?都有哪些方案?
1.twemproxy,大概概念是,它类似于一个代理方式,使用时在本需要连接 redis 的地方改为连接 twemproxy, 它会以一个代理的身份接收请求并使用一致性 hash 算法,将请求转接到具体 redis,将结 果再返回 twemproxy。 缺点: twemproxy 自身单端口实例的压力,使用一致性 hash 后,对 redis 节点数量改变时候的计算值 的改变,数据无法自动移动到新的节点。
2.codis,目前用的最多的集群方案,基本和 twemproxy 一致的效果,但它支持在 节点数量改变情况下, 旧节点数据可恢复到新 hash 节点
3.redis cluster3.0 自带的集群,特点在于他的分布式算法不是一致性 hash,而是 hash 槽的概念, 以及自身支持节点设置从节点。具体看官方文档介绍。
16. redis哨兵模式的特性和特点以及缺点
这个哨兵模式的优点呢有很多,比如说这个支持的数据类型多,可以用AOF或RDB持久化存储,他性能还是特别好的,因为他用的是这个全内存操作嘛,至于这个缺点呢它主要是依赖于硬件设备,比如说他只能使用单线程,这个性能呢是受限于CPU性能的还有就是这个数据的存储量是跟机器内存大小相关的
17. 什么是缓存穿透,什么是缓存雪崩
缓存穿透:
当一个微应用或者分布式环境有上百万的流量请求时,如果这些请求的数据 在redis缓存这一层不存在,那么 就会穿过redis的缓存直达到后台,也就是mysql服务器,导致整个微服务应用挂掉
缓存雪崩:
就是redis缓存直接挂掉了,请求穿过缓存直接到达数据库,数据的并发访问量为几千,几万的访问量,导致数据 直接挂掉,最终导致整个系统挂掉
18. MySQL与MongoDB之间最基本的差别是什么?
MySQL和MongoDB两者都是免费开源的数据库。MySQL和MongoDB有许多基本差别包括数据的表示(data representation),查询,关系,事务,schema的设计和定义,标准化(normalization),速度和性能。 通过比较MySQL和MongoDB,实际上我们是在比较关系型和非关系型数据库,即数据存储结构不同。
19. MongoDB更新操作立刻fsync到磁盘?
不会,磁盘写操作默认是延迟执行的。写操作可能在两三秒(默认在60秒内)后到达磁盘。例如,如果一秒内数 据库收到一千个对一个对象递增的操作,仅刷新磁盘一次。
20. 为什么MongoDB的数据文件巨大
MongoDB会积极的预分配预留空间来防止文件系统碎片
21. MongoDB支持存储过程吗?如果支持的话,怎么用?
MongoDB支持存储过程,它是javascript写的,保存在db.system.js表中。
22. 如何理解MongoDB中的GridFS机制,MongoDB为何使用GridFS来存储文件?
GridFS是一种将大型文件存储在MongoDB中的文件规范。使用GridFS可以将大文件分隔成多个小文档存放, 这样我们能够有效的保存大文档,而且解决了BSON对象有限制的问题