一、redis持久化机制
Redis是一个支持持久化的内存数据库,通过持久化机制把内存中的数据同步到硬盘文件来保证数据持久化。当Redis重启后通过把硬盘文件重新加载到内存,就能达到恢复数据的目的。
过程:单独创建fork()一个子进程,将当前父进程的数据库数据复制到子进程的内存中,然后由子进程写入到临时文件中,持久化的过程结束了,再用这个临时文件替换上次的快照文件,然后子进程退出,内存释放。
持久化方式:
- RDB:Redis默认的持久化方式,按照一定的时间周期策略把内存的数据以快照的形式保存到硬盘的二进制文件。产生数据文件为dump.rdb,通过配置文件中的save参数来定义快照的周期。
- AOF:将Redis收到的每一个写命令通过Write函数追加到文件末尾,Redis重启是会通过执行文件中的写命令恢复数据。
二、缓存雪崩
指的是大量缓存设置了相同的缓存过期时间,即大量的缓存会在同一时间过期,此时数据库服务器的CPU和内存承受不住,造成数据库宕机,从而导致系统崩溃。
解决方案:
- 常用的解决方案是对数据库加锁,或者设计数据库队列,保证同一时间不会有大量的线程对数据库进行读写操作
- 将缓存的失效时间分开
三、缓存穿透
是指用户线程查询的数据在数据库中不存在,那么在缓存中自然也不会存在。但是按照正常的缓存逻辑,还是首先会去查询缓存,缓存没有的时候再查询数据库,从而造成两次毫无意义的查询开销,即缓存命中率。
解决方案:
- 使用布隆过滤器:即将所有可能存在的数据放到一个足够大的bitmap中,那么这时候如果在map中没有查询到,在数据库也不会有,直接返回空即可
- 在第一次查询数据库时如果返回结果为空,我们同样在redis中创建一个这样的缓存,并给他设置较小的过期时间,比如5分钟,那么第二次查询的时候就不必访问数据库了。
四、Memcache与Redis的区别都有哪些?
存储方式:
- Memecache把数据全部存在内存之中,断电后会挂掉,数据不能超过内存大小
- Redis有部份存在硬盘上,redis可以持久化其数据
数据支持类型:
- memcached所有的值均是简单的字符串
- redis支持更丰富的数据类型:list,set,zset,hash等
value最大值不同:
- memcache 只有 1mb
- Redis 最大可以达到 512M
Redis支持数据的备份,即master-slave模式的数据备份。
六、单线程的redis操作为什么这么快
- 纯内存操作,内存的执行效率本身就非常快
- 单线程操作,避免了频繁的上下文切换
- 采用了非阻塞I/O多路复用机制
七、redis的数据类型和使用场景
redis一共有五种数据类型,分别是:string、set、list、hash、sorted set
- string:最常规的数据类型,可以做token,计数功能等等
- hash:这里的value存储的是结构化的对象,类似于Java的HashMap,可以很方便的对hash中任意一个数据进行操作
- list:内部是用双向链表实现的,对于越接近两端的元素,速度越快,所以可以用来做排行榜、消息队列等
- set:存放的是不重复的值,可以用来做全局去重,另外就是交集、并集、差集等可以用来计算共同喜好等等
- sorted set:多了一个权重的概念,是有序的,场景:按点击量、时间排序等。
八、redis的过期策略以及内存淘汰机制
redis才用的是定期删除和惰性删除。
1.为什么不使用定时删除:
用一个定时器来负责监视key,过期则自动删除。虽然内存及时释放,但是十分消耗CPU资源。在大并发请求下,CPU要将时间应用在处理请求,而不是删除key,因此没有采用这一策略.
2.定期删除+惰性删除是如何工作的呢?
定期删除,redis默认每隔100ms进行检查(抽查),是否有过期的key,如果有就删除掉。
惰性删除,在获取某个key之前,先检查下这个key是否设置了过期时间,是否过期,如果过期就把key删除掉。
3.redis内存将满是使用的删除策略
首先,在redis.conf文件中进行配置:LRU算法即“最近很少使用”,其认为最近很少使用的键在未来的一段时间内也不会被用到。
maxmemory-policy volatile-lru
九、redis为什么是单线程
官方解释为因为redis是基于内存进行操作的,所以CPU并不是Redis的瓶颈,redis的瓶颈是机器内存大小或者网络带宽。
Redis利用队列技术将并发访问变为串行访问。
- 绝大部分请求是纯粹的内存操作,速度非常快
- 采用单线程,避免了不必要的上下文切换和竞争条件
- 采用非阻塞I/O多路复用机制。
十、redis集群方案都有哪些?
- twemproxy,类似于代理,使用时在本需要连接 redis 的地方改为连接 twemproxy, 它会以一个代理的身份接收请求并使用一致性 hash 算法,将请求转接到具体 redis,将结果再返回 twemproxy。缺点是不适合做节点经常增加减少的集群。
- codis,目前使用最多的集群方案,基本和 twemproxy 一致的效果,但它支持在 节点数量改变情况下,旧节点数据可恢复到新 hash 节点。
- redis cluster3.0 自带的集群,特点在于他的分布式算法不是一致性 hash,而是 hash 槽的概念,以及自身支持节点设置从节点。
十一、多台机器redis部署如何保证数据一致
主从复制,读写分离
对于多台机器的redis节点,设置一个主服务器,其他的都是这台主服务器的从服务器,给主服务器写权限,从服务器只有读权限,从服务器按照一定的策略从主服务器同步数据即可。
十二、大量的请求怎么样处理
- redis是一个单线程程序,也就说同一时刻它只能处理一个客户端请求;
- redis是通过IO多路复用(select,epoll, kqueue,依据不同的平台,采取不同的实现)来处理多个客户端请求的。
十三、为什么redis的操作是原子性的
对于redis来说,命令的原子性指的是一个操作不可以再分,操作要么执行,要么不执行。
redis操作之所以是原子性的是因为redis是单线程的。
Redis本身提供的所有API都是原子操作,Redis中的事务其实是要保证批量操作的原子性。
十四、说一说redis事务
Redis中的事务是一组命令的集合,采用MULTI...EXEC来进行事务控制。
Redis会将一个事务中的所有命令序列化,然后按顺序执行。
错误处理:
- 语法错误:只要命令的集合中有一条命令具有语法错误,执行EXEC后直接返回错误,连语法正确的命令也不会执行。
- 运行错误:指在命令执行时出现的错误(例如使用散列类型的命令操作集合类型的键)。如果事务里的一条命令出现了运行错误,事务里的 其他命令依然会执行,包括出错之后的命令。
- MULTI命令用于开启一个事务,它总是返回OK。 MULTI执行之后,客户端可以继续向服务器发送任意多条命令,这些命令不会立即被执行,而是被放到一个队列中,当EXEC命令被调用时,所有队列中的命令才会被执行。
- EXEC:执行所有事务块内的命令。返回事务块内所有命令的返回值,按命令执行的先后顺序排列。 当操作被打断时,返回空值 nil
- 通过调用DISCARD,客户端可以清空事务队列,并放弃执行事务, 并且客户端会从事务状态中退出。
- WATCH 命令可以为 Redis 事务提供 check-and-set (CAS)行为。 可以监控一个或多个键,一旦其中有一个键被修改(或删除),之后的事务就不会执行,监控一直持续到EXEC命令。使用UNWATCH来取消监控。