Redis是什么
Redis
(REmote DIctionary Server)是一个基于 C 语言开发的开源 NoSQL
数据库(BSD 许可)。与传统数据库不同的是,Redis
的数据是保存在内存
中的(内存数据库,支持持久化),因此读写速度非常快,被广泛应用于分布式缓存方向。并且,Redis 存储的是 KV
键值对数据。
Redis常用数据类型
5 种基础数据类型:
String
(字符串)、List
(列表)、Set
(集合)、Hash
(散列)、Zset
(有序集合)。3 种特殊数据类型:
HyperLogLog
(基数统计)、Bitmap
(位图)、Geospatial
(地理位置)。
Redis缓存异常的三个问题
缓存穿透:
是指缓存和数据库中都没有数据,导致所有的请求都落到数据库上,数据库短时间承受大量的请求而崩掉。
解决方法:
1、缓存取不到,数据库也取不到的数据,设置为key—null
的方式;
2、布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap
中去(它告诉你存在的话不能全信,其实有可能是不存在的,不过它他要是告诉你不存在的话,那就一定不存在)。缓存击穿:
高并发查询同一条数据,但是
redis
中的数据过期了,导致请求发送到了数据库,造成缓存击穿。解决方法:
1、设置热点数据永不过期;
2、使用互斥锁。分布式情况下使用分布式的锁。缓存雪崩:
缓存同一时间大面积的失效,后面的请求都会落到数据库上,造成数据库短时间内承受大量的数据请求。
解决方法:(缓存击穿的两种方法也可以)
1、缓存数据的过期时间随机设置,防止同一时间大量的数据过期的情况发生。
Redis缓存作用
简单点来说,就是优化客户端请求数据时,服务端的查询速度。
如果能在缓存中命中数据,那就查询缓存,不用再去查询数据库,从而减轻数据库的压力,提高服务器的性能。
Redis缓存数据一致性
「先更新数据库 + 再删除缓存」的方案,是可以保证数据一致性的。
因为因为缓存的写入通常要远远快于数据库的写入。
如果要想保证「先更新数据库,再删缓存」策略第二个操作能执行成功,我们可以使用「消息队列来重试缓存的删除」,或者「订阅 MySQL binlog 再操作缓存」,这两种方法有一个共同的特点,都是采用异步操作缓存。
Redis的过期算法
Redis
通过一个叫做过期字典(可以看作是 hash 表)来保存数据过期的时间。过期字典的键指向 Redis
数据库中的某个 key
(键),过期字典的值是一个 long long
类型的整数,这个整数保存了 key
所指向的数据库键的过期时间(毫秒精度的 UNIX 时间戳)。
- 常用的过期数据的删除策略就两个(重要!自己造缓存轮子的时候需要格外考虑的东西):
- 惰性删除:只会在取出 key 的时候才对数据进行过期检查。这样对 CPU 最友好,但是可能会造成太多过期 key 没有被删除。
- 定期删除:每隔一段时间抽取一批 key 执行删除过期 key 操作。并且,
Redis
底层会通过限制删除操作执行的时长和频率来减少删除操作对 CPU 时间的影响。
Redis的内存淘汰机制
Redis
提供 6 种数据淘汰策略:
- volatile-lru(least recently used):从已设置过期时间的数据集(
server.db[i].expires
)中挑选最近最少使用的数据淘汰。 - volatile-ttl:从已设置过期时间的数据集(
server.db[i].expires
)中挑选将要过期的数据淘汰。 - volatile-random:从已设置过期时间的数据集(
server.db[i].expires
)中任意选择数据淘汰。 - allkeys-lru(least recently used):当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的 key(这个是最常用的)。
- allkeys-random:从数据集(
server.db[i].dict
)中任意选择数据淘汰。 - no-eviction:禁止驱逐数据,也就是说当内存不足以容纳新写入数据时,新写入操作会报错。这个应该没人使用吧!
4.0 版本后增加以下两种:
- volatile-lfu(least frequently used):从已设置过期时间的数据集(
server.db[i].expires
)中挑选最不经常使用的数据淘汰。 - allkeys-lfu(least frequently used):当内存不足以容纳新写入数据时,在键空间中,移除最不经常使用的 key。