1 什么是redis?redis
Redis 是一个基于内存的高性能key-value数据库。数据库
2. Memcache与Redis的区别都有哪些?缓存
1)存储方式服务器
Memecache把数据所有存在内存之中,断电后会挂掉,数据不能超过内存大小。网络
Redis能够把数据保存在硬盘上,用来保证数据的持久性。数据结构
2)数据类型dom
Memcache的数据类型比较简单。异步
Redis有复杂的数据类型。分布式
3)使用底层模型不一样性能
它们之间底层的实现方式 以及与客户端之间通讯的应用协议不同。
4)value大小
redis最大能够达到1GB,而memcache只有1MB
3.Redis有哪些数据结构?
字符串String、字典Hash、列表List、集合Set、有序集合SortedSet。
更进一步,redis还有数据结构HyperLogLog、Geo、Pub/Sub、BloomFilter,RedisSearch,Redis-ML等
4.为何redis须要把全部数据放到内存中?
Redis为了达到最快的读写速度,将数据都读到内存中,并经过异步的方式将数据写入磁盘。因此redis具备快速和数据持久化的特征。
若是不将数据放在内存中,磁盘I/O速度为严重影响redis的性能。
若是设置了最大使用的内存,则数据量达到内存限值后,将不能继续插入新值。
5.怎么用Redis建立分布式锁
先用setnx来争抢锁,抢到以后,再用expire给锁加一个过时时间防止锁忘记了释放。
注意:若是在setnx以后,而且在执行expire以前,进程意外崩溃或者要重启维护了,这个锁就永远得不到释放了。
为了解决这个问题,set指令有很是复杂的参数,能够同时把setnx和expire合成一条指令
6.假如Redis里面有1亿个key,其中有10万个key是以固定的前缀开头的,如何将这些所有找出来?
使用keys命令能够扫出指定模式的key列表。
可是,若是这个redis正在给线上的业务提供服务,由于redis的单线程的,因此keys命令会致使线程阻塞一段时间,线上服务会停顿,直到命令执行完毕,服务才能恢复。
为了解决这个问题,可使用scan命令,scan命令能够无阻塞的提取出指定模式的key列表,会有必定的重复几率,在客户端作一次去重就能够了,可是总体所花费的时间会比直接用keys命令长。
7.若是有大量的key须要设置同一时间过时,须要如何处理?
若是大量的key过时时间设置的过于集中,那么当到了过时的那个时间点,redis可能会出现短暂的卡顿。
这种状况下,能够在时间上加一个随机值,使得过时时间分散一些。
8.Redis如何作持久化的?
bgsave作镜像全量持久化,aof作增量持久化。
由于bgsave会耗费较长时间,达不到实时,在停机的时候会致使大量丢失数据,因此须要aof来配合使用。
若是不要求性能,在每条写指令时都sync一下磁盘,就不会丢失数据。可是在高性能的要求下每次都sync是不现实的,通常都使用定时sync,好比1秒1次,这个时候最多会丢失1s的数据。
Redis会按期作aof重写,压缩aof文件日志大小。
在redis实例重启时,优先使用aof来恢复内存的状态,若是没有aof日志,就会使用rdb文件来恢复。
9.讲一下对Redis的同步机制的理解
Redis可使用主从同步,从从同步。
第一次同步时,主节点作一次bgsave,并同时将后续修改操做记录到内存buffer,待完成后将rdb文件全量同步到复制节点,复制节点接受完成后将rdb镜像加载到内存。
加载完成后,再通知主节点将期间修改的操做记录同步到复制节点进行重放就完成了同步过程。
10 对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)中任意选择数据淘汰
no-enviction(驱逐):禁止驱逐数据
11 对多级缓存的理解?
多级缓存就是有多个缓存,将ehcache配合redis缓存,好比ehcache做为1级缓存,使用redis做为2级缓存。
12 如何解决DB和缓存一致性问题?
当修改了数据库后,没有及时修改缓存就会形成不一致的状况。
而修改缓存失败的状况,最主要的缘由就是缓存服务器挂了。
若是由于网络问题引发的没有及时更新,能够经过重试机制来解决。
然而若是缓存服务器死了,那么客户端的请求天然也就没法到达,从而请求会直接打到数据库。
所以,咱们在修改数据库后,没法修改缓存,那么其中一个方案能够将这条数据放到数据库中,同时启动一个异步任务,定时去检测缓存服务器是否链接成功,一旦链接成功则从数据库中按顺序取出未同步的数据,依次进行同步缓存。
13.如何解决缓存穿透
生产中,一般都是先检查缓存中是否存在,若是存在直接返回缓存中内容,若是不存在就直接查询数据库,而后再缓存查询结果并返回。
这个时候若是查询的某一个数据在缓存中一直不存在,就会形成每一次请求都查询DB,这样缓存就失去了做用,在流量大时,就形成了缓存穿透。
有一个解决方案,能够将这个不存在的key预先设定一个值。是将缓存的KEY预先设置一个值,如,"key":"&&"。
若是查询请求过来,获得的返回值是发现是预先设定的"&&", 那咱们的应用就能够决定是否继续等待继续访问,仍是放弃掉此次操做。
若是继续等待访问,过一个时间轮询点后,再次请求这个key,若是取到的值再也不是"&&",则认为这时候key有值了,从而把大量的相似请求阻挡在缓存之中,也就避免了缓存穿透。
13. redis常见性能问题和解决方案
(1) Master最好不要作任何持久化工做,如RDB内存快照和AOF日志文件
(2) 若是数据比较重要,某个Slave开启AOF备份数据,策略设置为每秒同步一次
(3) 为了主从复制的速度和链接的稳定性,Master和Slave最好在同一个局域网内
(4) 尽可能避免在压力很大的主库上增长从库
(5) 主从复制不要用图状结构,用单向链表结构更为稳定,即:Master <- Slave1 <- Slave2 <- Slave3...
这样的结构方便解决单点故障问题,实现Slave对Master的替换。若是Master挂了,能够马上启用Slave1作Master,其余不变。