揭秘Redis面试内幕

1.什么是Redis持久化?Redis有哪几种持久化方式?优缺点是什么?

持久化就是把内存的数据写到磁盘中去,防止服务宕机了内存数据丢失。

Redis 提供了两种持久化方式:RDB(默认) 和AOF

RDB核心函数RDBSave(生成RDB文件)和RDBLoad(从文件加载内存)两个函数,按照一定的时间周期策略把内存的数据以快照的形式保存到硬盘的二进制文件。即Snapshot快照存储,对应产生的数据文件为dump.rdb,通过配置文件中的save参数来定义快照的周期。

AOF:Redis会将每一个收到的写命令都通过Write函数追加到文件最后,当Redis重启是会通过重新执行文件中保存的写命令来在内存中重建整个数据库的内容。 当两种方式同时开启时,数据恢复Redis会优先选择AOF恢复。

二.Redis 有哪些架构模式?

单机版

问题:

特点:简单

1、内存容量有限 2、处理能力有限 3、无法高可用。

主从复制

Redis的主从复制(replication)是异步的,其中被复制的服务器为主服务器(master),而通过复制创建出来的服务器复制品则为从服务器(slave)。 只要主从服务器之间的网络连接正常,主从服务器两者会具有相同的数据,主服务器就会一直将发生在自己身上的数据更新同步 给从服务器,从而一直保证主从服务器的数据相同。主从复制,读写分离,主数据库可以进行读写操作,当发生写操作的时候自动将数据同步到从数据库,而从数据库一般是只读的,并接收主数据库同步过来的数据,一个主数据库可以有多个从数据库,而一个从数据库只能有一个主数据库。

特点:

1、master/slave 数据相同

2、降低 master 读压力,客户端可以从slave读取数据

问题:

无法保证高可用

没有解决 master 写的压力

哨兵

Redis sentinel 是一个分布式系统中监控 redis 主从服务器,并在主服务器下线时自动进行故障转移。其中三个特性:

监控(Monitoring): Sentinel 会不断地检查你的主服务器和从服务器是否运作正常。

提醒(Notification): 当被监控的某个 Redis 服务器出现问题时, Sentinel 可以通过 API 向管理员或者其他应用程序发送通知。

自动故障迁移(Automatic failover): 当一个主服务器不能正常工作时, Sentinel 会开始一次自动故障迁移操作。

特点:

1、保证高可用

2、监控各个节点

3、自动故障迁移

缺点:主从模式,切换需要时间丢数据

没有解决 master 写的压力

集群(proxy 型):

添加了Twemproxy代理服务器,需要维护代理服务器的高可用。

集群(直连型):

redis-cluster集群,Redis-Cluster采用无中心结构,每个节点保存数据和整个集群状态,每个节点都和其他所有节点连接。

特点:

1、无中心架构(不存在哪个节点影响性能瓶颈),少了 proxy 层。

2、数据按照 slot 存储分布在多个节点,节点间数据共享,可动态调整数据分布。

3、可扩展性,可线性扩展到 1000 个节点,节点可动态添加或删除。

4、高可用性,部分节点不可用时,集群仍可用。通过增加 Slave 做备份数据副本

5、实现故障自动 failover,节点之间通过 gossip 协议交换状态信息,用投票机制完成 Slave到 Master 的角色提升。

缺点

1、资源隔离性较差,容易出现相互影响的情况。

2、数据通过异步复制,不保证数据的强一致性

三.Redis分布式锁

定义:

线程锁:主要用来给方法、代码块加锁。当某个方法或代码使用锁,在同一时刻仅有一个线程执行该方法或该代码段。线程锁只在同一JVM中有效果,因为线程锁的实现在根本上是依靠线程之间共享内存实现的,比如synchronized是共享对象头,显示锁Lock是共享某个变量(state)。

进程锁:为了控制同一操作系统中多个进程访问某个共享资源,因为进程具有独立性,各个进程无法访问其他进程的资源,因此无法通过synchronized等线程锁实现进程锁。

分布式锁:当多个进程不在同一个系统中,用分布式锁控制多个进程对资源的访问。

如果是单机情况下(单JVM),线程之间共享内存,只要使用线程锁就可以解决并发问题。

