什么是Redis:
Redis是一个数据库,不过他是C语言开发的。不同于其他的数据库,他是一个基于内存的数据库,数据直接存储在内存中,所以他的读写速度非常快,(不需要从磁盘中IO)。但是由于内存的存储空间的限制,所以redis主要广泛用于缓存方向。
另外,Redis 除了做缓存之外,也经常用来做分布式锁,甚至是消息队列。
缓存数据的处理过程:1. 首先查看缓存中是否有,有得话直接返回。2.缓存中没有,在数据库中查找。3.数据库中没有,直接返回空。4.数据库中有,更新到缓存中,然后返回数据。
为什么使用缓存:高频数据放在缓存中,因为缓存是直接存储在内存中,访问的速度快。使用缓存对于数据库能够承受的并发访问数量远远大于直接直接访问数据库,从而提高了整个系统的并发量。
Redis中的数据结构:
1. String,String数据结构是key-value类型的。一般用于需要记录数的场景,比如记录访问数量,文章的浏览量等。
2. List,List在redis里就是一个双链表,支持双向的查找和遍历。
3. Hash,哈希,类似于java的HashMap。hash适合用于存储对象。一般用hash来存储用户的信息或者是商品信息。
4. Set,类似于java中的HashSet。无序的集合,数据不重复。可以基于 set 轻易实现交集、并集、差集的操作。比如:你可以将一个用户所有的关注人存在一个集合中,将其所有粉丝存在一个集合。Redis 可以非常方便的实现如共同关注、共同粉丝、共同喜好等功能。这个过程也就是求交集的过程。
sorted set 排序的set,其中有一个参数score,可以通过score排序。
Redis缓存过期删除策略:
1 . 惰性删除:
只会在取出key的时候做判断,可能会造成大量的过期数据没有被删除。
2. 定期删除:
每隔一段时间,都执行删除过期的数据。
定期删除对内存更加友好,惰性删除对 CPU 更加友好。两者各有千秋,所以 Redis 采用的是 定期删除+惰性/懒汉式删除 。
然而仅仅通过给key设置过期时间和采用过期删除策略是不够的,可能还会有很多过期的key遗漏,所以我们需要一个内存的淘汰机制。
Redis内存淘汰机制:
1. Volatile- LRU:从设置过过期时间的数据中挑选最近最少使用的数据删除。
2. Volatile-TTL : 从已经设置过期时间的数据中挑选即将要过期的数据删除。
3. Random : 从已经设置过期时间的数据中随机删除。
4. all keys LRU :当内存不够写入新数据的时候,删除所有key中最近最少使用的key。
5. all keys random: 随机删除数据
6. no-eviction:禁止驱逐数据,内存不够写入新数据报错。
7. volatile-LFU:从设置过过期时间的数据中挑选使用频率最少的数据删除。
8. all keys LFU:当内存不够写入新的数据的时候,删除所有key中使用频率最低的key。
Redis 持久化:
在有些时候,我们需要把数据持久化道硬盘中,为了数据的安全备份防止宕机等情况的发生。
两种持久化的方式:
1. RDB:快照,redis通过创建摸个时间点上的数据的快照副本。然后对副本进行备份。默认的方式。
2. AOF:与快照持久化相比,AOF 持久化的实时性更好,因此已成为主流的持久化方案。
可以通过 appendonly yes 开启AOF。
开启之后,每一条redis中更改的数据命令,redis都会把他们写到一个缓存文件中,然后根据append fsync 刷盘的参数来决定怎么将数据同步到硬盘中持久化。
3种参数:
always:总是,每次有数据发生更新就写入AOF文件。
every sec:每秒一次
no:让系统自行决定。
Redis 4.0 对于持久化机制的优化:
从redis4.0 开始支持RDB和AOF的混合版。
混合持久化只发生于 AOF 重写过程。使用了混合持久化,重写后的新 AOF 文件前半段是 RDB 格式的全量数据,后半段是 AOF 格式的增量数据。
AOF 重写
AOF 持久化是通过保存被执行的写命令来记录数据库状态的,所以AOF文件的大小随着时间的流逝一定会越来越大;影响包括但不限于:对于Redis服务器,计算机的存储压力;AOF还原出数据库状态的时间增加;
为了解决AOF文件体积膨胀的问题,Redis提供了AOF重写功能:Redis服务器可以创建一个新的AOF文件来替代现有的AOF文件,新旧两个文件所保存的数据库状态是相同的,但是新的AOF文件不会包含任何浪费空间的冗余命令,通常体积会较旧AOF文件小很多。
缓存穿透:
大量请求的key不在缓存上,然后大量的请求直接丢到数据库上,根本没有经过缓存这一层。
解决办法:参数校验,一些明显不合法的请求直接过滤掉或者返回错误给服务端。
布隆过滤器:把所有可能存在的请求的值都存放在布隆过滤器中,当用户请求过来,先判断用户发来的请求的值是否存在于布隆过滤器中。不存在的话,直接返回请求参数错误信息给客户端,存在的话才会走下面的流程。
什么布隆过滤器:一共可以检索元素是否在一个大的集合中的数据结构。
具体的结构是一个位数组,存储的都是0或者1. 这种数据结构是高效且性能很好的,但缺点是具有一定的错误识别率和删除难度。并且,理论情况下,添加到集合中的元素越多,误报的可能性就越大。
当一个元素加入布隆过滤器中的时候,会进行如下操作:
- 使用布隆过滤器中的哈希函数对元素值进行计算,得到哈希值(有几个哈希函数得到几个哈希值)。
- 根据得到的哈希值,在位数组中把对应下标的值置为 1。
当我们需要判断一个元素是否存在于布隆过滤器的时候,会进行如下操作:
- 对给定元素再次进行相同的哈希计算;
- 得到值之后判断位数组中的每个元素是否都为 1,如果值都为 1,那么说明这个值在布隆过滤器中,如果存在一个值不为 1,说明该元素不在布隆过滤器中。
重点:布隆过滤器说某个元素存在,小概率会误判。布隆过滤器说某个元素不在,那么这个元素一定不在。
缓存雪崩:
缓存在同一时间大面积的失效,就像雪崩一样,一下子所有的请求直接落到了数据库上。
两种情况:
1. 缓存系统突然宕机
2. 同一时间大量的key失效
解决办法:
1.采用redis集群,避免同一时间大面积的缓存失效发生。
2. 限流,避免同时处理大量的请求
3. 设置不同的失效时间
4. 缓存永不失效,让淘汰策略来淘汰缓存(LRU)