redis核心机制深入解析
redis的安装与使用介绍,参见redis安装与介绍。
Redis Cluster 故障转移 怎么保证数据一致性 https://www.oschina.net/question/128542_2307816
Redis主要涉及的概念包括下列几大类:
- Redis 基本数据结构详解
- Redis 高并发问题策略
- Redis 集群结构以及设计理念
- Redis 持久化机制
- Redis 应用场景设计
相关的具体要点如下:
什么是 Redis?
Redis 的特点有哪些?
Redis的灵活性允许各种不同的键构造和存储方案。Red is 性能和可维护性的优劣取决于Redis 数据库键的设计与构造。一种良好而又通用的实践是在设计Redis 键时至少起草一份粗略概要,用于描述存人Redis 中的信息及采用何种Redis 结构中的初步想法。
为什么 Redis 需要把所有数据放到内存中?
Redis 适用场景有哪些?
Redis常用的业务场景有哪些?
Memcached 与 Redis 的区别都有哪些?
更加丰富的数据结构。Memcached是多线程服务器。
Redis常用的命令有哪些?https://redis.io/commands(redis 3/4/5都增加了不少很实用的特性和命令)
get,set(Redis 2.6.12开始一个命令支持设置分布式锁),del,append,expire,expireat,ttl,object,debug object,incr,decr,eval
lrange,lpop,rpush,还有支持阻塞式pop的命令blpop、在列表间移动元素的命令
keys,需要注意keys会阻塞,不能在线上使用,可以使用scan,它慢一点,是异步的,不会影响阻塞,但是不会去重、需要客户端去重,使用更复杂。
sadd,srem,sismember,smembers,还支持集合操作如sinter,sunion,sdiff,交集、并集、差集,跟java Set一样。
hset,hget,hgetall,hdel,hincrby
zadd,zrem,zrange(返回排名在a-b之间的成员),zrangebyscore(延时队列),zincrby,以及各种降序、升序,根据排名、分值的命令,应该来说相当实用,可以用于投票、top时间戳等等。
subscribe, unsubscribe,psubscribe,punsubscribe
watch,setnx(2.6.12之后就不需要了)
Redis 是单线程的吗?
是。
Redis 为什么设计成单线程的?
因为数据全部在内存中,且使用NIO模型。redis利用队列技术将并发访问变为串行访问,消除了传统数据库串行控制的开销,也避免了不必要的上下文切换和竞争条件。
一个字符串类型的值能存储最大容量是多少?512M。Redis各个数据类型最大存储量分别是多少?
Redis 持久化机制有哪些? 区别是什么?
什么是缓存穿透?怎么解决?
缓存穿透是指查询一个一不存在的数据。例如:从缓存redis没有命中,需要从mysql数据库查询,查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到数据库去查询,造成缓存穿透。
解决方法:如果查询数据库也为空,直接设置一个默认值存放到缓存,这样第二次到缓冲中获取就有值了,而不会继续访问数据库。设置一个过期时间或者当有值的时候将缓存中的值替换掉即可。
什么是缓存击穿?如何解决?
穿透指的是一个不存在key导致的大面积同时访问DB,击穿则指的是一个存在的key失效。
解决方法:1、加分布式锁机制。2、全局维护ID集合。
什么是缓存雪崩? 怎么解决?
缓存雪崩是指数据未加载到缓存中,或者缓存同一时间大面积的失效,从而导致所有请求都去查数据库,导致数据库CPU和内存负载过高,甚至宕机。
解决方法:1、集群部署,可以使用Redis Cluster。2、降级(非核心服务下线)、二级缓存。3、Redis备份和快速预热。
缓存的更新策略有几种?分别有什么注意事项?
什么是分布式锁?有什么作用?
分布式锁可以通过什么来实现?
介绍一下分布式锁实现需要注意的事项?
Redis怎么实现分布式锁?
先拿setnx来争抢锁,抢到之后,再用expire给锁加一个过期时间防止锁忘记了释放。**如果在setnx之后执行expire之前进程意外crash或者要重启维护了,那会怎么样?**set指令有非常复杂的参数,这个应该是可以同时把setnx和expire合成一条指令来用的!也就是lua脚本。
常见的淘汰算法有哪些?
Redis 淘汰策略有哪些?
https://redis.io/topics/lru-cache
Redis 缓存失效/过期策略有哪些?很重要
Redis 默认每秒进行10 次过期扫描,为了保证过期扫描不会出现循环过度,导致结程卡死的现象,算法还增加了扫描时间的上限,默认不会超过25ms 。当客户端请求到来时,服务器如果正好进入过期扫描状态,客户端的请求将会等待至少25ms 后才会进行处理,如果客户端将超时时间设置得比较短,比如10ms ,那么就会出现大量的链接因为超时而关闭,业务端就会出现很多异常。所以业务开发人员一定要注意过期时间,如果有大批量的key 过期,要给过期时间设置一个随机范围,而不能全部在同一时间过期。
Redis 的持久化机制有几种方式?
RDB和AOF,redis 4.x开始引入了混合模式(和oracle的rman备份一样,记录备份期间的redo,然后恢复时先恢复快照,然后应用redo实现快速恢复),最大化降低恢复时间。相关配置可以参考https://www.cnblogs.com/lxwphp/p/11281066.html
如果redis实例很大,例如几十GB,那么使用bgsave创建子进程和保存快照的时间可能会很长,在虚拟化环境或非SSD环境中,甚至可能高达一二十分钟。因此对于大型实例来说,恰当的评估save的设置是非常重要的。如果可以容忍部分数据丢失,最好是在slave节点执行快照动作。
http://www.mamicode.com/info-detail-2329676.html
请介绍一下持久化机制 RDB, AOF的优缺点分别是什么?
RDB是内存数据的二进制序列化形式,在存储上非常紧凑,Redis 使用操作系统的多进程COW (Copy On Write )机制来实现快照持久化,比较耗资源,所以它并不是完整的,会丢失不少数据的修改,所以结果可能是错误的,相比缺少而言、结果错误很可能是致命的。
AOF 日志记录的是内存数据修改的指令记录文本。Redis 在长期运行的过程中, AOF 的日志会越来越长。如果实例宕机重启,重放整个AOF 曰志会非常耗时,导致Redis 长时间无法对外提供服务,所以需要对AOF进行瘦身。Red is 提供了bgrewriteaof 指令用于对AOF 曰志进行瘦身,其原理就是开辟一个子进程对内存进行遍历,转换成一系列Red is 的操作指令,序列化到一个新的AOF曰志文件中。序列化完毕后再将操作期间发生的增量AOF 日志追加到这个新的AOF日志文件中,追加完毕后就立即替代旧的AOF 曰志文件了,瘦身工作就完成了。即使如此,仍然可能很大。
AOF和数据库的redo一样,提供了缓存刷新模式,所以不同的值会存在丢数据的风险。
Redis 通讯协议是什么?有什么特点?
RESP。简单。
请介绍一下 Redis 的数据类型 SortedSet(zset) 以及底层实现机制?Redis 集群最大节点个数是多少?
多级ziplist结构,成B*结构。
Redis 集群的主从复制模型是怎样的?
,运行中加入的时候,这是需要注意的,否则会导致客户端无响应,redis 4.x进行了优化,直接socket发送(如果从节点重启本地就有rdb,怎么样?)。
redis不支持MM复制(mysql的galera cluster支持)。
Redis Cluster 可以为每个主节点设置若干个从节点,当主节点发生故障时,集群会自动将其中某个从节点提升为主节点。如果某个主节点没有从节点,那么当它发生故障时,集群将完全处于不可用状态。不过Redis 也提供了一个参数clusterrequire-full-coverage 可以允许部分节点发生故障,其他节点还可以继续提供对外访问。除此之外,Redis Cluster 提供了一种选项cluster-node-timeout , 表示当某个节点持续timeout 的时间失联时,才可以认定该节点出现故障,需要进行主从切换。如果没有这个选项,网络抖动会导致主从频繁切换(数据的重新复制)。
redis集群主从切换的相关原理以及案例参见https://www.cnblogs.com/amei0/p/8177076.html,https://blog.csdn.net/Aquester/article/details/85936185
Redis 如何做内存优化?
Redis 事务相关命令有哪些?
Redis 事务在形式上看起来也差不多,指令分别是multi、exec、discard。multi指示事务的开始, exec 指示事务的执行, discard 指示事务的丢弃。
Redis 事务的注意点有哪些?
只是一种串行化执行机制,并非ACID所定义的事务。
Redis 为什么不支持回滚?
Redis 的事务根本不具备“原子性” ,而仅仅是满足了事务的“隔离性”中的串行化-一当前执行的事务有着不被其他事务打断的权利。事务在遇到指令执行失败后,后面的指令还会继续执行。
请介绍一下 Redis 集群实现方案
Redis Cluster是去中心化的,每个节点负责整个集群的一部分数据,每个节点负责的数据多少可能不一样。这些节点相互连接组成一个对等的集群,它们之间通过一种特殊的二进制协议交互集群信息。如下:
为了保证高可用性,每个节点本身通常又部署成m-s模式,所以一共有6节点,如下:
当Redis Cluster 的客户端来连接集群时,也会得到一份集群的槽位配置信息。这样当客户端要查找某个key 时,可以直接定位到目标节点(即:客户端路由方式Twemproxy则是中间件路由,中间件架构最成功的模式,没落是社区更新不及时)。这种模式不同于经过代理查找目标服务节点,直接在客户端完成了,避免了单点失败。Re di s Clu s ter 默认会对key 值使用crcl 6 算法进行hash ,得到-个整数值,然后用这个整数值对16 384 进行取模来得到具体槽位。Redis Cluster 还允许用户强制把某个key 挂在特定槽位上。通过在key 字符串里面嵌入tag 标记, 这就可以强制key 所挂的槽位等于tag 所在的槽位。
请介绍一下 Redis 常见的业务使用场景?
参见redis安装与介绍。
Redis 集群会有写操作丢失吗?为什么?
请介绍一下 Redis 的 Pipeline (管道),以及使用场景
当我们使用客户端对Redis 进行一次操作时,客户端将请求传送给服务器,服务器处理完毕后,再将晌应回复给客户端。这要花费一个网络数据包来回的时间。如果连续执行多条指令,那就会花费多个网络数据包来固的时间。通过管道可以将网络交互次数从N降低为1。从而大幅度提升性能,在redis没有到100%之前,增加每个管道中的命令数可以持续提升redis的tps。最典型的就是如缓存了id->userInfo,name->id,此时就可以网络次数从,2降低为1,一次性保存一个用户的信息。但是可以根据返回值执行查找吗?
请说明一下 Redis 的批量命令与 Pipeline 有什么不同?
两者都是为了提升性能。批量命令如mget,hmget常用于针对相同的数据结构执行多个命令,且仅仅发送了一次网络请求。pipeline则支持异步发送模式,请求、应答数不会减少(这和上面的描述不一致啊??);默认情况下(即pipeline的参数为true),这就是事务中多个命令一次性执行的实现方式。
Redis 慢查询是什么?通过什么配置?
参见redis安装与介绍。注:redis的慢查询指的是逻辑处理过程慢,不包含等待时间。
Redis 的慢查询修复经验有哪些? 怎么修复的?
请介绍一下 Redis的发布订阅功能
fanout模式的mq,不通过lpop/lpush分区模式,它支持一条消息发送给所有的订阅者。必须先启动消费者,然后再执行生产者。因为Pub Sub 的生产者传递过来一个消患, Redis 会直接找到相应的消费者传递过去。如果一个消费者都没有,那么消息会被直接丢弃。如果开始有三个消费者, 个消费者突然挂掉了,生产者会继续发送消息,另外两个消费者可以持续收到消息,但是当挂掉的消费者重新连上的时候,在断连期间生产者发送的消息,对于这个消费者来说就是彻底丢失了。还要注意客户端缓存超出导致丢数据。
如果Redis 停机重启, PubSub 的消息是不会持久化的,毕竟Redis 看机就相当于一个消费者都没有,所有的消息会被直接丢弃。正是因为Pub Sub 有这些缺点,在消息队列的领域它几乎找不到合适的应用场景。redis 5.0引入了新的Stream(借鉴了kafka的设计思想)数据类型,支持消息的持久化。
请介绍几个可能导致 Redis 阻塞的原因
一些特殊的全key扫描,如keys a*
怎么去发现 Redis 阻塞异常情况?
如何发现大对象
在redis 4.x中,增加了memory命令,极大地简化了大对象的查找。参见:https://blog.csdn.net/yunqishequ1/article/details/78751492
Redis 的内存消耗分类有哪些?内存统计使用什么命令?
参见https://blog.csdn.net/yunqishequ1/article/details/78751492
简单介绍一下 Redis 的内存管理方式有哪些?如何设置 Redis 的内存上限?有什么作用?淘汰策略(很重要)
Redis 提供了配置参数maxmemory来限制内存超出期望大小。
当实际内存超出maxmemory时, Redis 提供了几种可选策略( maxmemory-policy)来让用户自己决定该如何腾出新的空间以继续提供读写服务。
1. noeviction :不会继续服务写请求( del 请求可以继续服务),读请求可以继续进行。这样可以保证不会丢失数据,但是会让线上的业务不能持续进行。这是默认的淘汰策略。
2. volatile-lru : 尝试淘汰设置了过期时间的key,最少使用的key 优先被淘汰。没有设置过期时间的k巳y 不会被淘汰,这样可以保证需要持久化的数据不会突然丢失。
3 . volatile-ttl :跟上面几乎一样,不过淘汰的策略不是LRU ,而是比较key 的剩余寿命时的值,忧l 越小越优先被淘汰。
4. volatile-random :跟上面几乎一样,不过淘汰的key 是过期key 集合中随机的key 。
5. allkeys-lru :区别于volatile-lru ,这个策略要淘汰的key 对象是全体的key 集合,而不只是过期的key 集合。这意昧着-些没有设置过期时间的key 也会被淘汰。
6. allkeys-random :跟上面几乎一样,不过淘汰的key 是随机的key 。
什么是 bigkey? 有什么影响?
怎么发现bigkey?
冷热数据表示什么意思?
缓存命中率表示什么?
怎么提高缓存命中率?
如何优化 Redis 服务的性能?
如何实现本地缓存?请描述一下你知道的方式
请介绍一下 Spring 注解缓存
如果 AOF 文件的数据出现异常,Redis服务怎么处理?
有几个参数可以控制其行为。
aof-load-truncated yes:如果AOF文件结尾损坏,Redis启动时是否仍载入AOF文件
Redis 的主从复制模式有什么优缺点?
从节点不会进行过期扫描,从节点对过期的处理是被动的。主节点在key 到期时,会在AOF 文件里增加一条del 指令,同步到所有的从节点,从节点通过执行这条del 指令来删除过期的key 。因为指令同步是异步进行的,所以如果主节点过期的key 的del 指令没有及时同步到从节点的话,就会出现主从数据的不-致,主节点没有的数据在从节点里还存在,比如上一节的集群环境分布式锁的算法漏洞就是因为这个同步延迟产生的。
Redis sentinel (哨兵) 模式优缺点有哪些?
在复制的基础上,哨兵实现了自动化的故障恢复。缺陷:写操作无法负载均衡;存储能力受到单机的限制。
Redis 集群架构模式有哪几种?
如何设置 Redis 的最大连接数?查看Redis的最大连接数?查看Redis的当前连接数?
Redis 的链表数据结构的特征有哪些?
请介绍一下 Redis 的 String 类型底层实现?
Redis 的 String 类型使用 SSD 方式实现的好处?
设计一下在交易网站首页展示当天最热门售卖商品的前五十名商品列表?
spring redis读写分离配置
redis与数据库的双写一致性
先读缓存,后读数据库。先写数据库,后写缓存(懒写模式)。https://blog.csdn.net/qq_35190492/article/details/103004235
参考:《Redis 深度历险:核心原理与应用实践》、《Redis实战》、吐血整理60个Redis面试题、redis面试常见的10个问题,跳表可参考:https://segmentfault.com/a/1190000020596941、https://zhuanlan.zhihu.com/p/92536201、https://www.cnblogs.com/Elliott-Su-Faith-change-our-life/p/7545940.html
redis开发最佳实践:https://blog.csdn.net/lavorange/article/details/90743392,最主要是1、节省内存;2、减少网络交互;3、注意单次操作大小控制,避免redis单线程pending。
redis 大value的问题,参考https://www.v2ex.com/t/353568,https://www.lmlphp.com/user/418/article/item/30305/(主要是hash取模,找个好的算法,和并行一个道理)。实际上我们在SSD上测试下来,从开始,value的增大对于set而言线性下降,从接近10K开始,get影响不大。
[root@ta5host bin]# ./redis-benchmark -t get,set -n 1000000 -d 10000 ====== SET ====== 1000000 requests completed in 13.02 seconds 50 parallel clients 10000 bytes payload keep alive: 1 100.00% <= 1 milliseconds 100.00% <= 1 milliseconds 76804.91 requests per second ====== GET ====== 1000000 requests completed in 10.56 seconds 50 parallel clients 10000 bytes payload keep alive: 1 100.00% <= 1 milliseconds 94688.01 requests per second [root@ta5host bin]# ./redis-benchmark -t get,set -n 1000000 -d 8000 ====== SET ====== 1000000 requests completed in 9.30 seconds 50 parallel clients 8000 bytes payload keep alive: 1 100.00% <= 1 milliseconds 100.00% <= 1 milliseconds 107492.20 requests per second