如果是分布式情况下(多JVM),线程A和线程B很可能不是在同一JVM中,这样线程锁就无法起到作用了,这时候就要用到分布式锁来解决。

分布式锁实现:

分布式锁一般有三种实现方式:1. 数据库乐观锁;2. 基于Redis的分布式锁;3. 基于ZooKeeper的分布式锁。

分布式锁实现的关键是在分布式的应用服务器外,搭建一个存储服务器,存储锁信息,这时候我们很容易就想到了Redis。首先我们要搭建一个Redis服务器,用Redis服务器来存储锁信息。

在实现的时候要注意的几个关键点:

1、锁信息必须是会过期超时的,不能让一个线程长期占有一个锁而导致死锁;

2、同一时刻只能有一个线程获取到锁。

3. 加锁和解锁必须是同一个客户端,客户端自己不能把别人加的锁给解了

几个要用到的redis命令:

setnx(key, value):“set if not exits”,若该key-value不存在,则成功加入缓存并且返回1,否则返回0。

get(key):获得key对应的value值,若不存在则返回nil。

getset(key, value):先获取key对应的value值,若不存在则返回nil,然后将旧的value更新为新的value。

expire(key, seconds):设置key-value的有效期为seconds秒。

先拿setnx来争抢锁,抢到之后,再用expire给锁加一个过期时间防止锁忘记了释放。

如果在setnx之后执行expire之前进程意外crash或者要重启维护了,那会怎么样?

set指令有非常复杂的参数,这个应该是可以同时把setnx和expire合成一条指令来用的!

四。Redis做异步队列

一般使用list结构作为队列,rpush生产消息,lpop消费消息。

pub/sub主题订阅者模式,可以实现1:N的消息队列。

五。

缓存穿透:大量并发请求一个不存的key,缓存查不到去后端数据库寻找,造成对后端的压力。

缓解:加一个布隆过滤器,将可能存在的key映射到一个大的bitmap上,将一定不存在的key请求过滤掉。

缓存雪崩:缓存重启或者大量缓存失效时会客户端的大量请求会直接施加在后端数据库,导致系统崩溃。

对线程加锁,控制线程访问数据库的数量;将缓存失效时间均匀分散开;二级缓存,新开辟一个缓存拷贝原始缓存,当原始缓存失效时访问备用缓存。

缓存预热:系统上线后,将相关的缓存数据直接加载到缓存系统。这样就可以避免在用户请求的时候,先查询数据库,然后再将数据缓存的问题!用户直接查询事先被预热的缓存数据!

缓存更新:及时更新缓存中的数据,需要一定的缓存失效策略,常见的策略有两种:

(1)定时去清理过期的缓存; (2)当有用户请求过来时,再判断这个请求所用到的缓存是否过期,过期的话就去底层系统得到新数据并更新缓存。

缓存降级:降级是在服务器流量暴增的情况下,有取舍的对部分页面及功能有策略地降低其服务水准,已释放服务资源保证核心业务正常运行。服务降级的目的,是为了防止Redis服务故障,导致数据库跟着一起发生雪崩问题。因此,对于不重要的缓存数据,可以采取服务降级策略。

六。热点数据 冷数据

热点数据,缓存才有价值,将热点数据同步保存到Redis缓存,减少数据库压力。

冷数据,大部分数据可能还没有再次访问到就已经被挤出内存,缓存价值不大。

七。Memcache与Redis的区别

1、存储方式:Memecache把数据全部存在内存之中,断电后会挂掉,数据不能超过内存大小。

Redis有部分存在硬盘上,redis可以持久化其数据。

2、数据支持类型:memcached所有的值均是简单的字符串,redis作为其替代者,支持更为丰富的数据类型 ,提供list,set,zset,hash等数据结构的存储

3、value 值大小不同:Redis 最大可以达到 512M;memcache 只有 1mb。

4、redis的速度比memcached快很多 5、Redis支持数据的备份,即master-slave模式的数据备份。

八.单线程的redis为什么这么快

1、纯内存操作

2、单线程操作,避免频繁的上下文切换

九.redis的数据类型,以及每种数据类型的使用场景

list:消息队列,在消费者和生产者场景中应用比较多,list可以很好地实现先进先出的原则。

set:不重复数据,可以做全局去重,实现交集并集差集

