1.redis是什么
答:redis是一个基于内存的,key-value型的非关系型数据库。
2.redis一般用来做什么
答:redis一般用来做缓存,也可以用来做分布式锁,同时一些特殊的需求,如实时的排行榜可以用redis中的zset来实现。
3.为什么要用缓存(redis)
答:使用缓存可以提高系统的性能以及并发。因为redis是将数据存于内存,而MySQL(innodb)则是将数据存于磁盘,读取内存的速度是ns级别,而读取磁盘的速度是ms级别(相差是的6次方,中间隔着一个微秒),所以使用缓存的系统响应速度会很快。其次redis每秒的qps可以达到10万级别,而单机mysql只有几千的qps,所以使用redis可以提高系统的并发。
4.为什么要用redis而不用map/guava做缓存
答:这个得看系统的架构,如何是一个单机架构,使用map/guava也可以,反而省去了redis的配置,但是管理起来比较复杂,redis还可以可视化,但如果是一个分布式的系统架构,那么map/guava这些本地缓存就无法保证缓存的一致性,因为本地缓存是存在不同的服务器上的,而redis在分布式架构下就可以保证缓存的独立性,因为它是一个独立的第三方数据库,多个应用服务器存取都来redis就好。
5.redis的线程模型
答:redis大家都说是单线程的,但是他并是严格意义上的单线程。redis内部有一个文件事件处理器,file event handler,这个文件事件处理器是单线程的,所以redis被称为单线程模型。这个文件事件处理采用的是IO多路复用技术,同时监听多个socket,根据socket上的事件再来具体分配线程去执行。file event handler里分为三部分,分别为IO多路复用程序,文件事件分派器以及事件处理器。redis的IO复用技术是epoll
6.redis与memcached的区别
答:redis支持更丰富的数据类型,String,list,hash,set,zset,而memcached只支持string,而且Redis是支持数据持久化的,可以将内存保持在磁盘中,而memcached是无法持久化的,断电即失。且redis原生的支持集群模式,而memcache需要依靠外部的一些工具来实现,还有就是redis是一个单线程的IO服用模型,而memcache则是一个多线程的非阻塞IO模型
7.redis常见的数据结构以及使用场景分析
答:首先redis整个是基于哈希表实现的,key就是哈希表的key,然后value指向了具体数据。string,list,hash,set,zset。其中string是我用的最多的,一般的缓存都是用的string,底层是一个自定义的SDS结构体,它里面是由字符数组以及数组长度等成员,比如库存,token等等,命令就是set,get。。。list可以用于消息列表啊,粉丝列表啊,或者类似微博那种不断下拉的分页等等,底层实现是一个双向链表,lpush,rpush,lpop,rpop,hash底层就是一个哈希表,然后比较适合存放对象,key存对象名,value用来存具体的属性,hget,hset,set是一个可以自动排重的列表,可以用来求共同关注啊,共同粉丝,共同好友(从而进行一个好友推荐),底层是一个哈希表key实现的,sadd,spop,Zset,可以实现自动排序的set,底层是跳表加哈希表,哈希表用来存值和score,跳表存着score用来排序,zadd,zrange(返回指定范围的成员),可以用来实现一个实时的排行榜功能。BitMap,位图,支持按bit位来存储信息,可以用来实现布隆过滤器(BloomFilter),HyperLogLog,提供不精确的去重功能,比较适合用来做大规模数据的去重统计,以及Geospatial,可以用来保存地理位置,可以做距离计算,实现附近的人等功能
8.redis设置过期时间
答:我们set key的时候都可以给设置一个过期时间,expiire key+过期时间,单位是秒,或者setex+key+过期时间+值。这里涉及到了redis如何对过期的key进行删除。redis对过期key删除有两种方式,分别是定期删除以及惰性删除。定期删除就是redis默认100ms就随机抽取一些设置了过期时间的key,检查其是否过期,若过期则删除,这里注意是随机抽取,因为若是遍历的话太耗费时间了。还有一个惰性删除,因为定期删除会漏掉很多的过期key,所以需要惰性删除来补刀,惰性删除就是当已经过期的key被再次用到的时候,才会被删除,但是还有问题,要是一直不被用到呢?岂不是一直占用着内存?所以就得靠redis的内存淘汰机制
9.redis的内存淘汰机制(如何保证redis里面的数据都是热点数据呢)
答:redis提供了6种数据淘汰策略,分别是volatile-lru,从设置过期时间的数据集中挑选最近最少使用的key进行淘汰,volatile-ttl从以设置过期的数据集中淘汰将要过期的key,volatile-random从已设置过期时间的key中任意选择数据淘汰,allkeys-lru,当内存不足时,移除最近最少使用的key,allkeys-random,从数据集中任意淘汰数据,no-eviction,禁止驱逐数据,当内存满后,插入数据直接报错
10.redis持久化机制
答:redis是提供持久化的机制的,分别为RDB和AOF,RDB是redis默认的持久化方式。RDB的持久化的步骤为首先Redis主进程会检查是否有子进程在执行持久化任务,若有则直接返回。若没有,主进程会先fork一个子进程来执行RDB操作,fork操作会阻塞主进程,fork完之后便不会再阻塞。子进程会根据主进程内存生成临时快照文件,持久化完成之后将临时快照文件代替原来的dump.rdb文件,子进程持久化完会通知主进程。这个过程主进程的读写不受影响,因为此时主进程会写到一个内存的一个临时副本中,待完成持久化后再同步到主内存。RDB的优点就是文件小,加载RDB文件很快,但是无法做到实时持久化,会丢失最后一次持久化之后的写操作,且fork操作会阻塞主进程。AOF持久化方式则是记录的每一次写操作的命令,就是IO操作比较密集,有三个等级always每有一条更新记录都会同步,everysec每秒同步一次,no按照操作系统来决定何时刷盘。RDB还有一个重写机制,因为RDB文件较大,所以需要进行“压缩”,就是遍历内存数据,重新生成一个AOF文件,这个时间段的变更操作会被redis记录起来,待重写完毕之后追加到新文件中,同时替换旧的appendonly.aof文件。优点实时性,如遇物理故障,最多会丢失一秒的数据,但是恢复比较慢,因为记录的是命令,所以需要全部重新执行,且体积较大,因为是文本形式(RDB是数据的二进制形式,比较紧凑)。(这里的思考为什么rdb是二进制,因为数据本身底层存的就是二进制,AOF是命令,本身执行执行命令就够慢的了,要是将加上将二进制转为命令,然后再执行更加的慢)。redis4.0提供了一种混合式持久化方式,即大量数据使用rdb持久化方式,然后在两次持久化之间使用aof方式,所以这样恢复数据的时候先大量恢复rdb之后在恢复少量的aof即可。
11.redis事务
答:redis的事务通常使用MULTI,EXEC,WATCH等命令来实现。但是redis的事务是不支持原子性的。即如果事务中某个指令没有执行成功,其他语句照样执行。
12.缓存雪崩如何解决
答:首先缓存雪崩是所有缓存都要思考的事情,不只是redis,缓存雪崩指的是大面积缓存失效,导致大量请求直接打在数据库上,数据库短时间内无法承受如此大量请求而崩掉。尽量保证redis集群的一个高可用性,发现宕机尽快补上,选择合适的内存淘汰策略。做多级缓存,如本地也加一层缓存并行限流,外加限流,限制真正可以访问到数据库的流量如只允许2000的请求访问。若雪崩之后利用redis持久化方式尽快恢复数据。
13.缓存穿透
答:大量请求的key不在缓存中,导致打在了数据库上,例如黑客利用我们缓存中不存在的key发起大量请求,一般来说3000左右的并发就能打死大部分数据库了。解决方法就是首先做好参数校验,一些不合法的请求直接抛出异常信息返回客户端,如id必须大于0等等,如果换粗内核数据库都差不多某个key的话,缓存短期内过期的无效key。或者使用布隆过滤器,用BitMap实现。setbit key index 0或1 set某个bitmap的 index位为0或1
14.如何解决Redis的并发竞争Key问题
答:redis并发竞争key的问题是指多个系统对同一个key进行操作,但是由于执行顺序和期望不同,导致结果不同。采用分布式锁。
15.如何保证缓存和数据库双写是数据的一致性
答:保证最终一致性。