一、Redis的介绍
1.1Redis是什么
Redis是一个开源的,内存中的数据结构存储系统。它可以用做数据库、缓存、消息中间件。它支持多种数据结构类型,如字符串(String)、散列(hash),列表(list),集合(set),有序集合(sorted sets)与范围查询,bitmaps,hyperlogs和地理空间半径查询。Redis内置了复制,LUA脚本,LRU驱动事件,事务和不同级别的磁盘持久化机制,并提供Redis哨兵和自动分区提供高可用性.
二、关系型数据库与非关系型数据库之间的区别
2.1 关系型数据库
采用关系模型来组织数据的数据库就是关系型数据库,关系模型就是二维表格模型.一张二维表的表名就是关系,二维表的一行就是一条记录,二维表的一列就是一个字段.
优点:容易理解,容易维护,
使用方便,通用的sql语言
易于维护,丰富的完整性( 实体完整性、参照完整性和用户定义的完整性 ) 大大降低了数据冗 余和数据不一致的概率 2.2 非关系型数据库 非关系型,分布式一般不保证事务的ACID原则的数据存储结构.键值对存储,结构不稳定 优点:根据需要添加字段,不需要多表联查,仅需id查出对应的value 适用于SNS(社会化网络服务软件,比如facebook,微博) 严格上讲不是一种数据库,而是一种数据结构化存储方法的集合. 缺点:只适合存储一些较为简单的数据 不适合复杂查询的数据 不适合持久存储海量数据 2.3比较三、Redis适用的场景
数据库:数据性安全性不太高的,没有ACID强制要求
缓存:把经常使用的数据缓存起来,因为他是优先基于内存存储数据的
消息中间件:list双向队列结合具体的场景可以把Redis当作中间件来使用
四、常见的数据结构
Sting:以文本JSON形式存储的比较多
hash:比较适合存储二维表行列
lsit:头尾都可以获取添加
set集合:社交类软件取交集并集加关注,取消关注
sorted(课排序集合)排行榜
五、Redis主从复用
主从复用机制就是主服务器上的数据可以同步到从服务器上,从服务器可读,主服务器可读写。
六、key的过期淘汰机制
Redis可以对存储在Redis中的缓存数据设置过期时间,比如我们获取的短信验证码一般十分钟过期,我们这时候就需要在验证码存进Redis时添加一个key的过期时间,但是这里有一个需要格外注意的问题就是:并非key过期时间到了就一定会被Redis给删除。
定期删除
redis是默认设置了一个100ms的定期删除机制,每隔100ms就随机抽取一次设置了过期时间的key是否过期,过期了就删除。为什么不是全部检查一遍,因为key的数量太大的时候全部检查一遍会对cpu造成比较大的压力
惰性删除
定期删除由于是随机抽取可能会导致很多过期 Key 到了过期时间并没有被删除。所以用户在
从缓存获取数据的时候,redis会检查这个key是否过期了,如果过期就删除这个key。这时候就
会在查询的时候将过期key从缓存中清除。
内存淘汰机制
仅仅使用定期删除 + 惰性删除机制还是会留下一个严重的隐患:如果定期删除留下了很多已
经过期的key,而且用户长时间都没有使用过这些过期key,导致过期key无法被惰性删除,从而
导致过期key一直堆积在内存里,最终造成Redis内存块被消耗殆尽。那这个问题如何解决呢?这
个时候Redis内存淘汰机制应运而生了。Redis内存淘汰机制提供了6种数据淘汰策略:
一般情况下,推荐使用 volatile-lru 策略,对于配置信息等重要数据,不应该设置过期时
间,这样Redis就永远不会淘汰这些重要数据。对于一般数据可以添加一个缓存时间,当数据失
效则请求会从DB中获取并重新存入Redis中
七、Redis热点面试题
缓存击穿
高并发情况下,某个热门的key突然过期,此时大量的请求在Redis未找到缓存数据,进而全部取访问DB,引起DB压力瞬间增大,缓存击穿一般情况下不会造成DB宕机,知识会造成DB周期性的压力。
解决办法:对Redis数据不设置过期时间,而是在缓存的对象上添加一个属性表示过期时间,每次获取到数据的时候,首先校验该数据的时间属性,如果即将过期,则异步发起一个请求主动更新缓存中的数据,但这种方法容易导致拿到过期的数据,就得看业务是否可以接受。如果要求数据必须是新数据,则最好的办法是设置热点数据永不过期,然后加一个互斥锁保证数据的单线程写。
缓存穿透
指的是Redis缓存和DB中都不存放数据,比如通过id查询商品信息,id一般都大于0,攻击者会故意传id为-1去查询数据,这将会导致每次都不命中缓存而去DB中取数据,造成缓存穿透。
解决办法:
利用互斥锁,缓存失效的时候先去获得锁,得到锁了则取访问数据,没有得到锁,则休眠一段时间再去访问。
采用异步更新的方式,就是无论key是否过期,都直接返回。value中维护一个缓存失效时间,缓存如果过期,异步起一个线程去读数据,更新缓存。需要做缓存预热。
利用布隆过滤器,内部维护一系列合法的key,迅速判断出请求锁携带的key是否合法,如果不合法则直接返回,如果从数据库中取到的值为空也放入缓存,只是设定的过期时间较短,比如设置为60秒。
缓存雪崩
缓存中某一时间大量的key在同一时间内集中过期了,这时候会发生大量的缓存击穿现象,所有的请求都落在了DB上,由于查询的数据量过大,会引起DB压力过大甚至宕机现象。
解决方案
给缓存的失效时间,加上一个随机值,避免集体失效。如果Redis是集群部署,将热点数据
均匀分布在不同的Redis库中也能避免全部失效的问题
使用互斥锁,但是该方案吞吐量明显下降了。
设置热点数据永远不过期。
双缓存。我们有两个缓存,缓存A和缓存B。缓存A的失效时间为20分钟,缓存B不设失效时
间。自己做缓存预热操作。然后细分以下几个小点
1. 从缓存A读数据库,有则直接返回
2. A没有数据,直接从B读数据,直接返回,并且异步启动一个更新线程。
3. 更新线程同时更新缓存A和缓存B。



