1、什么是Redis?简述它的优缺点?
答:Redis的全称是:Remote Dictionary.Server,本质上是一个Key-Value范例的内存数据库,很像 memcached,整个数据库统统加载在内存当中举行操作,定期通过异步操作把数据库数据flush到硬盘 上举行保存。 因为是纯内存操作,Redis的性能非常出色,每秒可以处置惩罚超过 10万次读写操作,是已知性能最快的 Key-Value DB。 Redis的出色之处不但仅是性能,Redis最大的魅力是支持保存多种数据结构,别的单个value的最大限 制是1GB,不像 memcached只能保存1MB的数据,因此Redis可以用来实现很多有用的功能。 比方说用他的List来做FIFO双向链表,实现一个轻量级的高性 能消息队列服务,用他的Set可以做高 性能的tag体系等等。 另外Redis也可以对存入的Key-Value设置expire时间,因此也可以被当作一 个功能增强版的 memcached来用。 Redis的紧张缺点是数据库容量受到物理内存的限定,不能用作海量数据的高性能 读写,因此Redis适合的场景紧张局限在较小数据量的高性能操作和运算上。
2、Memcached 与 Redis 的异同?
答:共同点
- 都是基于内存的数据库,一般都用来当作缓存使用
- 都有逾期策略
- 两者的性能都非常高
异同点
- Redis 支持更丰富的数据范例,Memcached 只支持最简单的 k/v 数据范例,所有的值均是简单的字符串
- Redis 支持数据的持久化,而 Memecache 把数据全部存在内存之中,重启之后数据丢失
- Redis 有灾难规复机制,因为可以把缓存中的数据持久化到磁盘上
- Redis 在服务器内存使用完之后,可以将不用的数据放到磁盘上。但 Memcached 在服务器内存使用完之后,就会直接报异常
- Memcached 没有原生的集群模式,需要依靠客户端来实现往集群中分片写入数据;但 Redis现在是原生支持 cluster 模式的
- Memcached 是多线程,非阻塞 IO 复用的网络模子;Redis 使用单线程的多路 IO 复用模子
- Redis 支持发布订阅模子、Lua 脚本、事务等功能,而 Memcached 不支持。而且,Redis 支持更多的编程语言
- Memcached 逾期数据的删除策略只用了惰性删除,而 Redis 同时使用了惰性删除与定期删除
3、Redis支持哪几种数据范例?
答:String、List、Set、Sorted Set、hashes。
结构范例 | 结构存储的值 | 结构的读写能力 | String字符串 | 可以是字符串、整数或浮点数 | 对整个字符串或字符串的一部分举行操作;对整数或浮点数举行自增或自减操作; | List列表 | 一个链表,链表上的每个节点都包含一个字符串 | 对链表的两端举行push和pop操作,读取单个或多个元素;根据值查找或删除元素; | Set集合 | 包含字符串的无序集合 | 字符串的集合,包含底子的方法有看是否存在添加、获取、删除;还包含盘算交集、并集、差集等 | Hash散列 | 包含键值对的无序散列表 | 包含方法有添加、获取、删除单个元素 | Zset有序集合 | 和散列一样,用于存储键值对 | 字符串成员与浮点数分数之间的有序映射;元素的排列顺序由分数的巨细决定;包含方法有添加、获取、删除单个元素以及根据分值范围或成员来获取元素 | 三种特殊的数据范例 分别是 HyperLogLogs(基数统计), Bitmaps (位图) 和 geospatial (地理位置)
4、谈谈Redis 的对象机制(redisObject)?
答:比如说, 集合范例就可以由字典和整数集合两种不同的数据结构实现, 但是, 当用户执行 ZADD 下令时, 他/她应该不必关心集合使用的是什么编码, 只要 Redis 能按照 ZADD 下令的指示, 将新元素添加到集合就可以了。
这说明, 操作数据范例的下令除了要对键的范例举行检查之外, 还需要根据数据范例的不同编码举行多态处置惩罚.
为了解决以上问题, Redis 构建了本身的范例体系, 这个体系的紧张功能包括:
- • redisObject 对象.
- • 基于 redisObject 对象的范例检查.
- • 基于 redisObject 对象的显式多态函数.
- • 对 redisObject 举行分配、共享和烧毁的机制.
- /*
- * Redis 对象
- */
- typedef struct redisObject {
- // 类型
- unsigned type:4;
- // 编码方式
- unsigned encoding:4;
- // LRU - 24位, 记录最末一次访问时间(相对于lru_clock); 或者 LFU(最少使用的数据:8位频率,16位访问时间)
- unsigned lru:LRU_BITS; // LRU_BITS: 24
- // 引用计数
- int refcount;
- // 指向底层数据结构实例
- void *ptr;
- } robj;
复制代码
5、Redis有哪几种数据淘汰策略?
答:1.noeviction:返回错误当内存限定达到,而且客户端实验执行会让更多内存被使用的下令。 2.allkeys-lru: 实验回收最少使用的键(LRU),使得新添加的数据有空间存放。
3.volatile-lru: 实验回收最少使用的键(LRU),但仅限于在逾期集合的键,使得新添加的数据有空间存放。
4.allkeys-random: 回收随机的键使得新添加的数据有空间存放。
5.volatile-random: 回收随机的键使得新添加的数据有空间存放,但仅限于在逾期集合的键。
6.volatile-ttl: 回收在逾期集合的键,而且优先回收存活时间(TTL)较短的键,使得新添加的数据有空间 存放。
4.0 版本后增加以下两种:
1.volatile-lfu(least frequently used):从已设置逾期时间的数据集(server.db.expires)中挑选最不经常使用的数据淘汰。
2.allkeys-lfu(least frequently used):当内存不敷以容纳新写入数据时,在键空间中,移除最不经常使用的 key。
使用策略的规则:
1.如果数据呈现幂律分布,也就是一部分数据访问频率高,一部分数据访问频率低,则使用 allkeys-lru。
2.如果数据呈现平等分布,也就是所有的数据访问频率都相同,则使用 allkeys-random。
6、Redis如何做内存优化?
答:1. 缩减键值对象: 缩减键(key)和值(value)的长度,
key长度:如在设计键时,在完备形貌业务情况下,键值越短越好。
value长度:值对象缩减比力复杂,常见需求是把业务对象序列化成二进制数组放入Redis。起首应该在业务上精简业务对象,去掉不必要的属性制止存储无效数据。其次在序列化工具选择上,应该选择更高效的序列化工具来降低字节数组巨细。以JAVA为例,内置的序列化方式无论从速度还是压缩比都不尽如人意,这时可以选择更高效的序列化工具,如: protostuff,kryo等,下图是JAVA常见序列化工具空间压缩对比。
2.共享对象池
对象共享池指Redis内部维护[0-9999]的整数对象池。创建大量的整数范例redisObject存在内存开销,每个redisObject内部结构至少占16字节,甚至超过了整数自身空间消耗。以是Redis内存维护一个[0-9999]的整数对象池,用于节约内存。 除了整数值对象,其他范例如list,hash,set,zset内部元素也可以使用整数对象池。因此开发中在满意需求的前提下,尽量使用整数对象以节流内存。
7、一个字符串范例的值能存储最大容量是多少?
答:512M
8、为什么Redis需要把所有数据放到内存中?
答:Redis为了达到最快的读写速度将数据都读到内存中,并通过异步的方式将数据写入磁盘。 以是redis具有快速和数据持久化的特性,如果不将数据放在内存中,磁盘I/O速度为严峻影响redis的 性能。 在内存越来越便宜的今天,redis将会越来越受欢迎, 如果设置了最大使用的内存,则数据已有记录数达 到内存限值后不能继承插入新值。
9、Redis集群方案应该怎么做?都有哪些方案?
答:1.codis
2.现在用的最多的集群方案,基本和twemproxy一致的效果,但它支持在节点数量改变情况下,旧节点 数据可规复到新hash节点。 redis cluster3.0自带的集群,特点在于他的分布式算法不是一致性hash,而是hash槽的概念,以及自 身支持节点设置从节点。具体看官方文档介绍。
3.在业务代码层实现,起几个毫无关联的redis实例,在代码层,对key举行hash盘算,然后去对应的 redis实例操作数据。这种方式对hash层代码要求比力高,考虑部分包括,节点失效后的替代算法方 案,数据震荡后的主动脚本规复,实例的监控,等等。
10、Redis集群方案什么情况下会导致整个集群不可用?
答:有A,B,C三个节点的集群,在没有复制模子的情况下,如果节点B失败了,那么整个集群就会以为缺少 5501-11000这个范围的槽而不可用。
11、MySQL里有2000w数据,redis中只存20w的数据,如何保证redis中的数据都是热门数据?
答:redis内存数据集巨细上升到肯定巨细的时候,就会施行数据淘汰策略。
12、Redis有哪些适合的场景?
答:1.会话缓存(Session Cache) 最常用的一种使用Redis的情景是会话缓存(sessioncache),用Redis缓存会话比其他存储(如 Memcached)的上风在于:Redis提供持久化。当维护一个不是严酷要求一致性的缓存时,如果用户的 购物车信息全部丢失,大部分人都会不高兴的,现在,他们还会如许吗? 幸运的是,随着 Redis 这些年的改进,很轻易找到怎么得当的使用Redis来缓存会话的文档。甚至广为 人知的商业平台Magento也提供Redis的插件。
2.全页缓存(FPC) 除基本的会话token之外,Redis还提供很轻巧的FPC平台。回到一致性问题,即使重启了Redis实 例,因为有磁盘的持久化,用户也不会看到页面加载速度的降落,这是一个极大改进,类似PHP本地 FPC。 再次以Magento为例,Magento提供一个插件来使用Redis作为全页缓存后端。 别的,对WordPress的用户来说,Pantheon有一个非常好的插件wp-redis,这个插件能资助你以最快 速度加载你曾欣赏过的页面。
3.队列 Reids在内存存储引擎领域的一大长处是提供list和set操作,这使得Redis能作为一个很好的消息队列 平台来使用。Redis作为队列使用的操作,就类似于本地步伐语言(如Python)对 list 的 push/pop 操作。 如果你快速的在Google中搜索“Redis queues”,你立刻就能找到大量的开源项目,这些项目的目的 就是利用Redis创建非常好的后端工具,以满意各种队列需求。比方,Celery有一个后台就是使用 Redis作为broker,你可以从这里去查看。
4.排行榜/计数器 Redis在内存中对数字举行递增或递减的操作实现的非常好。集合(Set)和有序集合(SortedSet)也使 得我们在执行这些操作的时候变的非常简单,Redis只是恰好提供了这两种数据结构。 以是,我们要从排序集合中获取到排名最靠前的10个用户–我们称之为“user_scores”,我们只需要像 下面一样执行即可: 当然,这是假定你是根据你用户的分数做递增的排序。如果你想返回用户及用户的分数,你需要如许执 行: ZRANGE user_scores 0 10 WITHSCORES Agora Games就是一个很好的例子,用Ruby实现的,它的排行榜就是使用Redis来存储数据的,你可 以在这里看到。
5.发布/订阅 末了(但肯定不是最不紧张的)是Redis的发布/订阅功能。发布/订阅的使用场景确实非常多。我已瞥见 人们在外交网络连接中使用,还可作为基于发布/订阅的脚本触发器,甚至用Redis的发布/订阅功能来建 立聊天体系!
13、Redis支持的Java客户端都有哪些?官方推荐用哪个?
答:Redisson、Jedis、lettuce等等,官方推荐使用Redisson。
14、Redis和Redisson有什么关系?
答:Redisson是一个高级的分布式和谐Redis客服端,能资助用户在分布式环境中轻松实现一些Java的对 象 (Bloom filter, BitSet, Set, SetMultimap, ScoredSortedSet, SortedSet, Map, ConcurrentMap, List, ListMultimap, Queue, BlockingQueue, Deque, BlockingDeque, Semaphore, Lock, ReadWriteLock, AtomicLong, CountDownLatch, Publish / Subscribe, HyperLogLog)。
15、Jedis与Redisson对比有什么优缺点?
答:Jedis是Redis的Java实现的客户端,其API提供了比力全面的Redis下令的支持; Redisson实现了分布式和可扩展的Java数据结构,和Jedis相比,功能较为简单,不支持字符串操作, 不支持排序、事务、管道、分区等Redis特性。Redisson的宗旨是促进使用者对Redis的关注分离,从 而让使用者能够将精神更集中地放在处置惩罚业务逻辑上。
16、说说Redis哈希槽的概念?
答:Redis集群没有使用一致性hash,而是引入了哈希槽的概念,Redis集群有16384个哈希槽,每个key通 过CRC16校验后对16384取模来决定放置哪个槽,集群的每个节点负责一部分hash槽。
17、Redis集群的主从复制模子是怎样的?
答:为了使在部分节点失败或者大部分节点无法通信的情况下集群仍然可用,以是集群使用了主从复制模子, 每个节点都会有N-1个复制品
18、Redis集群最大节点个数是多少?
答:16384个。
这是因为Redis 集群并没有使用一致性hash,而是引入了哈希槽的概念。Redis 集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽,集群的每个节点负责一部分hash槽。
但为什么哈希槽的数量是16384(2^14)个呢?
在redis节点发送心跳包时需要把所有的槽放到这个心跳包里,以便让节点知道当前集群信息,16384=16k,在发送心跳包时使用char举行bitmap压缩后是2k(2 8 (8 bit) 1024(1k) = 16K),也就是说使用2k的空间创建了16k的槽数。
固然使用CRC16算法最多可以分配65535(2^16-1)个槽位,65535=65k,压缩后就是8k(8 8 (8 bit) 1024(1k) =65K),也就是说需要需要8k的心跳包,Redis作者以为如许做不太值得;而且一般情况下一个redis集群不会有超过1000个master节点,以是16k的槽位是个比力合适的选择。
19、Redis集群如何选择数据库?
答:Redis集群现在无法做数据库选择,默认在0数据库。
20、你能介绍一下布隆过滤器吗?
答:布隆过滤器紧张是用于检索一个元素是否在一个集合中。我们当时使用的是redisson实现的布隆过滤器。
它的底层紧张是先去初始化一个比力大数组,里面存放的二进制0或1。在一开始都是0,当一个key来了之后经过3次hash盘算,模于数组长度找到数据的下标然后把数组中原来的0改为1,如许的话,三个数组的位置就能标明一个key的存在。查找的过程也是一样的。
当然是有缺点的,布隆过滤器有大概会产生肯定的误判,我们一般可以设置这个误判率,大概不会超过5%,其实这个误判是肯定存在的,要不就得增加数组的长度,其实已经算是很划分了,5%以内的误判率一般的项目也能继承,不至于高并发下压倒数据库。
21、什么是 Redis Module?有什么用?
答:Redis 从 4.0 版本开始,支持通过 Module 来扩展其功能以满意特殊的需求。这些 Module 以动态链接库(so 文件)的情势被加载到 Redis 中,这是一种非常机动的动态扩展功能的实现方式,值得鉴戒学习!
我们每个人都可以基于 Redis 去定制化开发本身的 Module,比如实现搜索引擎功能、自界说分布式锁和分布式限流。
现在,被 Redis 官方推荐的 Module 有:
- RediSearch[11]:用于实现搜索引擎的模块。
- RedisJSON[12]:用于处置惩罚 JSON 数据的模块。
- RedisGraph[13]:用于实现图形数据库的模块。
- RedisTimeSeries[14]:用于处置惩罚时间序列数据的模块。
- RedisBloom[15]:用于实现布隆过滤器的模块。
- RedisAI[16]:用于执行深度学习/呆板学习模子并管理其数据的模块。
- RedisCell[17]:用于实现分布式限流的模块。
- ……
关于 Redis 模块的详细介绍,可以查看官方文档:https://redis.io/modules。
22、Redis中的管道有什么用?
答:一次哀求/相应服务器能实现处置惩罚新的哀求即使旧的哀求还未被相应,如许就可以将多个下令发送到服务 器,而不用等待回复,末了在一个步调中读取该答复。 这就是管道(pipelining),是一种几十年来广泛使用的技术。比方很多POP3协议已经实现支持这个功 能,大大加快了从服务器下载新邮件的过程。
23、怎么明白Redis事务?
答:事务是一个单独的隔离操作:事务中的所有下令都会序列化、按顺序地执行,事务在执行的过程中,不会 被其他客户端发送来的下令哀求所打断。 事务是一个原子操作:事务中的下令要么全部被执行,要么全部都不执行。
24、Redis 事务相关的下令有哪几个?
答:MULTI、EXEC、DISCARD、WATCH。
25、Redis key 的逾期时间和永世有用分别怎么设置?
答:EXPIRE 和PERSIST 下令。
26、Redis 如何做内存优化?
答:尽大概使用散列表(hashes),散列表(是说散列表里面存储的数少)使用的内存非常小,以是你应该 尽大概的将你的数据模子抽象到一个散列表里面。 比如你的web体系中有一个用户对象,不要为这个用户的名称,姓氏,邮箱,暗码设置单独的key,而是 应该把这个用户的所有信息存储到一张散列表里面。
27、Redis 回收进程如何工作的?
答:一个客户端运行了新的下令,添加了新的数据。 Redi 检查内存使用情况,如果大于maxmemory的限定, 则根据设定好的策略举行回收。 一个新的下令被执行,等等。 以是我们不断地穿越内存限定的边界,通过不断达到边界然后不断地回收回到边界以下。 如果一个下令的结果导致大量内存被使用(比方很大的集合的交集保存到一个新的键),不用多久内存限 制就会被这个内存使用量超越。
28、Redis 是单线程吗?
答:Redis 单线程指的是「接收客户端哀求->剖析哀求 ->举行数据读写等操作->发送数据给客户端」这个过程是由一个线程(主线程)来完成的,这也是我们常说 Redis 是单线程的原因。
但是,Redis 步伐并不是单线程的,Redis 在启动的时候,是会启动后台线程(BIO)的:
- Redis 在 2.6 版本,会启动 2 个后台线程,分别处置惩罚关闭文件、AOF 刷盘这两个任务;
- Redis 在 4.0 版本之后,新增了一个新的后台线程,用来异步开释 Redis 内存,也就是 lazyfree 线程。比方执行 unlink key / flushdb async / flushall async 等下令,会把这些删除操作交给后台线程来执行,好处是不会导致 Redis 主线程卡顿。因此,当我们要删除一个大 key 的时候,不要使用 del 下令删除,因为 del 是在主线程处置惩罚的,如许会导致 Redis 主线程卡顿,因此我们应该使用 unlink 下令来异步删除大key。
之以是 Redis 为「关闭文件、AOF 刷盘、开释内存」这些任务创建单独的线程来处置惩罚,是因为这些任务的操作都是很耗时的,如果把这些任务都放在主线程来处置惩罚,那么 Redis 主线程就很轻易发生阻塞,如许就无法处置惩罚后续的哀求了。
后台线程相当于一个消耗者,生产者把耗时任务丢到任务队列中,消耗者(BIO)不停轮询这个队列,拿出任务就去执行对应的方法即可。
关闭文件、AOF 刷盘、开释内存这三个任务都有各自的任务队列:
- BIO_CLOSE_FILE,关闭文件任务队列:当队列有任务后,后台线程会调用 close(fd) ,将文件关闭;
- BIO_AOF_FSYNC,AOF刷盘任务队列:当 AOF 日记配置成 everysec 选项后,主线程会把 AOF 写日记操作封装成一个任务,也放到队列中。当发现队列有任务后,后台线程会调用 fsync(fd),将 AOF 文件刷盘,
- BIO_LAZY_FREE,lazy free 任务队列:当队列有任务后,后台线程会 free(obj) 开释对象 / free(dict) 删除数据库所有对象 / free(skiplist) 开释跳表对象;
29、Redis 采取单线程为什么还这么快?
答:官方使用基准测试的结果是,单线程的 Redis 吞吐量可以达到 10W/每秒,如下图所示:
之以是 Redis 采取单线程(网络 I/O 和执行下令)那么快,有如下几个原因:
- Redis 的大部分操作都在内存中完成,而且采取了高效的数据结构,因此 Redis 瓶颈大概是呆板的内存或者网络带宽,而并非 CPU,既然 CPU 不是瓶颈,那么自然就采取单线程的解决方案了;
- Redis 采取单线程模子可以制止了多线程之间的竞争,省去了多线程切换带来的时间和性能上的开销,而且也不会导致死锁问题。
- Redis 采取了 I/O 多路复用机制处置惩罚大量的客户端 Socket 哀求,IO 多路复用机制是指一个线程处置惩罚多个 IO 流,就是我们经常听到的 select/epoll 机制。简单来说,在 Redis 只运行单线程的情况下,该机制允许内核中,同时存在多个监听 Socket 和已连接 Socket。内核会一直监听这些 Socket 上的连接哀求或数据哀求。一旦有哀求到达,就会交给 Redis 线程处置惩罚,这就实现了一个 Redis 线程处置惩罚多个 IO 流的效果。
30、Redis 6.0 之后为什么引入了多线程?
答:固然 Redis 的紧张工作(网络 I/O 和执行下令)一直是单线程模子,但是在 Redis 6.0 版本之后,也采取了多个 I/O 线程来处置惩罚网络哀求,这是因为随着网络硬件的性能提升,Redis 的性能瓶颈偶然会出现在网络 I/O 的处置惩罚上。
以是为了进步网络 I/O 的并行度,Redis 6.0 对于网络 I/O 采取多线程来处置惩罚。但是对于下令的执行,Redis 仍然使用单线程来处置惩罚,以是各人不要误解 Redis 有多线程同时执行下令。
Redis 官方表示,Redis 6.0 版本引入的多线程 I/O 特性对性能提升至少是一倍以上。
Redis 6.0 版本支持的 I/O 多线程特性,默认情况下 I/O 多线程只针对发送相应数据(write client socket),并不会以多线程的方式处置惩罚读哀求(read client socket)。要想开启多线程处置惩罚客户端读哀求,就需要把 Redis.conf 配置文件中的 io-threads-do-reads 配置项设为 yes。
- //读请求也使用io多线程
- io-threads-do-reads yes
复制代码 同时, Redis.conf 配置文件中提供了 IO 多线程个数的配置项。
- // io-threads N,表示启用 N-1 个 I/O 多线程(主线程也算一个 I/O 线程)
- io-threads 4
复制代码 关于线程数的设置,官方的发起是如果为 4 核的 CPU,发起线程数设置为 2 或 3,如果为 8 核 CPU 发起线程数设置为 6,线程数肯定要小于呆板核数,线程数并不是越大越好。
因此, Redis 6.0 版本之后,Redis 在启动的时候,默认情况下会额外创建 6 个线程(这里的线程数不包括主线程):
- Redis-server : Redis的主线程,紧张负责执行下令;
- bio_close_file、bio_aof_fsync、bio_lazy_free:三个后台线程,分别异步处置惩罚关闭文件任务、AOF刷盘任务、开释内存任务;
- io_thd_1、io_thd_2、io_thd_3:三个 I/O 线程,io-threads 默认是 4 ,以是会启动 3(4-1)个 I/O 多线程,用来分担 Redis 网络 I/O 的压力。
31、如何设计一个缓存策略,可以动态缓存热门数据呢?
答:由于数据存储受限,体系并不是将所有数据都需要存放到缓存中的,而只是将此中一部分热门数据缓存起来,以是我们要设计一个热门数据动态缓存的策略。
热门数据动态缓存的策略总体思绪:通过数据最新访问时间来做排名,并过滤掉不常访问的数据,只留下经常访问的数据。
以电商平台场景中的例子,现在要求只缓存用户经常访问的 Top 1000 的商品。具体细节如下:
- 先通过缓存体系做一个排序队列(比如存放 1000 个商品),体系会根据商品的访问时间,更新队列信息,越是最近访问的商品排名越靠前;
- 同时体系会定期过滤掉队列中排名末了的 200 个商品,然后再从数据库中随机读取出 200 个商品加入队列中;
- 如许当哀求每次到达的时候,会先从队列中获取商品 ID,如果掷中,就根据 ID 再从另一个缓存数据结构中读取实际的商品信息,并返回。
在 Redis 中可以用 zadd 方法和 zrange 方法来完成排序队列和获取 200 个商品的操作。
32、Redis 如何实现延迟队列?
答:延迟队列是指把当前要做的变乱,往后推迟一段时间再做。延迟队列的常见使用场景有以下几种:
- 在淘宝、京东等购物平台上下单,超过肯定时间未付款,订单会主动取消;
- 打车的时候,在规定时间没有车主接单,平台会取消你的单并提醒你暂时没有车主接单;
- 点外卖的时候,如果商家在10分钟还没接单,就会主动取消订单;
在 Redis 可以使用有序集合(ZSet)的方式来实现延迟消息队列的,ZSet 有一个 Score 属性可以用来存储延迟执行的时间。
使用 zadd score1 value1 下令就可以一直往内存中生产消息。再利用 zrangebysocre 查询符合条件的所有待处置惩罚的任务, 通过循环执行队列任务即可。
33、RDB 快照是如何实现的呢?
答:因为 AOF 日记记录的是操作下令,不是实际的数据,以是用 AOF 方法做故障规复时,需要全量把日记都执行一遍,一旦 AOF 日记非常多,势必会造成 Redis 的规复操作迟钝。
为了解决这个问题,Redis 增加了 RDB 快照。所谓的快照,就是记录某一个瞬间东西,比如当我们给风景拍照时,那一个瞬间的画面和信息就记录到了一张照片。
以是,RDB 快照就是记录某一个瞬间的内存数据,记录的是实际数据,而 AOF 文件记录的是下令操作的日记,而不是实际的数据。
因此在 Redis 规复数据时, RDB 规复数据的服从会比 AOF 高些,因为直接将 RDB 文件读入内存就可以,不需要像 AOF 那样还需要额外执行操作下令的步调才能规复数据。
RDB 做快照时会阻塞线程吗?
Redis 提供了两个下令来天生 RDB 文件,分别是 save 和 bgsave,他们的区别就在于是否在「主线程」里执行:
- 执行了 save 下令,就会在主线程天生 RDB 文件,由于和执行操作下令在同一个线程,以是如果写入 RDB 文件的时间太长,会阻塞主线程;
- 执行了 bgsave 下令,会创建一个子进程来天生 RDB 文件,如许可以制止主线程的阻塞;
Redis 还可以通过配置文件的选项来实现每隔一段时间主动执行一次 bgsave 下令,默认会提供以下配置:
- save 900 1
- save 300 10
- save 60 10000
复制代码 别看选项名叫 save,实际上执行的是 bgsave 下令,也就是会创建子进程来天生 RDB 快照文件。 只要满意上面条件的恣意一个,就会执行 bgsave,它们的意思分别是:
- 900 秒之内,对数据库举行了至少 1 次修改;
- 300 秒之内,对数据库举行了至少 10 次修改;
- 60 秒之内,对数据库举行了至少 10000 次修改。
这里提一点,Redis 的快照是全量快照,也就是说每次执行快照,都是把内存中的「所有数据」都记录到磁盘中。以是执行快照是一个比力重的操作,如果频率太频繁,大概会对 Redis 性能产生影响。如果频率太低,服务器故障时,丢失的数据会更多。
RDB 在执行快照的时候,数据能修改吗?
可以的,执行 bgsave 过程中,Redis 依然可以继承处置惩罚操作下令的,也就是数据是能被修改的,关键的技术就在于写时复制技术(Copy-On-Write, COW)。
执行 bgsave 下令的时候,会通过 fork() 创建子进程,此时子进程和父进程是共享同一片内存数据的,因为创建子进程的时候,会复制父进程的页表,但是页表指向的物理内存还是一个,此时如果主线程执行读操作,则主线程和 bgsave 子进程互相不影响。
34.使用过Redis分布式锁么,它是怎么实现的?
答:先拿setnx来争抢锁,抢到之后,再用expire给锁加一个逾期时间防止锁忘记了开释。 如果在setnx之后执行expire之前进程不测crash或者要重启维护了,那会怎么样? set 指令有非常复杂的参数,这个应该是可以同时把setnx和expire合成一条指令来用的!
35、使用过Redis做异队伍列么,你是怎么用的?有什么缺点?
答:一般使用list结构作为队列,rpush生产消息,lpop消耗消息。当lpop没有消息的时候,要得当sleep 一会再重试。 缺点: 在消耗者下线的情况下,生产的消息会丢失,得使用专业的消息队列如rabbitmq等。 能不能生产一次消耗多次呢? 使用pub/sub主题订阅者模式,可以实现1:N的消息队列。
36、什么是缓存穿透?如何制止?什么是缓存雪崩?何如制止?
答:缓存穿透 一般的缓存体系,都是按照key去缓存查询,如果不存在对应的value,就应该去后端体系查找(比如 DB)。一些恶意的哀求会故意查询不存在的key,哀求量很大,就会对后端体系造成很大的压力。这就叫 做缓存穿透。 如何制止?
1.对查询结果为空的情况也举行缓存,缓存时间设置短一点,或者该key对应的数据insert了之后清理 缓存。
2.对肯定不存在的key举行过滤。可以把所有的大概存在的key放到一个大的Bitmap中,查询时通过 该bitmap过滤。 缓存雪崩 当缓存服务器重启或者大量缓存集中在某一个时间段失效,如许在失效的时候,会给后端体系带来很大压 力。导致体系崩溃。 如何制止?
1.在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线 程查询数据和写缓存,其他线程等待。
2.做二级缓存,A1为原始缓存,A2为拷贝缓存,A1失效时,可以访问A2,A1缓存失效时间设置为 短期,A2设置为恒久 3:不同的key,设置不同的逾期时间,让缓存失效的时间点尽量均匀。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |