(一)Redis是什么
(二)Redis 的特性
Redis 作为一种高性能的键值对存储数据库,具有诸多特性。首先,它支持多种数据类型,包括字符串、哈希、列表、集合和有序集合等,这使得开发者可以根据不同的应用场景选择合适的数据结构,提高开发效率。例如,在缓存系统中,可以使用字符串类型存储热点数据;在社交网络应用中,可以利用集合类型进行共同好友的查找。
Redis 还具有持久化功能,支持 RDB 和 AOF 两种方式。RDB 是将内存中的数据定期写入磁盘,AOF 则是将每条写命令追加到一个日志文件中。这样可以在不影响性能的情况下保证数据的持久性,即使在服务器宕机或断电的情况下,也能通过恢复持久化文件来恢复数据。
Redis 的集群功能允许将数据分布在多个节点上,从而实现水平扩展,提高系统的可用性和性能。同时,Redis 提供了主从复制功能,可以实现数据的备份和高可用性。
在事务方面,Redis 虽然不能像传统关系型数据库那样支持完全的事务回滚,但也提供了一定程度的事务特性,可以保证在一定范围内的操作的原子性。
此外,Redis 还支持发布订阅、Lua 脚本等丰富的功能。发布订阅功能可以用于实现简单的消息系统,解耦业务代码;Lua 脚本则可以让开发者在 Redis 中执行自定义的逻辑,扩展 Redis 的功能。
(三)环境搭建
- Windows 安装
在 Windows 下安装 Redis 相对简单。首先从指定的下载地址下载安装包,一路 next 进行安装。安装完成后,Redis 的目录结构包括 redis-server.exe 和 redis-cli.exe 等文件。开启 redis-server.exe 启动 Redis 服务器,然后启动 redis-cli.exe 可以进行连接测试。如果需要配置密码,可以在 redis.windows.conf 文件中找到 requirepass 参数进行设置。
- Linux 安装
在 Linux 上安装 Redis 首先需要下载安装包,可以手动下载后上传至服务器,也可以使用命令自动下载。下载完成后解压安装包至指定目录,如 /opt 目录。接着需要安装基本环境和依赖,如 gcc 编译器等。安装完成后进行编译和安装,编译完成后会生成 src 目录。在 src 目录下可以进行安装操作,安装到指定目录。然后需要移动配置文件到安装目录下,并配置 Redis 为后台启动。可以通过修改 redis.conf 文件中的 daemonize 参数实现后台启动。使用 redis-cli 连接指定端口号进行测试,如果需要设置密码,可以通过一系列命令进行设置和验证。最后,可以使用性能测试工具 redis-benchmark 进行简单测试,如使用 100 个并发连接, 个请求进行测试,可以分析测试结果了解 Redis 的性能表现。
(一)数据库结构
Redis 默认有 16 个数据库,编号从 0 到 15。可以使用 select 命令来切换数据库,例如 select 1 表示切换到编号为 1 的数据库。不同数据库之间的数据是不互通的,这意味着在一个数据库中存储的键值对在另一个数据库中是不可见的。可以使用 dbsize 命令来查看当前数据库的大小,该命令会返回当前数据库中键的数量。
(二)基本操作
- keys * 命令可以查看当前数据库中的所有键。这个命令在实际应用中需要谨慎使用,特别是在数据库中键的数量非常大的时候,因为它可能会消耗大量的资源和时间。
- flushdb 命令用于清空当前数据库中的所有键值对。这个命令会立即删除当前数据库中的所有数据,所以在使用时要特别小心,确保不会误删重要数据。
- flushall 命令则更加彻底,它会清空所有数据库中的键值对。同样,这个命令也需要谨慎使用,以免造成不可挽回的数据丢失。
(三)Redis 为何单线程还如此快
Redis 虽然是单线程的,但却能拥有非常高的性能,其原因主要有以下几点:
首先,Redis 将所有数据都放在内存中进行存储。与传统的磁盘存储相比,内存的读写速度要快几个数量级。Redis 的每次读写操作都相当于从内存的变量中进行读写,访问内存比直接访问磁盘快得多,这使得 Redis 能够快速地处理大量的请求。
其次,在内存存储数据的情况下,没有上下文切换的单线程是最佳方案。多线程虽然可以增加系统的吞吐率,但同时也会带来线程创建和销毁的开销、上下文切换的开销以及锁的开销等问题。而 Redis 采用单线程架构,最大限度地减少了由于线程创建或销毁而产生的 CPU 消耗,减少了上下文切换造成的 CPU 消耗,同时也减少了锁开销。因为多线程应用程序需要锁来进行线程同步,而这容易出现错误。Redis 能够使用各种 “线程不安全” 命令,例如 Lpush,这也提高了其处理请求的效率。
此外,Redis 还采用了非阻塞 IO 和优化的数据结构等技术,进一步提高了其性能。例如,Redis 利用各种底层数据结构来高效存储数据,无需担心如何将它们持久化到持久存储中。Redis list 是使用链表实现的,它允许在列表的头部和尾部附近进行恒定时间 O (1) 插入和删除;Redis sorted set 是通过跳跃列表实现的,可以实现更快的查询和插入。
总之,Redis 单线程架构是经过深思熟虑的选择,并且经受住了时间的考验。尽管是单线程,Redis 仍然是性能最高、最常用的内存数据存储之一。
(一)NoSQL 数据库概述
- NoSQL 数据库概念介绍
NoSQL 即 Not Only SQL,泛指非关系型数据库。与传统的关系型数据库相比,NoSQL 不依赖于业务逻辑方式存储数据,而是以简单的 key-value 模式进行存储。这种存储方式极大地增加了数据库的扩展能力,不遵循 SQL 标准,也不支持 ACID(原子性、一致性、隔离性、持久性)特性。然而,其性能远超传统的 SQL 数据库。例如,在处理大规模数据的高并发读写场景下,NoSQL 数据库能够轻松应对,而传统关系型数据库可能会出现性能瓶颈。
- NoSQL 使用场景
- 对数据高并发的读写:在一些互联网应用中,如社交网络、电商平台等,需要处理大量的用户请求,对数据的读写操作要求极高的并发性能。NoSQL 数据库能够满足这种高并发的需求,快速响应大量的读写请求。
- 海量数据的读写:当数据量达到海量级别时,传统关系型数据库在存储和查询方面可能会遇到困难。而 NoSQL 数据库可以通过分布式架构轻松处理海量数据的读写操作。
- 对数据的高可扩展性:随着业务的发展,数据量和访问量不断增加,需要数据库具有良好的可扩展性。NoSQL 数据库可以方便地添加新的节点,实现水平扩展,满足业务增长的需求。
- NoSQL 不适用场景
- 需要事务支持:如果应用场景对数据的一致性要求非常高,需要严格的事务支持,那么 NoSQL 数据库可能不太适合。虽然一些 NoSQL 数据库提供了一定程度的事务支持,但与传统关系型数据库相比,还是相对较弱。
- 复杂关系的查询:如果需要进行复杂的多表关联查询,NoSQL 数据库可能无法满足需求。NoSQL 数据库通常不擅长处理复杂的关系查询,更适合存储简单的键值对或文档数据。
- 常见的 NoSQL 数据库
- Memcache:Memcache 是很早出现的 NoSQL 数据库,其数据都存储在内存中,一般不进行持久化。它支持简单的 key-value 模式,支持的类型单一,主要作为缓存数据库,辅助持久化数据库使用。例如,在一些高并发的 Web 应用中,可以将热点数据存储在 Memcache 中,以提高数据的访问速度。
- Redis:Redis 几乎覆盖了 Memcached 的绝大部分功能。它的数据也都在内存中,但支持持久化,主要用作备份恢复。Redis 支持多种数据结构存储,一般作为缓存数据库辅助持久化的数据库使用。例如,在一些需要快速读写和数据备份的场景中,Redis 可以发挥重要作用。
- MongoDB:MongoDB 是高性能、开源、模式自由的文档型数据库。它的数据也存储在内存中,可根据数据特点替代关系型数据库(RDBMS)或配合 RDBMS 存储特定数据。例如,在一些需要存储复杂数据结构和进行灵活查询的场景中,MongoDB 非常适用。
(二)Redis 的数据类型
- String
String 是 Redis 中最基本的数据类型,可以存储 String 或数字。它常用于复杂计数功能的缓存,比如统计网站的访问量、商品的销量等。例如,使用 Redis 的 INCR 命令可以对一个存储数字的 String 进行自增操作,实现计数器的功能。同时,String 类型还可以存储字符串数据,如缓存网页的内容、用户的登录状态等。
- Hash
Hash 类型可以存储结构化对象,方便操作其中的某个字段。它非常适合用于单点登录存储用户信息,比如存储用户的 ID、用户名、密码等信息。在 Redis 中,可以使用 HSET、HGET 等命令对 Hash 类型的数据进行操作。例如,使用 HSET 命令可以设置 Hash 中的某个字段的值,使用 HGET 命令可以获取 Hash 中某个字段的值。
- List
List 类型可以做简单的消息队列功能,利用 lrange 命令可做基于 redis 的分页功能。例如,使用 LPUSH 和 RPUSH 命令可以向 List 的头部或尾部添加元素,使用 LPOP 和 RPOP 命令可以从 List 的头部或尾部弹出元素。在消息队列场景中,可以将生产者生成的消息通过 LPUSH 命令添加到 List 中,消费者通过 RPOP 命令从 List 中取出消息进行处理。在分页功能场景中,可以将数据存储在 List 中,通过 lrange 命令获取指定范围内的数据,实现分页效果。
- Set
Set 是由 String 元素组成的无序集合,通过哈希表实现,不允许重复。Set 类型可实现共同关注、共同好友等功能。例如,在社交网络应用中,可以使用 SADD 命令将用户的关注对象添加到 Set 中,使用 SINTER 命令可以获取两个用户的共同关注对象。
- Sorted Set
Sorted Set 通过分数来为集合中的成员进行从小到大的排序。它可用于榜单等功能,比如排行榜、热门商品列表等。在 Redis 中,可以使用 ZADD 命令向 Sorted Set 中添加元素和分数,使用 ZRANGEBYSCORE 命令可以获取指定分数范围内的元素。
(三)高级数据类型
Redis 的高级数据类型包括用于计数的 HyperLogLog 和用于支持存储地理位置信息的 Geo 等。
HyperLogLog 是一种用于基数统计的数据集合类型,它可以在输入元素的数量或体积非常大的时候,计算基数所需的内存空间总是固定的、并且是很小的。例如,在统计网站的独立 IP 数量、系统的用户访问量等场景中,可以使用 HyperLogLog。使用 PFADD 命令可以添加指定元素到 HyperLogLog 中,使用 PFCOUNT 命令可以返回给定 HyperLogLog 的基数估算值。
Geo 类型是 Redis 在 3.2 版本中添加的对地理位置的支持。它可以用于存储地理位置信息,并进行距离计算、附近位置查询等操作。例如,在社交应用中,可以使用 Geo 类型存储用户的地理位置信息,实现附近的人功能;在物流应用中,可以使用 Geo 类型存储仓库的位置信息,进行货物配送路径规划。使用 GEOADD 命令可以添加指定的地理空间位置到指定的 key 中,使用 GEODIST 命令可以返回给定两个位置之间的距离。
(一)配置文件介绍
- Units 单位
Redis 中的所有数据容量都是以 bytes 为单位计算的。具体的换算标准如下:
- 1k => 1000 bytes
- 1kb => 1024 bytes
- 1m => bytes
- 1mb => 1024 * 1024 bytes
- 1g => bytes
- 1gb => 1024 * 1024 * 1024 bytes
- INCLUDES 包含
我们知道 Redis 只有一个配置文件,如果多个人进行开发维护,那么就需要多个这样的配置文件,这时候多个配置文件就可以在此通过 include /path/to/local.conf 配置进来,而原本的 redis.conf 配置文件就作为一个总闸。
- # include /path/to/local.conf
- # include /path/to/other.conf
- NETWORK 网络配置
- bind:绑定 redis 服务器网卡 IP,默认为 127.0.0.1,即本地回环地址。这样的话,访问 redis 服务只能通过本机的客户端连接,而无法通过远程连接。如果 bind 选项为空的话,那会接受所有来自于可用网络接口的连接。例如:bind 192.168.1.100 10.0.0.1(能够远程访问);bind 127.0.0.1 ::1(只能本机访问);bind * -:😗(模糊匹配所有 IP 地址)。
- protected-mode:设置本机访问保护模式,设置为 no 表示关闭保护模式,即允许远程访问。例如:protected-mode no。
- port:指定 redis 运行的端口,默认是 6379。例如:port 6379。
- tcp-backlog:用于设置 tcp 的 backlog,backlog 其实是一个连接队列,在高并发环境下你需要一个高 backlog 值来避免慢客户端连接问题。例如:tcp-backlog 511。
- timeout:设置客户端连接超时时间(当一个客户端连接超过多少秒没操作,就关闭此连接),单位是秒,默认是 0,即永不失效。例如:timeout 0。
- tcp-keepalive:设置客户端发送的最后一个数据包与 redis 发送的第一个保活探测报文之间的时间间隔,单位是秒,默认为 300 秒。例如:tcp-keepalive 300。
- GENERAL 通用
- daemonize:设置后台启动,如果设置为 yes 表示允许后台启动 Redis,默认设置为 no。例如:daemonize yes。
- pidfile:设置存放 pid 文件的位置,每个实例会产生一个不同的 pid 文件。例如:pidfile /var/run/redis_6379.pid。
- loglevel:设置 Redis 的日志级别,共有四种日志级别,默认的日志级别是 notice,有如下 4 种取值:debug(记录大量日志信息,适用于开发、测试阶段)、verbose(较多日志信息)、notice(适量日志信息,适用于生产环境)、warning(仅有部分重要、关键信息才会被记录)。例如:loglevel notice。
- logfile:设置日志文件的位置,默认为空。例如:logfile “”。
- databases:数据库的数量,默认的数据库为 16 个,默认操作的数据库是 0 库。例如:databases 16。
- 限制
- maxclients:设置客户端的最大连接数,默认不启动该设置。例如:maxclients 10000。
- maxmemory:设置 Redis 可以使用的内存量,建议必须设置,否则,内存占满会造成服务器宕机。例如:maxmemory 。
- maxmemory-policy:设置移除策略,默认不启用该配置。例如:# maxmemory-policy noeviction。
- maxmemory-samples:设置样本数量,默认是不设置的。设置样本数量,LRU 算法和最小 TTL 算法都并非是精确的算法,而是估算值,所以你可以设置样本的大小,redis 默认会检查这么多个 key 并选择其中 LRU 的那个。一般设置 3 到 7 的数字,数值越小样本越不准确,但性能消耗越小。例如:maxmemory-samples 5。
- SECURITY 安全
- requirepass:设置客户端连接密码,默认是不启动的。例如:requirepass foobared。
(二)常用命令
- 全局命令介绍通用全局命令和常用全局命令
- get和set:redis 中最核心的命令是get和set,get根据 key 来取 value,只支持 string 类型的 value,其他类型的 value 不行;set把 key 和 value 存储进去。例如:set key value;get key。
- keys:用来查询当前服务器上匹配的 key,通过一些特殊符号(通配符)来描述 key 的模样,匹配上述模样的 key 就能被查询出来。支持如下统配样式:h?llo匹配hello,hallo和hxllo;h*llo匹配hllo和heeeello;h[ae]llo匹配hello和hallo但不匹配hilllo;[^e]llo匹配hallo,hbllo,… 但不匹配hello;h[a-b]llo匹配hallo和hbllo。语法:KEYS pattern。时间复杂度是 O (N),返回值:匹配pattern的所有 key。
- exists:判断某个 key 是否存在。语法:EXISTS key [key …]。时间复杂度:O (1),返回值:key 存在的个数。
- del:删除指定的 key,可以一次性删除一个或者多个。语法:DEL key [key …]。时间复杂度:O (1),返回值:删除掉的 key 的个数。
- expire:为指定的 key 添加秒级的过期时间(Time To Live TTL)。语法:EXPIRE key seconds。时间复杂度:O (1),返回值:1 表示设置成功。0 表示设置失败。
- ttl:获取指定 key 的过期时间,秒级。语法:TTL key。时间复杂度:O (1),返回值:剩余过期时间。-1 表示没有关联过期时间,-2 表示 key 不存在。
- type:返回 key 对应的数据类型。语法:TYPE key。时间复杂度:O (1),返回值:none,string,list,set,zset,hash and stream。
- 特定数据类型命令针对不同的数据类型,如字符串、哈希、列表、集合、有序集合等,介绍其常用命令
- 字符串:Redis 最常用的命令包括SET、GET、INCR、DECR、EXPIRE等。SET用于设置一个键值对,如果键已经存在,则会覆盖原来的值。例如:SET mykey “Hello World”。GET用于获取一个键的值。例如:GET mykey。INCR用于对一个键的值进行自增操作。例如:SET mycounter 0;INCR mycounter。DECR用于对一个键的值进行自减操作。例如:SET mycounter 1;DECR mycounter。EXPIRE用于设置一个键的过期时间(单位为秒)。例如:SET mykey “Hello World”;EXPIRE mykey 10。
- 哈希:HSET用于为哈希表中的字段设置值。如果哈希表不存在,则会创建一个新的哈希表。例如:HSET myhash field1 “Hello”。HGET用于获取哈希表中指定字段的值。例如:HGET myhash field1。
- 列表:RPUSH用于在列表的尾部添加一个或多个元素。如果列表不存在,则会创建一个新的列表。例如:RPUSH mylist “Hello” “World”。LRANGE用于获取列表中指定范围的元素。例如:RPUSH mylist “Hello” “World” “Redis”;LRANGE mylist 0 1。
- 集合:SADD用于向集合中添加一个或多个元素。如果集合不存在,则会创建一个新的集合。例如:SADD myset “Hello” “World”。SMEMBERS用于获取集合中的所有元素。例如:SMEMBERS myset。
- 有序集合:ZADD用于向有序集合中添加一个或多个元素。如果有序集合不存在,则会创建一个新的有序集合。例如:ZADD myzset 1 “Hello” 2 “World”。ZRANGE用于获取有序集合中指定范围内的元素。例如:ZADD myzset 1 “Hello” 2 “World” 3 “Redis”;ZRANGE myzset 0 1 WITHSCORES。
(一)发布和订阅
- 订阅发布消息图
- Redis 的发布订阅功能允许消息发布者将消息发送到特定的频道,而订阅者可以订阅这些频道以接收消息。可以用一个简单的示意图来表示这个过程,发布者作为消息的源头,将消息发送到一个或多个频道,订阅者则连接到 Redis 服务器并订阅感兴趣的频道,当有消息发布到订阅的频道时,订阅者就会收到消息。
- 发布订阅命令行实现
- Redis 提供了一组命令用于实现发布订阅功能。PUBLISH命令用于向指定频道发布消息,语法为PUBLISH channel message。例如,PUBLISH news_channel "Breaking News"将 “Breaking News” 这条消息发布到 “news_channel” 频道。SUBSCRIBE命令用于订阅一个或多个频道,语法为SUBSCRIBE channel [channel…]。比如,SUBSCRIBE sports_channel订阅 “sports_channel” 频道。当有其他客户端向 “sports_channel” 发布消息时,订阅者就会收到这条消息。PSUBSCRIBE命令可以进行模式匹配订阅,例如PSUBSCRIBE news.*,当有客户端向以 “news.” 开头的频道发布消息时,订阅者会收到消息。PUNSUBSCRIBE命令用于退订所有给定模式的频道,UNSUBSCRIBE命令用于退订给定的一个或多个频道的信息。
(二)新数据类型
- Bitmaps 简介及命令
- Bitmaps 不是一种独立的数据类型,实际上是对位操作的字符串(key-value)。它通过操作二进制位来进行记录,只有 0 和 1 两个状态,可以应用在统计用户每日打卡情况等场景。常用命令有setbit用于设置 Bitmaps 中某个偏移量的值,getbit获取 Bitmaps 中某个偏移量的值,bitcount统计字符串被设置为 1 的 bit 数,bitop可以做多个 Bitmaps 的 and(交集)、or(并集)、not(非)、xor(异或)操作并将结果保存在 destkey 中。
- HyperLogLog 简介及命令
- HyperLogLog 是一种用于基数统计的数据结构,可以用来估计一个集合中不同元素的数量,而不需要存储每个元素的具体值。优势在于其内存占用非常小,同时可以提供较高的近似精确度。常用操作有pfadd添加元素到指定 key 对应的集合中,pfmerge合并多个集合的基数到指定的 destkey 中,pfcount统计指定 key 中对应的基数值。
- Geospatial 简介及命令
- Geospatial 是一种地理空间数据结构,用于存储地理位置的信息。可以实现如计算两个位置之间的距离、查找附近的人这类依赖于地理位置信息的功能。基本操作有geoadd将指定经纬度的地理位置及其名称添加到指定的 zset 集合中,geopos根据 key、member 名称获取指定的经纬度,geodist返回两个给定位置之间的距离,georadius以给定的经纬度为中心,找出指定半径内的元素 member,georadiusbymember找出指定元素周围的其他元素,zrem删除指定的 member 元素,zrange查看指定 key 中对应的所有 member 元素。
(三)Jedis 测试
- 步骤
- 首先需要在项目中引入 Jedis 的依赖,例如在 Maven 项目中添加redis.clientsjedis3.1.0。然后可以使用 Jedis 来连接 Redis 服务器进行各种操作。比如,使用Jedis jedis = new Jedis(“localhost”, 6379);创建一个 Jedis 实例连接到本地的 Redis 服务器。可以使用jedis.publish(“channel”, “message”)向指定频道发布消息,使用jedis.subscribe(new JedisPubSub() {…}, “channel”)订阅指定频道并在回调方法中处理接收到的消息。
- 常用 API
- Jedis 提供了丰富的 API 用于与 Redis 进行交互。除了上述的发布和订阅相关的 API 外,还有如jedis.set(“key”, “value”)用于设置键值对,jedis.get(“key”)用于获取键对应的值,jedis.exists(“key”)判断键是否存在等。
(四)SpringBoot 整合
- 引入所需依赖
- 在 Spring Boot 项目中整合 Redis 需要引入spring-boot-starter-data-redis依赖。例如在 Maven 项目中添加org.springframework.bootspring-boot-starter-data-redis2.7.12。
- 添加配置
- 在application.properties文件中添加 Redis 的连接配置,如spring.redis.host=127.0.0.1设置 Redis 服务器地址,spring.redis.port=6379设置端口,spring.redis.password=yourpassword设置密码(如果有)。
- 封装关于 redis 的工具类
- 可以创建一个 Redis 工具类,用于封装常用的 Redis 操作。例如,可以创建一个RedisUtil类,在其中注入RedisTemplate,并提供方法如set(String key, Object value)用于设置键值对,get(String key)用于获取键对应的值等。
- 进行测试
- 可以创建一个测试类,注入 Redis 工具类并进行测试。比如,调用redisUtil.set(“testKey”, “testValue”)设置一个键值对,然后调用redisUtil.get(“testKey”)获取该键对应的值并进行验证。
(五)事务与锁机制
- Redis 的事务定义
- Redis 的事务允许客户端将多个命令放入一个队列中,然后一次性执行这些命令。事务中的命令在执行前会被放入队列中,当执行EXEC命令时,所有命令会被一次性执行,不会被其他客户端的命令打断。
- multi、exex、discard 命令
- MULTI命令用于开启一个事务,将后续的命令放入事务队列中。EXEC命令用于执行事务中的所有命令。DISCARD命令用于取消事务,清空事务队列中的所有命令。
- 悲观锁与乐观锁
- 悲观锁是一种保守的锁机制,它假设在事务执行过程中会有其他事务对数据进行修改,因此在事务开始时就会对数据进行加锁,防止其他事务对数据进行修改。在 Redis 中,可以使用WATCH命令来实现悲观锁。乐观锁则假设在事务执行过程中不会有其他事务对数据进行修改,因此在事务执行时不会对数据进行加锁,而是在提交事务时检查数据是否被其他事务修改过,如果被修改过,则回滚事务。
- Watch 监控
- WATCH命令用于监视一个或多个键,如果在事务执行之前这些键被其他客户端修改了,那么事务将被取消。例如,WATCH key1 key2监视 “key1” 和 “key2”,如果在事务执行之前这两个键被其他客户端修改了,那么事务将不会被执行。
- 事务的三个特性
- Redis 的事务具有三个特性:原子性、一致性和隔离性。原子性是指事务中的所有命令要么全部执行,要么全部不执行。一致性是指事务执行前后,数据库的状态必须是一致的。隔离性是指事务之间的操作是相互隔离的,一个事务的执行不会影响其他事务的执行。
(六)持久化
- RDB(Redis DataBase)
- 什么是 RBD:RDB 是 Redis 的一种持久化方式,通过快照的方式将内存中的数据保存到磁盘上。在指定的时间间隔内,Redis 会将内存中的数据集快照写入磁盘。
- 什么是 Fork:在执行 RDB 持久化时,Redis 会使用fork系统调用创建一个子进程。子进程负责将数据集写入临时文件,写入成功后,再替换旧的文件。
- dump.rdb:这是 RDB 持久化生成的文件,保存了 Redis 内存中的数据。
- AOF(Append Only File)
- 是什么:AOF 持久化是通过将 Redis 服务器执行的所有写命令记录到一个只追加的文件中,当 Redis 服务器重启时,可以通过重新执行这些写命令来恢复数据。
- 配置部分:可以在 Redis 的配置文件中设置appendonly yes来开启 AOF 持久化,并可以设置appendfsync选项来控制 AOF 文件的同步方式,有always(每次写入都同步)、everysec(每秒同步一次)和no(由操作系统决定何时同步)三种选项。
- AOF 数据恢复:当 Redis 服务器启动时,如果开启了 AOF 持久化,它会优先加载 AOF 文件来恢复数据。Redis 会逐行读取 AOF 文件中的写命令,并执行这些命令来恢复数据。
- Rewrite:随着 AOF 文件的不断增大,Redis 会自动对 AOF 文件进行重写,以去除其中的冗余命令,减小文件大小。重写过程使用了与 RDB 持久化类似的写时复制技术,先创建一个新的 AOF 文件,然后将旧的 AOF 文件中的命令进行重写并写入新文件,最后替换旧文件。
- 优缺点:AOF 持久化的优点是可以提供更好的数据持久性,并且可以通过设置不同的同步策略来平衡性能和数据安全性。缺点是 AOF 文件通常比 RDB 文件大,并且在重写过程中可能会占用一定的系统资源。
(七)主从复制
- 概念
- Redis 的主从复制是一种数据复制机制,允许一个 Redis 服务器(主服务器)的数据被复制到一个或多个其他 Redis 服务器(从服务器)。主从复制可以实现数据的备份、读写分离等功能。
- 主从复制配置
- 在 Redis 的配置文件中,可以通过设置slaveof选项来配置从服务器连接到主服务器。例如,slaveof 192.168.1.100 6379表示从服务器连接到 IP 地址为 192.168.1.100、端口为 6379 的主服务器。
- 常用三招
- 一主二仆:一个主服务器和两个从服务器的配置模式。主服务器负责写入数据,从服务器从主服务器同步数据并提供读服务。
- 薪火相传:从服务器也可以作为其他从服务器的主服务器,形成级联的主从复制结构。
- 反客为主:当主服务器出现故障时,可以手动将从服务器提升为主服务器,继续提供服务。
- 复制原理
- 从服务器通过向主服务器发送SYNC命令来开始一次复制过程。主服务器接收到SYNC命令后,会执行BGSAVE命令生成 RDB 文件,并使用缓冲区记录此后执行的所有写命令。主服务器将 RDB 文件发送给从服务器,从服务器载入 RDB 文件,然后主服务器将缓冲区中的写命令发送给从服务器,从服务器执行这些写命令,完成数据同步。此后,主服务器执行的写命令会通过复制协议实时同步到从服务器。
- 哨兵模式
- 哨兵模式是一种用于监控 Redis 主从服务器的高可用解决方案。哨兵可以自动检测主服务器的故障,并在主服务器故障时自动将从服务器提升为主服务器。哨兵通过向主从服务器发送命令和接收响应来监控它们的状态,并通过投票机制来决定是否进行故障转移。
(八)集群
- 问题
- 随着数据量的不断增大和访问量的不断增加,单台 Redis 服务器可能无法满足需求,需要一种能够水平扩展的解决方案。
- 什么是集群
- Redis 集群是一种分布式架构,将数据分布在多个 Redis 节点上,每个节点负责一部分数据的存储和处理。集群可以实现数据的自动分片、故障转移和高可用性。
- 准备开始搭建集群
- 首先需要准备多个 Redis 服务器,可以在不同的物理机或虚拟机上运行。然后需要修改 Redis 的配置文件,开启集群模式,并设置节点的端口号、IP 地址等信息。
- 什么是 slots
- Redis 集群将数据分为 16384 个 slots(槽),每个节点负责一部分 slots 的存储和处理。当客户端向集群发送一个命令时,Redis 会根据命令的 key 计算出对应的 slot,并将命令转发到负责该 slot 的节点上执行。
- -c 采用集群策略连接,设置的数据会自动切换到相应的写主机
- 在使用 Redis 客户端连接集群时,可以使用-c选项采用集群策略连接。这样,当客户端向集群发送一个命令时,客户端会自动根据命令的 key 计算出对应的 slot,并将命令转发到负责该 slot 的节点上执行。如果负责该 slot 的节点出现故障,客户端会自动切换到其他可用的节点上执行命令。
- 查询集群中的值
- 可以使用CLUSTER KEYSLOT命令来查询一个 key 对应的 slot,使用CLUSTER NODES命令来查看集群中的节点信息。
- 故障修复
- 当集群中的某个节点出现故障时,Redis 会自动进行故障转移。如果是主节点出现故障,从节点会被提升为主节点,并开始接收客户端的请求。故障节点恢复后,会作为从节点重新加入集群。
- 优缺点
- 优点:可以实现水平扩展,提高系统的性能和可用性;自动进行数据分片和故障转移,减少了人工干预的需求。缺点:配置和管理相对复杂;在进行数据迁移和故障转移时可能会出现短暂的性能下降。
(九)应用问题
- 缓存穿透
- 缓存穿透是指查询一个不存在的数据,由于缓存中没有该数据,所以会直接查询数据库。如果大量的请求都是查询不存在的数据,会给数据库带来很大的压力。可以通过使用布隆过滤器、对空结果进行缓存等方式来解决缓存穿透问题。
- 缓存击穿
- 缓存击穿是指一个非常热门的数据在缓存过期的瞬间,同时有大量的请求来查询这个数据,由于缓存中没有该数据,所以这些请求会直接查询数据库,给数据库带来很大的压力。可以通过设置热点数据永不过期、使用互斥锁等方式来解决缓存击穿问题。
- 缓存雪崩
- 缓存雪崩是指大量的缓存数据在同一时间过期,导致大量的请求直接查询数据库,给数据库带来很大的压力。可以通过设置不同的过期时间、使用分布式锁等方式来解决缓存雪崩问题。
(十)分布式锁
- 概念
- 分布式锁是一种在分布式系统中用于控制共享资源访问的机制。在分布式系统中,由于多个节点可能同时尝试访问共享资源,因此需要一种机制来保证在同一时间只有一个节点能够访问共享资源。
- 分布式锁的主流实现方案
- 目前,分布式锁的主流实现方案有基于数据库、基于 Zookeeper 和基于 Redis 等。基于 Redis 的分布式锁具有实现简单、性能高、可靠性好等优点。
- 使用 redis 实现分布式锁
- 设置锁和过期时间:可以使用SETNX命令来设置锁,并使用EXPIRE命令来设置锁的过期时间。例如,SETNX lock_key 1设置锁,EXPIRE lock_key 10设置锁的过期时间为 10 秒。
- UUID 防止误删:为了防止误删其他客户端设置的锁,可以在设置锁时为锁的值设置一个唯一的标识符,例如使用 UUID。在释放锁时,先判断锁的值是否与自己设置的标识符一致,如果一致则释放锁。
- LUA 保证删除原子性:为了保证释放锁的操作是原子性的,可以使用 LUA 脚本。LUA 脚本可以在 Redis 服务器端执行,保证多个命令的原子性。例如,可以使用以下 LUA 脚本释放锁:if redis.call(“get”,KEYS[1]) == ARGV[1] then return redis.call(“del”,KEYS[1]) else return 0 end。
- 分布式锁的几个必要条件:分布式锁需要满足以下几个必要条件:互斥性、可重入性、锁的自动释放、锁的高可用性和锁的高性能。
(一)构建实时消息系统
在构建实时消息系统时,Redis 的发布 / 订阅功能发挥了重要作用。通过PUBLISH和SUBSCRIBE命令,可以轻松实现消息的实时推送和接收。例如,在一个在线聊天应用中,可以将用户的 ID 作为频道,当用户登录时,使用SUBSCRIBE命令订阅自己的频道。当有其他用户向该用户发送消息时,服务器可以使用PUBLISH命令将消息发布到对应的频道,这样用户就能实时接收到消息了。
假设我们有一个在线教育平台,老师在直播授课时可以通过 Redis 的发布 / 订阅功能向学生实时推送教学内容。老师作为消息发布者,将教学内容发布到特定的频道,学生作为订阅者,订阅这个频道以接收消息。这样可以确保学生能够实时获取老师的授课内容,提高教学效果。
(二)实现分布式锁
在分布式系统中,多个客户端可能需要对共享资源进行并发访问。为了避免数据冲突和不一致,可以使用 Redis 实现分布式锁。具体做法是利用 Redis 的原子操作(如SETNX)来确保同一时间只有一个客户端能获取到锁。
例如,在一个电商平台的库存管理系统中,当多个用户同时购买同一件商品时,需要对库存进行减操作。为了避免超卖现象,可以使用 Redis 分布式锁。当一个客户端需要访问共享资源(即库存)时,先尝试获取锁;如果获取成功,则进行资源访问(即进行库存减操作);访问完成后释放锁。这样,其他客户端在锁被占用时只能等待,从而保证了并发访问的有序性。
(三)缓存热门数据
Redis 非常适合作为缓存来存储热门数据,如热门文章、商品信息等。通过SET和GET命令,可以快速地将数据存储在 Redis 中,并从 Redis 中读取数据。当数据库中的数据发生变化时,可以使用 Redis 的过期时间或监听数据库变更来更新缓存。
以一个新闻网站为例,热门新闻的访问量通常非常高。可以将热门新闻的内容存储在 Redis 缓存中,当用户请求热门新闻时,首先从 Redis 中获取数据,如果 Redis 中没有,则从数据库中获取并将数据存入 Redis 中。同时,可以设置一个合理的过期时间,比如 30 分钟。当数据库中的新闻内容发生变化时,可以通过监听数据库变更或者手动更新 Redis 缓存,以保证缓存中的数据与数据库中的数据一致。这样,大量的读请求可以直接从 Redis 中获取数据,减轻了数据库的压力,提高了系统的响应速度。
(四)案例实战分析
1. 避免使用 keys 命令优化慢查询
在实际应用中,应避免使用keys命令,因为它可能会导致性能问题。可以通过执行slowlog查看慢查询日志,找出使用性能差的keys命令的代码进行优化。
例如,在一个大型电商平台中,如果频繁使用keys命令来查询所有商品的键,可能会导致服务器响应缓慢。可以通过使用更具体的查询命令,如SCAN,来逐步遍历键空间,避免一次性获取所有键,从而提高查询性能。
2. 解决连接失效问题
设置timeout和tcp-keepalive可以清理失效连接,避免因网络闪断导致的客户端连接问题。
在一个分布式系统中,网络连接可能会出现不稳定的情况。通过设置合理的timeout时间,可以在客户端连接长时间无操作时自动关闭连接,释放资源。同时,设置tcp-keepalive可以定期发送保活探测报文,检测连接的有效性。如果连接出现问题,可以及时进行重连,保证系统的稳定性。
3. 处理内存分配问题
修改 Linux 内核参数vm.overcommit_memory=1,可以解决 Redis 在保存数据到磁盘时因内存不足导致的Fork子进程失败问题。
在一个高负载的 Redis 服务器上,如果内存分配不合理,可能会导致在进行持久化操作时出现问题。通过修改内核参数,可以允许 Redis 在内存不足时进行过度提交,确保Fork子进程能够成功创建,从而保证数据的持久化。但需要注意的是,过度提交内存可能会导致系统性能下降,因此需要根据实际情况进行调整。
(一)学习路径
- 入门基础
- 在入门阶段,首先要了解 Redis 的基本概念和特点。Redis 是一个高性能的内存数据库,支持多种数据结构,如字符串、哈希、列表、集合和有序集合等。通过阅读相关的文档和教程,了解 Redis 的安装过程和基本配置选项。
- 掌握 Redis 的数据结构和基本命令是入门的关键。可以通过实际操作 Redis 命令行客户端,熟悉各种数据结构的操作方法,如 SET、GET、HSET、HGET、LPUSH、RPUSH、SADD、ZADD 等命令。同时,学会使用 SELECT 命令切换数据库,以及使用 DBSIZE 命令查看数据库大小。
- 连接和配置 Redis 也是入门的重要内容。了解如何使用 Redis 客户端连接到 Redis 服务器,可以通过命令行客户端或者编程语言的 Redis 客户端库进行连接。同时,掌握 Redis 的配置文件的基本结构和常用配置选项,如端口号、绑定 IP、日志级别、持久化方式等。
- 进阶应用
- 深入研究持久化是进阶应用的重要部分。Redis 提供了两种持久化方式:RDB 和 AOF。RDB 是通过快照的方式将内存中的数据保存到磁盘上,而 AOF 是通过将写命令追加到日志文件中实现持久化。了解这两种持久化方式的优缺点和适用场景,以及如何配置和管理持久化。
- 发布与订阅是 Redis 的一个重要功能,可以实现消息的实时推送和接收。学习如何使用 PUBLISH 和 SUBSCRIBE 命令实现发布与订阅功能,以及如何使用 PSUBSCRIBE 命令进行模式匹配订阅。了解发布与订阅的应用场景,如实时消息系统、日志收集等。
- 事务和批处理也是进阶应用的重要内容。Redis 的事务可以保证一组命令的原子性执行,而批处理可以提高命令的执行效率。学习如何使用 MULTI、EXEC、DISCARD 命令实现事务,以及如何使用管道技术实现批处理。了解事务和批处理的应用场景,如数据一致性保证、批量数据处理等。
- 高级应用与性能优化
- 学习分布式缓存和高可用性是高级应用的重要部分。Redis 可以作为分布式缓存使用,提高系统的性能和响应速度。了解如何使用 Redis 实现分布式缓存,如缓存策略、缓存更新、缓存失效等。同时,学习 Redis 的高可用性解决方案,如主从复制、哨兵模式、集群模式等,了解这些方案的优缺点和适用场景。
- 掌握高级数据结构和应用场景是高级应用的另一个重要内容。Redis 除了基本的数据结构外,还提供了一些高级数据结构,如 HyperLogLog、Bitmaps、Geospatial 等。了解这些高级数据结构的特点和应用场景,如基数统计、用户行为分析、地理位置信息处理等。
- 进行性能优化和安全性加强也是高级应用的重要内容。了解 Redis 的性能优化方法,如内存优化、命令优化、网络优化等。同时,学习 Redis 的安全配置选项,如设置密码、限制访问 IP、使用 SSL 加密等,加强 Redis 的安全性。
- 实战应用和深入研究
- 通过实战案例学习最佳实践是实战应用的重要部分。可以参考一些实际的 Redis 应用案例,如电商平台的库存管理、社交网络的实时消息系统、新闻网站的缓存系统等,了解 Redis 在实际应用中的最佳实践和注意事项。
- 深入探究高级用法和定制化是实战应用的另一个重要内容。可以学习 Redis 的 Lua 脚本功能,实现复杂的业务逻辑和数据处理。同时,了解 Redis 的模块扩展机制,如 RedisModule、RedisJSON 等,实现定制化的功能扩展。
- 了解 Redis 生态系统和扩展是深入研究的重要内容。Redis 有一个丰富的生态系统,包括各种客户端库、工具和插件。了解这些生态系统的组成和使用方法,如 Jedis、Redisson、RedisInsight 等,以及如何使用这些工具和插件提高开发效率和管理 Redis 服务器。
(二)资源推荐
- 网站资源
- redis 中文官方网站是学习 Redis 的重要资源,提供了 Redis 的详细文档、下载链接、社区论坛等。在官方网站上,可以了解 Redis 的最新特性和版本更新,以及获取官方的技术支持和建议。
- Redis 命令参考是一个非常实用的网站,提供了 Redis 所有命令的详细说明和示例。在学习 Redis 命令时,可以参考这个网站,了解每个命令的用法和参数含义。
- 菜鸟教程 Redis 教程是一个适合初学者的教程网站,提供了 Redis 的基础知识和入门教程。在这个网站上,可以学习 Redis 的安装、配置、数据结构、命令等基本内容,以及一些简单的应用案例。
- Redisson 官网是一个 Java 语言的 Redis 客户端库,提供了丰富的功能和强大的性能。在使用 Java 开发 Redis 应用时,可以参考 Redisson 官网,了解 Redisson 的用法和示例,以及获取技术支持和建议。
- 宝藏博主博客是一个个人博客,作者分享了很多关于 Redis 的学习经验和实战案例。在这个博客上,可以学习到一些实用的 Redis 技巧和方法,以及了解 Redis 在实际应用中的一些问题和解决方案。
- 视频资源
- 尚硅谷的 Redis 视频教程是一个非常全面的教程,涵盖了 Redis 的基础知识、高级特性、实战案例等内容。在这个教程中,讲师讲解详细,示例丰富,适合初学者和进阶者学习。
- 狂神说 Java 的 Redis 视频教程是一个幽默风趣的教程,讲师通过生动的例子和形象的比喻,讲解 Redis 的知识和应用。在这个教程中,讲师注重实践操作,让学习者能够快速掌握 Redis 的使用方法。
- 黑马程序员的 Redis 视频教程是一个专业的教程,涵盖了 Redis 的基础知识、高级特性、实战案例等内容。在这个教程中,讲师讲解深入,注重原理分析,适合进阶者学习。
- 图灵学院的 Redis 视频教程是一个深入的教程,涵盖了 Redis 的高级特性、实战案例、性能优化等内容。在这个教程中,讲师讲解详细,注重实战操作,适合高级开发者学习。
- 书籍推荐
- 《Redis 深度历险》是一本非常好的 Redis 书籍,作者通过丰富的实战案例和深入的原理分析,讲解 Redis 的知识和应用。在这本书中,作者介绍了 Redis 的数据结构、持久化、发布与订阅、事务、Lua 脚本、分布式锁等内容,以及如何在实际项目中使用 Redis。这本书适合有一定 Redis 基础的读者阅读,能够帮助读者深入理解 Redis 的原理和应用。
版权声明:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权、违法违规、事实不符,请将相关资料发送至xkadmin@xkablog.com进行投诉反馈,一经查实,立即处理!
转载请注明出处,原文链接:https://www.xkablog.com/rfx/12180.html