Redis是什么
Redis(Remote Dictionary Server)是一个开源的高性能键值(key-value)缓存数据库,它主要用于将数据存储在内存中,以提供快速的读写访问速度。
Redis有哪些特点
- 高性能:Redis将数据存储在内存中,因此能够提供非常快速的读写操作。它使用高效的数据结构和算法,以及异步I/O模型,实现了高吞吐量和低延迟的数据访问。
- 数据结构多样性:Redis支持多种数据结构,包括字符串(String)、哈希表(Hash)、列表(List)、集合(Set)、有序集合(Sorted Set)等。每种数据结构都有丰富的操作命令,可以满足不同场景下的数据存储和处理需求。
- 持久化:Redis支持数据持久化,可以将内存中的数据保存到磁盘上,以便在重启或宕机后恢复数据。它提供了两种持久化方式:快照(snapshotting)和日志(append-only file)。
- 丰富的特性:Redis支持 publish/subscribe, 通知, key 过期等特性
Redis的使用场景
-
缓存:Redis作为高速缓存数据库,用于存储频繁访问的数据,以提高应用程序的响应速度。例如,将数据库查询结果缓存在Redis中,以减少对数据库的访问次数。
-
限时业务的运用: redis中可以使用expire命令设置一个键的生存时间,到时间后redis会删除它。利用这一特性可以运用在限时的优惠活动信息、手机验证码等业务场景。
-
实时计数器:Redis的原子性操作和高性能使其成为实时计数器的有效工具。例如,可以使用Redis的INCR命令实现网站的访问计数器或用户行为统计。
-
分布式锁:Redis的原子性操作和乐观锁机制使其成为实现分布式锁的理想选择。通过利用Redis的SETNX命令和过期时间设置,可以实现多个进程或服务器之间的互斥访问控制。
-
排行榜相关问题:关系型数据库在排行榜方面查询速度普遍偏慢,所以可以借助redis的SortedSet进行热点数据的排序。
比如点赞排行榜,做一个SortedSet, 然后以用户的openid作为上面的username, 以用户的点赞数作为上面的score, 然后针对每个用户做一个hash, 通过zrangebyscore就可以按照点赞数获取排行榜,然后再根据username获取用户的hash信息,这个当时在实际运用中性能体验也蛮不错的。
基础数据结构
1. String字符串
字符串是Redis最简单的数据结构,可以存储任意类型的字符串数据。它不仅可以存储简单的文本数据,还可以存储二进制数据,如图片、音频或视频等。
操作 | 示例 | 解析 |
---|---|---|
设置键值对 | SET key value | 将键key 设置为对应的值value |
获取值 | GET key | 获取键key 对应的值 |
增加值 | INCR key | 将键key 对应的值自增1 |
减少值 | DECR key | 将键key 对应的值自减1 |
SET name "John"
GET name
```
这个例子将一个名为"name"的字符串键的值设置为"John",然后通过GET命令获取该键的值。
- 实战场景
- 缓存: 经典使用场景,把常用信息,字符串,图片或者视频等信息放到redis中,redis作为缓存层,mysql做持久化层,降低mysql的读写压力。
- 计数器:redis是单线程模型,一个命令执行完才会执行下一个,同时数据可以一步落地到其他的数据源。
- session:常见方案spring session + redis实现session共享
- 分布式锁:使用字符串作为锁的标识,并利用Redis的原子性操作实现分布式锁机制。
2. List列表
列表是一个有序的字符串集合,它可以包含多个元素。你可以在列表的两端执行插入和删除操作,以便快速地在列表的任意位置添加或移除元素。
操作 | 示例 | 解析 |
---|---|---|
左侧插入 | LPUSH key value1 value2 | 在键key 对应的列表的左侧依次插入值value1 和value2 |
右侧插入 | RPUSH key value1 value2 | 在键key 对应的列表的右侧依次插入值value1 和value2 |
获取范围 | LRANGE key start stop | 获取键key 对应的列表在指定范围内的元素 |
弹出元素 | LPOP key 或 RPOP key | 弹出并返回键key 对应的列表的左侧或右侧的元素 |
LPUSH fruits "apple"
LPUSH fruits "banana"
LRANGE fruits 0 -1
```
这个例子在名为"fruits"的列表的左侧依次插入了"apple"和"banana"两个元素,然后使用LRANGE命令获取整个列表的所有元素。
- 实战场景
- 消息队列:将待处理的消息存储在列表中,消费者可以按顺序获取并处理这些消息。
- 最新动态:将最新的动态消息存储在列表中,用户可以获取和浏览最新的动态。
- 历史记录:使用列表存储用户的历史操作记录,以便回溯和展示。
3. Set集合
集合是一个无序的字符串集合,不允许重复的元素。它提供了一系列的集合操作,如交集、并集和差集,可以方便地对集合进行操作和计算。
操作 | 示例 | 解析 |
---|---|---|
添加成员 | SADD key member1 member2 | 向键key 对应的集合添加成员member1 和member2 |
获取成员数 | SCARD key | 获取键key 对应的集合中成员的数量 |
获取所有 | SMEMBERS key | 获取键key 对应的集合中的所有成员 |
移除成员 | SREM key member1 member2 | 从键key 对应的集合中移除成员member1 和member2 |
SADD tags "red"
SADD tags "blue"
SMEMBERS tags
```
这个例子使用一个名为"tags"的集合存储了"red"和"blue"两个标签,然后通过SMEMBERS命令获取集合中的所有成员。
- 实战场景
- 标签系统:使用集合存储标签,以便对标签进行快速的交集、并集和差集等操作。
- 好友关系:使用集合存储用户的好友关系,以便进行快速的共同好友和推荐好友的计算。
- 唯一值存储:使用集合存储唯一的值,确保数据的一致性和去重
4. Hash散列
哈希是一种键值对的集合,类似于关联数组或字典。在Redis中,哈希是使用一个键来存储多个字段和对应的值。哈希结构非常适合存储对象,并且可以方便地对对象的字段进行操作。
操作 | 示例 | 解析 |
---|---|---|
设置字段值 | HSET key field value | 在键key 对应的哈希中,设置字段field 的值为value |
获取字段值 | HGET key field | 获取键key 对应的哈希中字段field 的值 |
获取所有 | HGETALL key | 获取键key 对应的哈希中所有的字段和值 |
删除字段 | HDEL key field1 field2 或 HDEL key [field1, field2] | 删除键key 对应的哈希中的一个或多个字段 |
HSET user:id1 name "Alice"
HSET user:id1 age 25
HGETALL user:id1
```
这个例子使用一个哈希键"user:id1"存储了用户的姓名和年龄,然后通过HGETALL命令获取该哈希键中所有字段和值。
- 实战场景
- 用户信息存储:将用户的各种信息(姓名、年龄、地址等)存储在哈希中,方便检索和更新。
- 缓存对象:将复杂的对象结构存储为哈希,以便在需要时快速获取完整的对象。
5. Zset有序集合
它是一个排序的字符串集合,其中每个成员都与一个分数相关联。这种关联使得有序集合具有两个主要特点:
- 排序:有序集合中的成员按照分数进行排序。这意味着你可以按照成员的顺序访问集合中的元素。例如,你可以根据分数从低到高或从高到低获取成员。
- 分数关联:每个成员都与一个分数相关联。这个分数可以用来对成员进行排序,也可以用来标识和比较成员之间的权重或重要性。
操作 | 示例 | 解析 |
---|---|---|
添加成员 | ZADD key score1 member1 score2 member2 | 向键key 对应的有序集合添加带有分数的成员 |
获取成员数 | ZCARD key | 获取键key 对应的有序集合中成员的数量 |
获取范围 | ZRANGE key start stop [WITHSCORES] | 获取键key 对应的有序集合在指定范围内的成员(可选择包含分数) |
增加分数 | ZINCRBY key increment member | 将键key 对应的有序集合中成员member 的分数增加指定的值 |
ZADD leaderboard 1000 "John"
ZADD leaderboard 800 "Alice"
ZADD leaderboard 1200 "Bob"
ZRANGE leaderboard 0 -1 WITHSCORES
```
在这个例子中,我们使用ZADD命令将三个成员("John"、"Alice"和"Bob")添加到名为"leaderboard"的有序集合中,并为每个成员设置了相应的分数。然后,我们使用ZRANGE命令来获取整个有序集合的成员和分数。
-
实战场景
- 排行榜:有序集合经典使用场景。例如小说视频等网站需要对用户上传的小说视频做排行榜,榜单可以按照用户关注数,更新时间,字数等打分,做排行。
6. Redis事务
Redis中的事务是可以视为一个队列,即我们可以通过MULTI开始一个事务,这相当于我们声明了一个命令队列。接下来,我们向Redis中提交的每条命令,都会被排入这个命令队列。当我们输入EXEC命令时,将触发当前事务,这相当于我们从命令队列中取出命令并执行,所以Redis中一个事务从开始到执行会经历开始事务,命令入队和 执行事务 三个阶段。
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> SET Book_Name "GIt Pro"
QUEUED
127.0.0.1:6379> SADD Program_Language "C++" "C#" "Jave" "Python"
QUEUED
127.0.0.1:6379> GET Book_Name
QUEUED
127.0.0.1:6379> EXEC
1) OK
2) (integer) 4
3) "GIt Pro"
事务相关命令
-
MULTI
MULTI
命令用于开启Redis事务。在执行MULTI
命令之后,所有后续的命令都会被放入一个队列中,而不是立即执行。这样可以确保这些命令作为一个原子操作执行,要么全部执行成功,要么全部失败。 -
EXEC
在一个事务中执行所有先前放入队列的命令,然后恢复正常的连接状态。当使用WATCH命令时,只有当受监控的键没有被修改时,EXEC命令才会执行事务中的命令。
-
DISCARD
放弃事务,清除事务队列中的命令,然后恢复正常的连接状态。如果使用了UNWATCH命令,那么DISCARD命令就会取消当前连接监控的所有键。
-
WATCH
当某个事务需要按条件执行时,就要使用该命令将key设置为受监控的。如果在事务执行之前这些key被其他命令所改动,那么整个事务将会被打断。WATCH命令可用于提供CAS功能。
-
UNWATCH
清除事务中所有监控的键。如果调用了EXEC或DISCARD命令,那么就不需要手动调用UNWATCH命令。
Redis事务的特性
- 原子性(Atomicity):Redis事务中的所有命令要么全部执行成功,要么全部失败。事务中的命令作为一个不可分割的单元执行,保证原子性操作。在执行EXEC命令时,如果Redis事务中某条命令执行失败,其后的命令仍然会被执行,没有回滚。
- 隔离性(Isolation):事务是一个单独的隔离操作,没有隔离级别的概念,事务队列中的命令在没有提交之前都不会实际的被执行。在事务中,所有命令都会被序列化,按顺序地执行。事务在执行的过程中,其他客户端发送来的命令请求不会插入到事务执行命令序列中。
- 持久性:如果Redis运行在某种特定的持久化模式下时,事务也具有持久性。
需要注意的是,Redis的事务并不提供隔离级别(如读未提交、读已提交、可重复读、串行化)的概念,也不支持回滚已执行的命令。此外,Redis的事务机制仅在单个Redis节点上有效,不支持分布式事务。
7. Redis持久化
Redis是一个基于内存的数据库,如果没有持久化的化,那么一旦服务器重启或者断电,那么之前的所有数据都会丢失。
持久化的两种方式:
-
RDB(Redis Database)
是指在指定的时间间隔之内,将内存中的数据快照写入磁盘,它是某一个时间点上数据的完整副本,通过配置文件中save命令配置
# save 时间间隔 修改次数
save 60 10 #60秒内有10次修改的话,进行一次快照
-
AOF(append only file),意思就是追加文件
在执行写命令的时候,不仅会将命令写入到内存中,还会将命令写入到一个追加的文件中,这个文件就是AOF文件,它会以日志的形式写入每一写操作,当Redis重启的时候,就会通过重新执行AOF文件中的命令,来在内存中重建整个数据库的内容
appendonly yes
8.Redis 支持三种集群方案
- 主从复制模式
- Sentinel(哨兵)模式
- Cluster 集群模式
a. 主从复制
主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(master),后者称为从节点(slave);
数据的复制是单向的,只能由主节点到从节点。
默认情况下,每台Redis服务器都是主节点,且一个主节点可以有多个从节点(或没有从节点),但一个从节点只能有一个主节点。
作用:
- 高可用性和故障恢复:主从复制可以提供高可用性,当主节点发生故障或不可用时,从节点可以接管主节点的功能,继续提供读写服务。通过配置适当数量的从节点,可以实现故障转移和自动故障恢复,提高系统的可用性。
- 负载均衡:通过将读操作分布到多个从节点上,主从复制可以实现负载均衡。主节点负责处理写操作,而从节点可以处理读操作(即写Redis数据时应用连接主节点,读Redis数据时应用连接从节点),从而分担主节点的负载。这样可以提高系统的整体性能和吞吐量。
- 数据备份和灾难恢复:通过将数据复制到从节点,主从复制提供了数据备份的机制。从节点保存了主节点的数据副本,当主节点发生数据丢失或损坏时,可以使用从节点进行数据恢复。这对于灾难恢复和数据保护非常有用。
b. 哨兵模式
哨兵模式是一种特殊的模式,哨兵是一个独立的进程,它会独立运行。其原理是哨兵通过发送命令,等待Redis服务器响应,从而监控运行的多个 Redis 实例。
哨兵服务器的作用:
- 通过发送命令,让 Redis 服务器返回监控其运行状态,包括主服务器和从服务器;
- 当哨兵监测到 master 宕机,会自动将 slave 切换成 master ,然后通过发布订阅模式通知其他的从服务器,修改配置文件,让它们切换主机;
优点:
- 哨兵模式是基于主从模式的,所有主从的优点,哨兵模式都具有。
- 主从可以自动切换,系统更健壮,可用性更高(可以看作自动版的主从复制)。
c. 集群模式
Redis Cluster是Redis提供的一种分布式解决方案,用于在多个节点上分片存储数据,并提供高可用性和横向扩展能力。
Redis Cluster的主要特点和工作原理如下:
- 分布式数据存储:Redis Cluster将数据分片存储在多个节点上,每个节点负责存储一部分数据。数据的分片是通过使用哈希槽(hash slot)来实现的,Redis Cluster将整个数据集分为16384个哈希槽,每个节点负责管理一部分哈希槽。
- 自动数据迁移和负载均衡:当节点加入或离开集群时,Redis Cluster会自动进行数据迁移和重新分配哈希槽,以实现负载均衡和数据的高可用性。当有节点失效时,集群会自动将失效节点的哈希槽迁移到其他正常节点上,确保数据的可用性。
- 高可用性和故障转移:Redis Cluster采用主从复制机制来提供高可用性。每个主节点都有若干个从节点,当主节点失效时,从节点可以接管主节点的功能,实现故障转移。Redis Cluster使用Gossip协议来进行节点间的状态通信和故障检测。
- 客户端路由和请求转发:客户端可以直接连接到任意一个节点,并通过节点进行数据访问。当客户端发送命令时,节点会根据命令中的键来确定数据所在的哈希槽,并将请求转发到负责该哈希槽的节点上。这样,客户端可以透明地访问整个集群的数据。