之前对redis的理解,只能说是:一些简单命令和定义之类的会使用或者知道,之后的话,慢慢在项目中用了很多这方面的技术,看了关于redis的封装方法,似乎发现了新大陆(其实只是理解了一些),还需要慢慢深入。
01 Redis是什么
一个开源的,内存中的数据结构存储系统;
用作数据库、缓存和消息中间件;
支持的常见的5种数据结构:
-
字符串String
-
散列Hashes
-
列表List
-
集合Set
-
有序集合Sorted set
而Redis内置了复制(replication)、LUA脚本、LRU驱动事件、事务和不同级别的磁盘持久化,并通过哨兵和自动分区Cluster提高高可用性,这些才是项目中使用比较多的几个部分。
02 Redis缓存
为什么要缓存呐,其实对于一些频繁访问的数据把它放到缓存中,从而减少了数据库的访问,对于日活比较高的能够很好的达到速度和性能的改善。
缓存查询顺序:
在数据获取的时候,一般是先从缓存中取数据;
如果缓存中没有的话,再去数据库取数据。
Redis缓存问题:
最主要的几个就是:缓存击穿、缓存穿透和缓存雪崩。
缓存穿透:
当访问数据库中的一个不存在的key的时候,发现没有数据,程序会去数据库的查询,当查不到数据的时候,就不会写入redis缓存,从而导致这个不存在的数据每次请求都会去数据库查询,导致缓存穿透。当数据量比较大的时候,可能导致数据库挂掉。
(画这几张图,也是头大,不知道怎么才能把代码用图体现出来)
解决:
采用布隆过滤器。用一个比较大的bitmap,存储可能访问的key,对不存在的key直接过滤掉;
当数据库查询的值为空,也要设置一个默认值,可以把这个有效时间设置短一点;
缓存雪崩:
是说大量的缓存集中的进行失效,导致了缓存穿透,进而所有的查询都在数据库上,数据库很快就承受不住,甚至宕机,导致了缓存雪崩。
解决:
过期时间均匀分布,而不是集中到一点;
设置两个缓存的key,而具有不同的失效时间,当key1失效之后,访问key2,然后更新key1和key2;
使用分布式锁(redis的Lock方法),从而当应用发现缓存失效之后,拿到锁的线程才去更新缓存;
mq消息队列的削峰方式,当应用发现缓存失效之后,发送消息,消费者消费后进行更新数据和缓存,后台线程会检测缓存中是否存在缓存,如果存在就不更新
(其实,用户很多很多的哦,大批量)
缓存击穿:
是指一个key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个屏障上凿开了一个洞。
解决:
和缓存雪崩的方法其实差不多:都可以用分布式锁来处理。