Redis(Remote Dictionary Server) 是一个使用 C 语言编写的,开源的(BSD许 可)高性能非关系型(NoSQL)的键值对数据库。
Redis 可以存储键和五种不同类型的值之间的映射。键的类型只能为字符串,值 支持五种数据类型:字符串、列表、集合、散列表、有序集合。
与传统数据库不同的是 Redis 的数据是存在内存中的,所以读写速度非常快, 因此 redis 被广泛应用于缓存方向,每秒可以处理超过 10万次读写操作,是已
知性能快的Key-Value DB。
另外,Redis 也经常用来做分布式锁。除此之 外,Redis 支持事务 、持久化、LUA脚本、LRU驱动事件、多种集群方案。
**优点 **
**缺点 **
主要从“高性能”和“高并发”这两点来看待这个问题。
高性能:
假如用户第一次访问数据库中的某些数据。这个过程会比较慢,因为是从硬盘上 读取的。将该用户访问的数据存在数缓存中,这样下一次再访问这些数据的时候 就可以直接从缓存中获取了。操作缓存就是直接操作内存,所以速度相当快。如 果数据库中的对应数据改变的之后,同步改变缓存中相应的数据即可!
高并发:
直接操作缓存能够承受的请求是远远大于直接访问数据库的,所以我们可以考虑 把数据库中的部分数据转移到缓存中去,这样用户的一部分请求会直接到缓存这 里而不用经过数据库。
缓存分为本地缓存和分布式缓存。以 Java 为例,使用自带的 map 或者 guava 实现的是本地缓存,主要的特点是轻量以及快速,生命周期随着 jvm 的销毁 而结束,并且在多实例的情况下,每个实例都需要各自保存一份缓存,缓存不具 有一致性。
使用 redis 或 memcached 之类的称为分布式缓存,在多实例的情况下,各实 例共用一份缓存数据,缓存具有一致性。缺点是需要保持 redis 或 memcached 服务的高可用,整个程序架构上较为复杂。
Redis主要有5种数据类型,包括String,List,Set,Zset,Hash,满足大部分 的使用要求 数据类型 可以存储 的值 操作 应用场景
数据类型 | 可以存储 的值 | 操作 | 应用场景 |
---|---|---|---|
STRING | 字符串、 整数或者 浮点数 | 对整个字 符串或者 字符串的 其中一部 分执行操 作 对整数和 浮点数执 行自增或 者自减操 作 | 做简单的 键值对缓 存 |
LIST | 列表 | 从两端压 入或者弹 出元素 对单个或 者多个元 素进行修 剪, 只保留一 个范围内 的元素 | 存储一些 列表型的 数据结 构,类似 粉丝列 表、文章 的评论列 表之类的 数据 |
SET | 无序集合 | 添加、获 取、移除 单个元素 检查一个 元素是否 存在于集 合中 | 交集、并 集、差集 的操作, 比如交 集,可以 把两个人 的粉丝列 |
HASH | 包含键值 对的无序 散列表 | 添加、获 取、移除 单个键值 对 获取所有 键值对 检查某个 键是否存 在 | 结构化的 数据,比 如一个对 象 |
ZSET | 有序集合 | 添加、获 取、删除 元素 根据分值 范围或者 成员来获 取元素 计算一个 键的排名 | 去重但可 以排序, 如获取排 名前几名 的用户 |
计数器
可以对 String 进行自增自减运算,从而实现计数器功能。Redis 这种内存型数 据库的读写性能非常高,很适合存储频繁读写的计数量。
缓存
将热点数据放到内存中,设置内存的大使用量以及淘汰策略来保证缓存的命中率。
会话缓存
可以使用 Redis 来统一存储多台应用服务器的会话信息。当应用服务器不再存 储用户的会话信息,也就不再具有状态,一个用户可以请求任意一个应用服务 器,从而更容易实现高可用性以及可伸缩性。
全页缓存(FPC)
除基本的会话token之外,Redis还提供很简便的FPC平台。以Magento为例, Magento提供一个插件来使用Redis作为全页缓存后端。此外,对WordPress的用户来说,Pantheon有一个非常好的插件 wp-redis,这个插件能帮助你以 快速度加载你曾浏览过的页面。
查找表
例如 DNS 记录就很适合使用 Redis 进行存储。查找表和缓存类似,也是利用了 Redis 快速的查找特性。但是查找表的内容不能失效,而缓存的内容可以失效, 因为缓存不作为可靠的数据来源。
消息队列(发布/订阅功能)
List 是一个双向链表,可以通过 lpush 和 rpop 写入和读取消息。不过好使用 Kafka、RabbitMQ 等消息中间件。
分布式锁实现 在分布式场景下,无法使用单机环境下的锁来对多个节点上的进程进行同步。可 以使用 Redis 自带的 SETNX 命令实现分布式锁,除此之外,还可以使用官方提 供的 RedLock 分布式锁实现。
其它
Set 可以实现交集、并集等操作,从而实现共同好友等功能。ZSet 可以实现有 序性操作,从而实现排行榜等功能。
Redis相比其他缓存,有一个非常大的优势,就是支持多种数据类型。
数据类型说明string字符串,简单的k-v存储hashhash格式,value为field和 value,适合ID-Detail这样的场景。list简单的list,顺序列表,支持首位或者末 尾插入数据set无序list,查找速度快,适合交集、并集、差集处理sorted set有 序的set
其实,通过上面的数据类型的特性,基本就能想到合适的应用场景了。
string——适合简单的k-v存储,类似于memcached的存储结构,短信验证 码,配置信息等,就用这种类型来存储。
hash——一般key为ID或者唯一标示,value对应的就是详情了。如商品详情, 个人信息详情,新闻详情等。
list——因为list是有序的,比较适合存储一些有序且数据相对固定的数据。如省 市区表、字典表等。因为list是有序的,适合根据写入的时间来排序,如:新 的***,消息队列等。
set——可以简单的理解为ID-List的模式,如微博中一个人有哪些好友,set 牛的地方在于,可以对两个set提供交集、并集、差集操作。例如:查找两个人 共同的好友等。
Sorted Set——是set的增强版本,增加了一个score参数,自动会根据score的 值进行排序。比较适合类似于top 10等不根据插入的时间来排序的数据。 如上所述,虽然Redis不像关系数据库那么复杂的数据结构,但是,也能适合很 多场景,比一般的缓存数据结构要多。了解每种数据结构适合的业务场景,不仅 有利于提升开发效率,也能有效利用Redis的性能。
持久化就是把内存的数据写到磁盘中去,防止服务宕机了内存数据丢失。
Redis 提供两种持久化机制 RDB(默认) 和 AOF 机制:
RDB是Redis默认的持久化方式。按照一定的时间将内存的数据以快照的形式保 存到硬盘中,对应产生的数据文件为dump.rdb。通过配置文件中的save参数来 定义快照的周期。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GxkQo2PG-1670293133744)(12-Redis面试题(2020最新版)-重点.assets/RDB.png)]
AOF持久化(即Append Only File持久化),则是将Redis执行的每次写命令记录 到单独的日志文件中,当重启Redis会重新将持久化的日志中文件恢复数据。 当两种方式同时开启时,数据恢复Redis会优先选择AOF恢复。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-x36qNN9u-1670293133744)(12-Redis面试题(2020最新版)-重点.assets/AOF.png)]
如果Redis被当做缓存使用,使用一致性哈希实现动态扩容缩容。
如果Redis被当做一个持久化存储使用,必须使用固定的keys-tonodes映射关系,节点的数量一旦确定不能变化。否则的话(即Redis节点需要动态变化的情况),必须使用可以在运行时进行数据再平衡的一套系统,而当前只有Redis集群可以做到这样。
我们都知道,Redis是key-value数据库,我们可以设置Redis中缓存的key的过
期时间。Redis的过期策略就是指当Redis中缓存的key过期了,Redis如何处理。
(expires字典会保存所有设置了过期时间的key的过期时间数据,其中,key是指向键空间中的某个键的指针,value是该键的毫秒精度的UNIX时间戳表示的过期时间。键空间是指该Redis集群中保存的所有键。)
Redis中同时使用了惰性过期和定期过期两种过期策略。
EXPIRE和PERSIST命令。
Redis的内存淘汰策略是指在Redis的用于缓存的内存不足时,怎么处理需要新写入且需要申请额外空间的数据。
全局的键空间选择性移除:
noeviction:当内存不足以容纳新写入数据时,新写入操作会报错。
allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除 近 少使用的key。(这个是最常用的)
allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个key。(不建议)
设置过期时间的键空间选择性移除:
volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除 近 少使用的key。
volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个key。
volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的key优先移除。
总结
Redis的内存淘汰策略的选取并不会影响过期的key的处理。内存淘汰策略用于处理内存不足时的需要申请额外空间的数据;过期策略用于处理过期的缓存数据。
Redis主要消耗什么物理资源?
内存。
Redis的内存用完了会发生什么?
如果达到设置的上限,Redis的写命令会返回错误信息(但是读命令还可以正常返回。)或者你可以配置内存淘汰机制,当Redis达到内存上限时会冲刷掉旧的内容。
Redis如何做内存优化?
可以好好利用Hash,list,sorted set,set等集合类型数据,因为通常情况下很多小的Key-Value可以用更紧凑的方式存放到一起。尽可能使用散列表
(hashes),散列表(是说散列表里面存储的数少)使用的内存非常小,所以你应该尽可能的将你的数据模型抽象到一个散列表里面。比如你的web系统中有一个用户对象,不要为这个用户的名称,姓氏,邮箱,密码设置单独的key,而是应该把这个用户的所有信息存储到一张散列表里面线程模型
可以好好利用Hash,list,sorted set,set等集合类型数据,因为通常情况下很多小的Key-Value可以用更紧凑的方式存放到一起。尽可能使用散列表(hashes),散列表(是说散列表里面存储的数少)使用的内存非常小,所以你应该尽可能的将你的数据模型抽象到一个散列表里面。比如你的web系统中有一个用户对象,不要为这个用户的名称,姓氏,邮箱,密码设置单独的key,而是应该把这个用户的所有信息存储到一张散列表里面线程模型
Redis基于Reactor模式开发了网络事件处理器,这个处理器被称为文件事件处理器(file event handler)。它的组成结构为4部分:多个套接字、IO多路复用程序、文件事件分派器、事件处理器。因为文件事件分派器队列的消费是单线程的,所以Redis才叫单线程模型。
文件事件处理器使用 I/O 多路复用(multiplexing)程序来同时监听多个套接字, 并根据套接字目前执行的任务来为套接字关联不同的事件处理器。当被监听的套接字准备好执行连接应答(accept)、读取(read)、写入(write)、关闭(close)等操作时, 与操作相对应的文件事件就会产生, 这时文件事件处理器就会调用套接字之前关联好的事件处理器来处理这些事件。
虽然文件事件处理器以单线程方式运行, 但通过使用 I/O 多路复用程序来监听多个套接字, 文件事件处理器既实现了高性能的网络通信模型, 又可以很好地与 redis 服务器中其他同样以单线程方式运行的模块进行对接, 这保持了 Redis 内部单线程设计的简单性。