学习笔记-LEC10-Redis-大厂程序员是怎么用的 | 青训营
第十节课《Redis - 大厂程序员是怎么用的》
1. 什么是Redis
Redis(Remote Dictionary Server)是一种开源的内存数据存储系统,常被称为"数据结构服务器",它支持多种数据结构,如字符串(Strings)、哈希(Hashes)、列表(Lists)、集合(Sets)、有序集合(Sorted Sets)等。Redis主要特点是将数据存储在内存中,以提供快速的读写访问速度,这使得它在需要高性能、低延迟的应用中得到广泛应用,如缓存、会话存储、排行榜等场景。
热数据和冷数据是在数据管理和缓存领域经常被用到的概念:
- 热数据(Hot Data): 热数据指的是经常被访问的数据,通常是应用中活跃的数据。这些数据具有较高的访问频率,因此将它们放在高速缓存中(如Redis)可以显著提高读取速度和性能。热数据一般不适合被移动或淘汰,因为它们持续被频繁访问。
- 冷数据(Cold Data): 冷数据指的是不经常被访问的数据,通常是应用中不太活跃的数据。这些数据的访问频率较低,因此将它们保留在高速缓存中可能是浪费资源。冷数据可以被移动到较慢但更廉价的存储介质中,以释放内存或其他资源。这种策略被称为"数据分层",通过将不同访问频率的数据放置在不同的存储层中,可以优化系统的性能和成本效益。
在使用Redis作为缓存层时,热数据通常会被放置在Redis中,以提供快速的读取访问。 而冷数据可能会根据其访问频率和重要性被保留在数据库等持久存储中。这种分层策略可以平衡性能需求和资源利用率。
如何与mysql(存储冷数据)协作
图上标的写场景的同步实现方式只是一种:解析数据库更新时的binlog来同步更新redis
Redis基本工作原理
AOF(Append-Only File): AOF是一种持久化方式,它记录了每个写操作(包括添加、修改、删除)的命令,以追加的方式将这些命令写入一个文件。AOF文件可以在服务器重启时重新执行,以恢复数据。
RDB(Redis Database): RDB是另一种持久化方式,它通过将数据在指定时间间隔内快照到硬盘上的二进制文件中来实现。RDB文件可以看作是数据库在某个时间点的快照,用于在服务器重启时恢复数据。
重新启动时先利用RDB往内存中恢复数据,再看AOF中有没有没执行到的命令/操作,从而进行执行,这样就能一定程度实现redis的持久化
单线程处理所有操作命令
意思就是只能排队顺序执行
2. Redis应用案例
1. 连续签到
-
使用expireAt设置过期时间
-
// 连续签到数+1
err := RedisClient.Incr(ctx, key).Err()
主要就是使用了Incr这个函数来加一
2. 消息通知
ES:
Elasticsearch(ES): Elasticsearch 是一个开源的分布式搜索和分析引擎,用于快速地存储、搜索和分析大量数据。它被广泛用于构建全文搜索、日志分析、实时数据分析和数据可视化等应用。ES以分布式、近实时、多租户、可扩展和高性能等特点而闻名。
Redis的List是QuickList
QuickList 是 Redis 中一种用于存储列表数据结构的优化数据结构。它是由双向链表(doubly linked list)和 Listpack(一种紧凑的列表编码格式)组合而成的。QuickList 在 Redis 3.2 版本引入,旨在提高列表操作的性能和内存效率。
具体来说,QuickList 的设计目标是在保持双向链表的快速插入、删除操作的同时,通过使用紧凑的 Listpack 编码格式,减少内存占用。这对于存储大量列表数据时尤其有用。
3. 计数
计数结果存在redis比较方面,因为访问比较频繁嘛,主页上都会有这项内容
但是怎么做到一个key对应6个计数呢?使用Hash的Dict
一个key对应一个Dict,一次就能拿到6个数据
redis中的渐进式rehash
其实就是在用户访问数据的时候,就把他访问的数据迁移到新hashtable中去,这样就能逐渐实现迁移,不至于整个拷贝太过耗时
渐进式 rehash 是 Redis 中一种处理哈希表扩容的方法,它允许在 Redis 运行时动态地将旧的哈希表逐渐迁移到新的更大的哈希表中,以实现扩容操作。渐进式 rehash 可以在不影响 Redis 读写操作的情况下进行,以避免系统停机时间。
需要进行 rehash 的原因主要是为了扩容。当哈希表中的元素数量增加,导致哈希冲突增多,影响哈希表的性能时,就需要进行扩容操作。扩容的目标是增加哈希表的大小,使得每个哈希桶(bucket)中的元素数量更少,从而降低哈希冲突的概率,提高查找效率。
具体的原因包括:
- 减少哈希冲突: 哈希表在装载因子(load factor)较高时,哈希冲突会增多,导致查找操作的效率下降。通过扩容,可以减少装载因子,减少哈希冲突。
- 提高性能: 扩容后的哈希表具有更大的容量,可以容纳更多的元素,提高了哈希表的性能和容量。
- 适应数据增长: 随着时间的推移,数据集可能会不断增长,扩容可以使哈希表适应数据的增加。
- 平衡负载: 扩容可以在不同的节点上平衡负载,将数据均匀分布在多个哈希表中,提高系统的可扩展性和负载均衡。
在 Redis 中,渐进式 rehash 的过程如下:
- 创建一个新的空哈希表,大小为原哈希表的两倍。
- 在新哈希表中渐进地将旧哈希表中的元素迁移过去,逐渐完成。
- 在迁移过程中,对于一个给定的键,它可能同时存在于旧哈希表和新哈希表中,Redis 在读取操作中会同时查询两个哈希表,然后将元素逐步从旧哈希表迁移到新哈希表中。
- 当所有元素都从旧哈希表迁移到新哈希表后,旧哈希表会被释放。
需要注意的是,扩容操作是一个相对复杂的过程,它会在一定程度上消耗系统资源。因此,在进行渐进式 rehash 操作时,需要根据实际情况合理安排,以避免影响系统性能。
4. 排行榜
为什么不使用mysql?
因为mysql是关系型数据库,只能记录一条条记录,排行榜需要排序,几千万条记录经常去排序显然会遇到很大的性能问题
虽然在某些情况下可以使用 MySQL 实现排行榜功能,但是相对于 Redis 的有序集合,MySQL 可能会遇到一些性能瓶颈和问题。以下是一些考虑因素:
- 性能和响应时间: MySQL 是关系型数据库,需要进行连接、查询和索引操作,相对而言在插入、更新和查询操作上可能比 Redis 的有序集合慢,尤其在高并发环境下。排行榜功能通常需要频繁的读写操作,使用 Redis 可以更快地响应请求。
- 索引维护: 如果排行榜需要按照分数进行排序,那么在 MySQL 中需要建立相应的索引,但索引会带来维护成本,尤其是在频繁插入和更新的情况下。
- 内存占用: MySQL 在处理大量数据时需要更多的内存,而 Redis 在内存使用和管理上更加灵活。排行榜可能涉及大量的用户或成员,使用 Redis 可以更好地处理这些情况。
- 扩展性: MySQL 的扩展性需要考虑复杂的集群和分片架构,而 Redis 支持分布式架构,并且可以更容易地扩展。
- 持久性和备份: MySQL 需要更多的配置和管理来实现数据的持久性和备份,而 Redis 提供了持久性机制,并且可以更轻松地进行数据备份。
- 复杂性: MySQL 是一个功能强大的数据库系统,但在一些简单的场景中,使用 Redis 的有序集合可以更加轻量和简单,减少配置和管理的复杂性。
需要注意的是,每个应用场景都有不同的需求和约束,因此选择使用 Redis 还是 MySQL 取决于你的具体情况。如果你的排行榜功能对性能和响应时间要求较高,同时需要处理大量的读写操作,使用 Redis 的有序集合可能更为适合。然而,如果你已经熟悉 MySQL 或者系统已经在使用 MySQL,也可以根据自己的情况来权衡使用哪种数据库。
redis的zset
在实现排行榜(Leaderboard)功能时,使用 Redis 的有序集合(Sorted Set,也叫做 zset)是一种非常常见和有效的方法。这是因为 Redis 的有序集合提供了一些特性,使得它非常适合用于构建排行榜功能。
- 有序性: 有序集合是有序的数据结构,它可以为每个成员(例如玩家、用户等)分配一个分数。这个分数可以用来进行排序,从而实现排行榜中的元素按照某种顺序(如分数高低、得分多少等)排列。
- 高效的插入和更新: Redis 的有序集合支持快速的插入和更新操作,可以用来迅速添加或更新排行榜中的成员。使用
ZADD命令可以方便地实现这些操作。 - 高效的范围查询: Redis 的有序集合支持按照分数范围进行查询,例如获取前 N 名玩家。这些查询操作在有序集合中的数据结构下非常高效。
- 去重和唯一性: 每个成员在有序集合中是唯一的,这可以确保每个玩家或用户在排行榜中只出现一次,避免了重复计算。
- 支持分数变化: 如果需要实时更新玩家或用户的分数,有序集合提供了更新分数的命令,如
ZINCRBY,可以方便地增加或减少分数。 - 持久性和持久化: Redis 可以将数据持久化到磁盘上,确保排行榜数据的持久性。同时,有序集合的特性使得在 Redis 重启后能够快速恢复排行榜数据
zset的数据结构 zskiplist + HashDict
skiplist
跳跃表(Skip List)是一种基于有序链表的数据结构,它在有序集合中支持快速查找、插入和删除操作。跳跃表通过引入多层次的链表,以一种随机化的方式来提高查找的效率,类似于平衡树,但更简单和易于实现。
跳跃表的主要特点和原理包括:
- 多层链表结构: 跳跃表包含多层链表,每一层都是原始有序链表的一个子集。最底层是原始有序链表,每一层都是前一层的稀疏子集。
- 节点索引: 每个节点都包含一个数据元素,以及指向下一层和右侧元素的指针。上层的节点是下层节点的索引,它们指向下层的节点,从而允许跳跃式查找。
- 随机性: 跳跃表的建立和更新操作中使用随机数来决定节点是否升级到更高的层级。这种随机性可以确保跳跃表保持平衡,避免了像平衡树那样的复杂平衡操作。
- 查找效率: 跳跃表通过多层索引的方式,可以在平均情况下在O(log n)时间内进行查找操作,这使得它适用于快速检索有序数据。
- 插入和删除: 插入和删除操作相对简单,可以在O(log n)时间内完成。当插入或删除导致某个节点的索引层级减少,会逐步删除不再需要的索引。
- 空间复杂性: 跳跃表相对于平衡树等数据结构来说,其空间复杂性较低,只需要额外存储索引节点,而不需要平衡操作和旋转。
跳跃表在一些情况下可以作为有序集合的替代品,特别是在需要高效的插入、删除和查找操作时。然而,它并不是适用于所有情况的最佳选择,在特定的业务需求和性能要求下,需要综合考虑使用跳跃表还是其他数据结构。