发布时间:2023-03-21 17:30
Redis 是一个完全开源的、由 C 语言编写、遵守 BSD 协议(BSD 开源协议是一个给予使用者很大自由的协议,可以自由的使用、修改源代码,也可以将修改后的代码作为开源或者专有软件再发布)、支持网络、可基于内存、分布式、可选持久性、高性能的键值对(key-value)存储数据库,并支持多种语言的 API 。
Redis 是远程的、基于内存的、是非关系型数据库。
由于值(value)可以是:字符串(String)、哈希(Hash)、列表(List)、集合(Set)、有序集合(Zset)等类型,所以 Redis 常被称为数据结构服务器。
String:Redis 最基本的数据类型,一个 key 对应一个 value。二进制安全(可以包含任何数据,比如 jpg 图片或者序列化的对象。一个 Redis 字符串 value 最多可以是 512M。
Hash:类似 Java 里的 Map
List:简单的字符串列表,按照插入顺序排序,底层是个链表。可以通过 List 存储一些列表型的数据结构,类似粉丝列表、文章的评论列表之类的东西。
也可以基于 List 实现分页查询,这个是很棒的一个功能,基于 Redis 实现简单的高性能分页,可以做类似微博那种下拉不断分页的东西,性能高,就一页一页走。
Set:String 类型的无序集合,通过 HashTable 实现。
Zset:String 类型的有序集合,不允许重复的成员。
String 类型是 Redis 中最常用的类型,内部的实现是通过 SDS (Simple Dynamic String,类似于 Java 中的 ArrayList)来存储的,可以通过分配冗余空间的方式来减少内存的频繁分配。
缓存是高并发场景下提高热点数据访问性能的一个有效手段。缓存类型分为:本地缓存、分布式缓存、多级缓存。
RDB:Redis DataBase,指定时间间隔内,将内存中的数据集快照(snapshot)写入磁盘。恢复时是将快照文件直接读入内存中来达到数据恢复的。
Redis 会单独创建一个子进程来进行持久化(我们可以在做项目过程中自己模拟:创建一个线程来持久化),会先将数据写进一个临时文件中,等到持久化过程结束了,在用这个临时文件替换上次持久化好的文件。在这个过程中,只有子进程来负责 IO 操作,主进程任然处理客户端的请求,保证了极高的性能。
在默认情况下,Redis 将数据库快照保存在 dump.rdb 的二进制文件中,通过触发快照的形式,做到将指定时间间隔内的数据持久化到 dump.rdb。例如:可以2分钟内持久化一次,将对数据库的写操作备份到磁盘上的 dump.rdb。
AOF:Append Only File,以日志的形式记录 Redis 每一个写操作,将 Redis 执行过的所有指令记录下来(读操作不记录),只允许追加文件而不允许改写。Redis 启动之后会读取 appendonly.aof 文件来实现重新恢复数据。默认不开启,需要将 redis.conf 中的 appendonly no 改为 yes 。
两者如何选择:如果想达到较高的数据安全性,应该同时使用两种持久化方式。有很多用户只是用 AOF 方式,但是并不推荐,因为定时生成 RDB 快照非常便于进行数据库备份,而且 RDB 恢复数据集的速度也更快。所以,如果可以承受数分钟内的数据丢失,可以只使用 RDB 持久化。
数据缓存、队列原子性、数据存储。
缓存穿透:
在大多数互联网应用中,缓存的使用方式是:业务系统 -> 缓存 -> 数据库。
缓存穿透就是业务系统访问了根本不存在的数据,数据库返回空。
危害:如果海量请求查询不存在的数据,那么这些请求就都会落到数据库,数据库压力剧增,可能导致系统崩溃。
解决:将数据库查询结果为空的 key 也存到缓存中,并设置较短的生命周期,节省内存空间。
缓存雪崩:
缓存实际上是为了保护数据库,帮数据库抵挡大量的查询请求,从而避免脆弱的数据库受到伤害。当缓存因某种原因失效,原本被缓存抵挡的海量请求就会涌向数据库,此时数据库若抵挡不了崩溃,这就是缓存雪崩。
解决:开启备用缓存。
缓存击穿:(热点数据集中失效)
我们一般会给缓存设定一个失效时间,超时后该数据库会被缓存直接删除,一定程度上保证数据的实时性。
但是,对于一些请求量极高的热点数据,一旦过了有效时间,那么将会有大量的请求落在数据库上,从而可能导致数据库崩溃。
解决:互斥锁。只允许一个线程重建缓存,其他线程等待重建缓存的线程执行完成,重新从缓存获取数据即可。