一、缓存雪崩
为什么使用缓存?
1.提高性能:缓存查询速度比数据库查询速度快(内存vs硬盘)。
2.提高并发能力:缓存分担了部分请求,支持更高的并发。
redis存储的数据和内存占用是有限的,因此我们才需要对数据设置过期时间,并采用惰性删除+定期删除策略清除过期键,释放内存。如果数据缓存的过期时间是相同的,redis正好把这部分数据清掉或者redis服务器出现故障,缓存失效请求全部走数据库,这种现象就是缓存雪崩。缓存雪崩可能导致数据库被搞垮,导致整个系统直接崩溃。
如何解决缓存雪崩?
二、缓存穿透
当查询一个一定不存在的数据,由于缓存不命中,去查询数据库也无法查询出结果,因此不会写入到缓存中,这会导致每个查询都去请求数据库,造成缓存穿透。
解决方案:
三、缓存并发
高并发场景下同时查询大量查询过期的key值,最后查询数据库将缓存结果写到缓存、造成数据库压力过大。
解决方案:互斥锁 对锁不了解的可以查看初始锁的世界文章。
四、缓存和数据库双写一致性
数据库与缓存读写模式策略
写完数据库后是否需要马上更新缓存还是直接删除缓存?
一般的策略是当更新数据时,先删除缓存,再更新数据库,而不是更新缓存,等要查询的时候才把最新的数据更新到缓存。
常见数据库与缓存双写情况导致数据不一致的场景和解决方案。
保证数据一致的方案:
1. databus
Databus是一个低延迟、可靠的、支持事务的、保持一致性的数据变更抓取系统。由LinkedIn于2013年开源。Databus通过挖掘数据库日志的方式,将数据库变更实时、可靠的从数据库拉取出来,业务可以通过定制化client实时获取变更并进行其他业务逻辑。搭建过程简述:下载ojdbc6.jar然后复制放在sandbox-repo/com/oracle/ojdbc6/11.2.0.2.0/,然后重命名ojdbc6-11.2.0.2.0.jar,构建需要gradle支持。
2. 阿里的canal监听binglog进行更新。
canal是阿里巴巴旗下的一款开源项目,纯Java开发。基于数据库增量日志解析,提供增量数据订阅&消费,目前主要支持了MySQL(也支持mariaDB)。
如何使用redis做一个消息队列?
redis知识查缺补漏---面试题
特点:简单
缺点: 内存容量有限 处理能力有限 无法高可用
主从复制
Redis 的复制(replication)功能允许用户根据一个 Redis 服务器来创建任意多个该服务器的复制品,其中被复制的服务器为主服务器(master),而通过复制创建出来的服务器复制品则为从服务器(slave)。 只要主从服务器之间的网络连接正常,主从服务器两者会具有相同的数据,主服务器就会一直将发生在自己身上的数据更新同步 给从服务器,从而一直保证主从服务器的数据相同。
特点:master/slave角色 master/slave数据相同 降低master读压力转交salve分担。
缺点:无法保证高可用 没有解决 master写的压力
哨兵模式:
Redis sentinel 是一个分布式系统中监控 redis 主从服务器,并在主服务器下线时自动进行故障转移。其中三个特性:
监控(Monitoring):Sentinel 会不断地检查你的主服务器和从服务器是否运作正常。
提醒(Notification):当被监控的某个 Redis 服务器出现问题时, Sentinel 可以通过 API 向管理员或者其他应用程序发送通知。
自动故障迁移(Automatic failover):当一个主服务器不能正常工作时, Sentinel 会开始一次自动故障迁移操作。
特点:保证高可用 监控各个节点 自动故障迁移
缺点:主从模式切换需要时间可能会丢数据 没有解决master写的压力。
集群(proxy)型
Twemproxy是一个 Twitter 开源的一个 redis 和 memcache 快速/轻量级代理服务器;Twemproxy是一个快速的单线程代理程序,支持 Memcached ASCII 协议和 redis 协议。
特点:多种hash算法:MD5、CRC16、CRC32、CRC32a、hsieh、murmur、Jenkins 支持失败节点自动删除 后端sharding分片逻辑对业务透明,业务方的读写方式和操作单个redis一致。
缺点:增加了新的proxy,需要维护其高可用 failover 逻辑需要自己实现,其本身不能支持故障的自动转移可扩展性差,进行扩缩容都需要手动干预。
集群直连型:
从redis 3.0之后版本支持redis-cluster集群,Redis-Cluster采用无中心结构,每个节点保存数据和整个集群状态,每个节点都和其他所有节点连接。
特点: 1.无中心架构(不存在哪个节点影响性能瓶颈),少了 proxy 层。
2.数据按照 slot 存储分布在多个节点,节点间数据共享,可动态调整数据分布
3.可扩展性,可线性扩展到 1000 个节点,节点可动态添加或删除。
4.高可用性,部分节点不可用时,集群仍可用。通过增加 Slave 做备份数据副本
5.实现故障自动 failover,节点之间通过 gossip 协议交换状态信息,用投票机制完成 Slave到 Master 的角色提升。
缺点:资源隔离性较差,容易出现相互影响的情况和数据通过异步复制,不保证数据的强一致性。
9.redis集群如何选择数据库?
redis集群目前无法做数据库选择,默认在0数据库。
10. redis集群之间如何复制的?最大节点个数是多少?
异步复制 16384个
11. redis 内存如何做优化?
能用散列表存储就优先选择,占用的内存小。如果要保持用户的基本信息,直接用散列保存,不要为每个属性单独设key。
12.redis回收使用的是什么算法?
LRU算法
13.redis回收进程如何工作的?
一个客户端运行了新的命令,添加了新的数据。
Redis检查内存使用情况,如果大于maxmemory的限制, 则根据设定好的策略进行回收。
一个新的命令被执行,等等。
所以我们不断地穿越内存限制的边界,通过不断达到边界然后不断地回收回到边界以下。
如果一个命令的结果导致大量内存被使用(例如很大的集合的交集保存到一个新的键),不用多久内存限制就会被这个内存使用量超越。
14.redis如何做大量数据插入?
redis2.6开始redis-cli支持pipe model模式,提供大量数据的插入。
15.redis为什么要分区?
分区可以让redis管理更大的内存,redis将可以使用所有机器的内存。如果没有分区,最多只能使用一台机器的内存。分区使redis的计算能力通过简单地增加计算机得到成倍提升,redis的网络带宽也会随着计算机和网卡的增加而成倍增长。
16.redis分区方案有哪些?
客户端分区:在客户端已经决定数据会被存储到哪个redis节点或者从哪个redis节点读取。大多数客户端已经实现了客户端分区。
代理分区:客户端将请求发送给代理,然后代理决定去哪个节点写数据或者读数据。代理根据分区规则决定请求哪些redis实例,然后根据redis的响应结果返回客户端。redis和memcache的一种代理实现就是twemproxy。
查询路由(query routing):客户端随机地请求任意一个redis实例,然后由redis将请求转发给正确的redis节点。redis cluster实现了一个混合形式的查询路由,并不是直接将请求从一个redis节点转发到另一个redis节点,而是在客户端的帮助下直接redirected到正确的节点。
17.redis分区有什么缺点?
涉及多个key的操作通常不会被支持。如不能直接使用交集指令对俩个集合求交集,因为集合存储的redis实例可能不同。
操作多个key不能使用redis事务。
分区使用的粒度是key,不能使用一个非常长的排序key存储一个数据集。(The partitioning granularity is the key, so it is not possible to shard a dataset with a single huge key like a very big sorted set.)
当使用分区的时候,数据处理会非常复杂。例如为了备份必须从不同的redis实例和主机同时收集rdb/apf文件。
分区时动态扩容或缩容可能非常复杂。redis集群在运行时增加或者删除redis节点,能做到最大程度对用户透明地数据再平衡,但其他一些客户端分区或者代理分区则不支持这种特性,可以使用预分片技术来解决。
18.redis持久化数据和缓存如何做扩容?
如果Redis被当做缓存使用,使用一致性哈希实现动态扩容缩容。
如果Redis被当做一个持久化存储使用,必须使用固定的keys-to-nodes映射关系,节点的数量一旦确定不能变化。否则的话(即Redis节点需要动态变化的情况),必须使用可以在运行时进行数据再平衡的一套系统,而当前只有Redis集群可以做到这样。
19.分布式redis是前期做还是后期规模上来再做?为什么?
Redis是如此的轻量(单实例只使用1M内存),为防止以后的扩容,最好就是一开始就启动较多实例。即便你只有一台服务器,一开始就让Redis以分布式的方式运行,使用分区,在同一台服务器上启动多个实例。
一开始就多设置几个Redis实例,例如32或者64个实例,对大多数用户来说这操作起来可能比较麻烦,但是从长久来看做这点牺牲是值得的。
当你的数据不断增长,需要更多的Redis服务器时,你需要做的就是仅仅将Redis实例从一台服务迁移到另外一台服务器而已(而不用考虑重新分区的问题)。一旦你添加了另一台服务器,你需要将你一半的Redis实例从第一台机器迁移到第二台机器。
20.Twemproxy是什么?
Twemproxy是Twitter维护的(缓存)代理系统,代理Memcached的ASCII协议和Redis协议。它是单线程程序,使用c语言编写,运行起来非常快。它是采用Apache 2.0 license的开源软件。Twemproxy支持自动分区,如果其代理的其中一个Redis节点不可用时,会自动将该节点排除(这将改变原来的keys-instances的映射关系,所以你应该仅在把Redis当缓存时使用Twemproxy)。Twemproxy本身不存在单点问题,因为你可以启动多个Twemproxy实例,然后让你的客户端去连接任意一个Twemproxy实例。Twemproxy是Redis客户端和服务器端的一个中间层,由它来处理分区功能应该不算复杂,并且应该算比较可靠的。
21.支持一致性哈希的客户端有哪些?
redis-rb predis
22.redis是单线程的,如何提高多核cpu的利用率?
可以在同一个服务器部署多个redis的实例,当成不同的服务器来使用。在某些时候,无论如何一个服务器是不够的,所以你想使用多个cpu,可以考虑分片(shard)。
23.一个redis实例最多能存放多少的keys?list、set、sorted set最多能存放多少元素?
一个redis至少能存2亿5千万的keys。任何list、set、sorted set都可以存放232个元素。redis的存储极限主要还是取决于系统的可用内存值。
24.redis常见性能问题和解决方案?
(1) Master最好不要做任何持久化工作,如RDB内存快照和AOF日志文件
(2) 如果数据比较重要,某个Slave开启AOF备份数据,策略设置为每秒同步一次。
(3) 为了主从复制的速度和连接的稳定性,Master和Slave最好在同一个局域网内。
(4) 尽量避免在压力很大的主库上增加从库。
(5) 主从复制不要用图状结构,用单向链表结构更为稳定,即:Master <- Slave1 <- Slave2 <- Slave3...
这样的结构方便解决单点故障问题,实现Slave对Master的替换。如果Master挂了,可以立刻启用Slave1做Master,其他不变。
25.redis如何实现延迟任务?
我们知道zset本质就是set结构上加了排序功能,当添加或者修改元素,会按照score值进行排序。如果score代表是执行时间的时间戳,某个时间加入到zset集合中就会排序,然后写一个死循环不断取第一个key值,如果当前时间戳大于key的时间戳就取出来消费删除,这样就可以执行延迟任务的目的,而且不需要遍历整个zset,造成性能浪费。
本文主要介绍了redis一些比较经典的面试题,通过这些题目有助于大家更好的理解redis。如果觉得还不错的小伙伴请关注我,后面持续会推出好文。
如果小伙伴们还想要其他面试题和资料的话,欢迎关注公众号:
努力不一定有结果,但是不努力一定不会有结果。