sorted set:集合元素能够根据score进行排列,可以做排行榜应用。

十.redis的过期策略以及内存淘汰机制

redis采用的是定期删除+惰性删除策略。 定期删除:定期删除,redis默认每个100ms检查,随机抽取进行检查是否有过期的key,有过期key则删除。

惰性删除:定期删除会导致有些过期的key没有被检查到而没被删除,惰性删除会在访问key时检查是否过期,如果过期了此时就会删除。

问题:如果定期删除没删除key。然后你也没及时去请求key,也就是说惰性删除也没生效。这样,redis的内存会越来越高。那么就应该采用内存淘汰机制。

volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰

volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰 volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰 allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰 allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰

十一.redis集群环境中,有多个子系统去set一个key,解决方式:

(1)如果对这个key操作,不要求顺序: 准备一个分布式锁,大家去抢锁,抢到锁就做set操作即可 (2)如果对这个key操作,要求顺序: 分布式锁+时间戳。 假设这会系统B先抢到锁,将key1设置为{valueB 3:05}。接下来系统A抢到锁,发现自己的valueA的时间戳早于缓存中的时间戳,那就不做set操作了。以此类推。 (3) 采用队列模式将并发访问变成串行访问,将set方法变成串行访问。 实际上,对redis的操作都是具有原子性的,是线程安全的操作,你不用考虑并发问题,

十二.Redis实现分布式锁

Redis中可以使用SETNX命令实现分布式锁。

将 key 的值设为 value ,当且仅当 key 不存在。 若给定的 key 已经存在,则 SETNX 不做任何动作

解锁:使用 del key 命令就能释放锁

解决死锁: 1)通过Redis中expire()给锁设定最大持有时间,如果超过,则Redis来帮我们释放锁。 2) 使用 setnx key “当前系统时间+锁持有的时间”和getset key “当前系统时间+锁持有的时间”组合的命令就可以实现。

十三.Redis事务

Redis事务功能是通过MULTI、EXEC、DISCARD和WATCH 四个原语实现的,Redis中的事务保证了批量操作的原子性 Redis会将一个事务中的所有命令序列化,然后按顺序执行。

1)MULTI命令用于开启一个事务,它总是返回OK。 MULTI执行之后,客户端可以继续向服务器发送任意多条命令,这些命令不会立即被执行,而是被放到一个队列中,当EXEC命令被调用时,所有队列中的命令才会被执行。 2)EXEC:执行所有事务块内的命令。返回事务块内所有命令的返回值,按命令执行的先后顺序排列。 当操作被打断时,返回空值 nil 。 3)通过调用DISCARD,客户端可以清空事务队列,并放弃执行事务, 并且客户端会从事务状态中退出。 4)WATCH 命令可以为 Redis 事务提供 check-and-set (CAS)行为。 可以监控一个或多个键,一旦其中有一个键被修改(或删除),之后的事务就不会执行,监控一直持续到EXEC命令。 为了保证批量操作或多个操作的原子性,也可以通过Redis+Lua的方式实现。

十四.Redis 常见性能问题和解决方案?

(1) Master 最好不要做任何持久化工作,如 RDB 内存快照和 AOF 日志文件 (2) 如果数据比较重要,某个 Slave 开启 AOF 备份数据,策略设置为每秒同步一次 (3) 为了主从复制的速度和连接的稳定性, Master 和 Slave 最好在同一个局域网内 (4) 尽量避免在压力很大的主库上增加从库 (5) 主从复制不要用图状结构,用单向链表结构更为稳定,即: Master <- Slave1 <- Slave2 <- Slave3…

十五.redis处理大量请求

redis是一个单线程程序,也就说同一时刻它只能处理一个客户端请求; redis是通过IO多路复用来处理多个客户端请求的,

I/O 多路复用程序总是会将所有产生事件的套接字都入队到一个队列里面, 然后通过这个队列, 以有序(sequentially)、同步(synchronously)、每次一个套接字的方式向文件事件分派器传送套接字: 当上一个套接字产生的事件被处理完毕之后(该套接字为事件所关联的事件处理器执行完毕), I/O 多路复用程序才会继续向文件事件分派器传送下一个套接字。如果一个套接字又可读又可写的话, 那么服务器将先读套接字, 后写套接字.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值