Skip to content

Commit

Permalink
update:15 articles
Browse files Browse the repository at this point in the history
  • Loading branch information
alu234 committed Mar 8, 2024
1 parent 8909614 commit 2d42168
Show file tree
Hide file tree
Showing 17 changed files with 153 additions and 0 deletions.
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,21 @@
* [数据库的ACID特性](./problems/数据库的ACID特性.md)
* [MySQL的主从复制是如何实现的?](./problems/MySQL的主从复制是如何实现的?.md)
* [mysql的索引都有那些?](./problems/mysql的索引都有那些?.md)
* [Redis 有什么作用?为什么要用 Redis](./problems/Redis有什么作用?为什么要用Redis.md)
* [Redis 的底层数据结构有哪些](./problems/Redis的底层数据结构有哪些.md)
* [介绍 intset 及其升级过程,支持降级吗](介绍intset及其升级过程,支持降级吗.md)
* [介绍 SDS,Redis 为什么要使用 SDS 而不是 C 字符串](./problems/介绍SDS,Redis为什么要使用SDS而不是C字符串.md)
* [介绍 dict,什么是 rehash?什么是渐进式 rehash](./problems/介绍dict,什么是rehash?什么是渐进式rehash.md)
* [介绍 ziplist,什么是连锁更新?quicklist、lispack](./problems/介绍ziplist,什么是连锁更新?quicklist、lispack.md)
* [介绍 Redis 的 skiplist](./problems/介绍Redis的skiplist.md)
* [Redis 数据类型(对象)有哪些](./problems/Redis数据类型(对象)有哪些.md)
* [Redis String 原理和使用场景(分布式锁)](./problems/RedisString原理和使用场景(分布式锁).md)
* [Redis List 的原理和使用场景](./problems/RedisList的原理和使用场景.md)
* [Redis Set 的原理和使用场景](./problems/RedisSet的原理和使用场景.md)
* [Redis ZSet 的原理和使用场景(延迟队列)](./problems/RedisZSet的原理和使用场景(延迟队列).md)
* [为什么 Zset 需要同时使用跳表和字典来实现?](./problems/为什么Zset需要同时使用跳表和字典来实现?.md)
* [为什么 Redis 使用跳表而不是红黑树来实现 Zset](./problems/为什么Redis使用跳表而不是红黑树来实现Zset.md)
* [Redis Hash 的原理和使用场景](./problems/RedisHash的原理和使用场景.md)

# 海量数据处理

Expand Down
13 changes: 13 additions & 0 deletions problems/RedisHash的原理和使用场景.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
### Redis Hash 原理:

- Redis的Hash是一个键值对集合,类似于Python的字典(dictionary),可以存储多个字段和对应的值。
- 在内部实现上,Redis的Hash使用类似于Java HashMap的方式来存储数据,通过哈希表和链地址法解决哈希冲突。
- Hash在Redis中是一种非常高效的数据结构,可以快速插入、查找、更新和删除字段及其对应的值。

### Redis Hash 使用场景:

1. **存储对象属性**:Hash适合用于存储对象的属性信息,比如用户信息、商品详情等。每个字段表示对象的一个属性,对应的值为属性值,方便管理和查询。
2. **缓存数据**:Hash可以作为缓存数据的存储结构,将复杂数据序列化后存储在Hash中,快速读取以提升性能。
3. **计数器**:Hash的字段值可以是整数类型,因此可以用于实现计数器功能,比如统计网站访问量、点赞次数等。
4. **配置信息**:Hash可用于存储配置信息,例如系统参数、功能开关等,方便进行动态调整。
5. **存储用户会话信息**:Hash可以用来存储用户的会话信息,每个用户对应一个Hash,字段表示不同的会话属性。
12 changes: 12 additions & 0 deletions problems/RedisList的原理和使用场景.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
### Redis List 原理:

- Redis的List类型是一个双向链表,支持在两端进行元素的插入和删除操作,即头部(左侧)和尾部(右侧)。
- List可以存储有序的字符串元素,允许重复元素的存在,内部采用链表结构来存储数据。
- List类型提供了丰富的操作命令,如从指定位置插入元素、获取范围内的元素、根据值查找索引等。

### Redis List 使用场景:

1. 消息队列:List类型常用于实现简单的消息队列,生产者通过将消息推入列表尾部,消费者则从列表头部弹出消息,实现基本的消息发布与订阅功能。
2. 实时排行榜:可以利用List类型存储用户得分信息,并根据得分的高低排序,快速获取用户在排行榜中的位置。
3. 循环任务调度:通过List的阻塞弹出操作(BLPOP、BRPOP)实现轮询循环任务的调度,比如定时任务、延时任务等。
4. 数据同步:List类型可以用于记录数据变更日志,实现数据同步功能,生产端生成数据变更事件并推入列表,消费端消费事件并执行相应的同步操作。
12 changes: 12 additions & 0 deletions problems/RedisSet的原理和使用场景.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
### Redis Set 原理:

- Redis的Set类型是一个无序、不重复的集合,内部使用哈希表实现,保证了集合中元素的唯一性。
- Set类型支持添加、删除、判断元素是否存在等操作,时间复杂度为O(1)。
- Redis还提供了丰富的集合运算命令,如求交集、并集、差集等,方便对多个集合进行操作。

### Redis Set 使用场景:

1. 标签系统:Set类型适合用于存储对象的标签信息,每个对象可以关联一个或多个标签,通过集合操作实现标签之间的交集、并集查询。
2. 好友关系:可以将用户的好友列表存储在Set中,利用集合运算命令快速实现共同好友、推荐好友等功能。
3. 唯一性校验:通过Set类型存储数据的唯一性信息,可以快速进行去重操作,确保数据的唯一性。
4. 点赞/收藏功能:可以利用Set类型记录用户点赞或收藏的内容,确保每个用户对同一内容只能进行一次操作。
13 changes: 13 additions & 0 deletions problems/RedisString原理和使用场景(分布式锁).md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Redis中的String是一种简单的键值对数据类型,用于存储字符串、整数或二进制数据。在Redis中,String类型是最基础和常用的数据类型之一。

### Redis String原理:

- String在Redis中是一个二进制安全的字符串,可以存储任意类型的数据。
- Redis的String类型是动态字符串(dynamic string),即内部使用了预分配的缓冲区来保存字符串值,并能够自动扩展。
- String类型支持常见的操作,如设置值、获取值、追加、自增、自减等,操作时间复杂度为O(1)。

### Redis String使用场景:

1. 缓存:String类型常用于缓存数据,如缓存页面内容、计算结果等。由于Redis的快速读写能力,String类型适合作为缓存数据的存储方式。
2. 计数器:可以利用String的自增、自减操作实现计数器功能,如统计网站访问量、商品库存等。
3. 分布式锁:通过String类型的SETNX命令(Set if Not eXists)可以实现分布式锁。即当某个键不存在时,设置该键为特定值,以此实现互斥锁的功能。
12 changes: 12 additions & 0 deletions problems/RedisZSet的原理和使用场景(延迟队列).md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
### Redis ZSet 原理:

- Redis的ZSet(有序集合)是在Set基础上增加了一个分数(score)字段,用于对集合中的元素进行排序。
- ZSet内部使用跳跃表(Skip List)和哈希表结合的方式实现,保证了元素的有序性和唯一性。
- ZSet支持添加、删除、更新元素,并且可以根据分数范围、排名等条件快速获取元素。

### Redis ZSet 使用场景:

1. 排行榜:ZSet适合用于实现各种类型的排行榜功能,比如用户积分排行榜、文章热度排行榜等,通过设置分数来排序。
2. 时间轴:可以利用ZSet记录时间戳及相关事件信息,实现用户时间轴功能,按时间顺序展示用户的动态。
3. 延迟队列:ZSet常用于实现延迟队列,即将需要延迟处理的任务以时间戳作为分数存储在有序集合中,通过定时轮询或者通过有序集合提供的带有时间区间的命令来获取需要执行的任务。
4. 范围查询:ZSet提供了根据分数范围获取元素的功能,可用于实现范围查询,比如根据积分范围查找用户。
13 changes: 13 additions & 0 deletions problems/Redis数据类型(对象)有哪些.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Redis中有五种主要的数据类型(对象),分别是:

1. String(字符串):最简单的数据类型,可以存储文本、整数或二进制数据。常见的操作包括设置和获取值、追加、自增、自减等。
2. List(列表):有序的字符串列表,支持从两端进行插入、删除操作,提供了丰富的列表操作命令,如插入元素、弹出元素、范围查询等。
3. Set(集合):无序的字符串集合,不允许重复元素的存在,常用于存储唯一值,并提供了集合运算(交集、并集、差集)等功能。
4. Hash(哈希):键值对的集合,适用于存储对象属性等结构化数据,常用于存储用户信息、配置信息等。
5. Sorted Set(有序集合):类似于集合,但每个元素都关联一个分数(score),根据分数进行排序。常用于实现排行榜、计分板等需求。

除了上述五种主要的数据类型外,Redis还支持一些其他数据类型,如:

- HyperLogLog:用于基数统计的数据结构,可以估算集合中不同元素的数量。
- GeoSpatial:用于存储地理位置信息的数据结构,支持空间索引和相关的地理位置查询操作。
- Bitmaps:位图数据结构,适用于高效存储位操作相关的信息,如用户在线状态、用户签到记录等。
7 changes: 7 additions & 0 deletions problems/Redis有什么作用?为什么要用 Redis.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Redis是一个开源的内存数据库,它主要用于缓存、消息队列、会话管理等功能。Redis具有以下几个作用和优点:

1. 快速:Redis将数据存储在内存中,因此读写速度非常快,适合对响应时间要求较高的场景。
2. 支持丰富的数据结构:除了简单的字符串外,Redis还支持列表、集合、有序集合、哈希等复杂数据结构,使其适用于各种场景。
3. 持久化:Redis支持数据的持久化,可以定期将内存中的数据保存到磁盘,保证数据不丢失。
4. 高并发:Redis支持多个客户端同时访问,并且提供了原子性操作,保证数据的一致性。
5. 分布式:Redis支持分布式部署,可以通过主从复制、集群等方式实现水平扩展。
7 changes: 7 additions & 0 deletions problems/Redis的底层数据结构有哪些.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Redis的底层数据结构主要包括以下几种:

1. 字符串(string):最简单的数据结构,可以存储字符串、整数或者浮点数。
2. 列表(list):一个双向链表,可以存储有序的字符串元素。
3. 集合(set):一个无序集合,其中的每个元素都是唯一的。
4. 有序集合(sorted set):类似于集合,但每个元素都会关联一个分数,根据分数可以进行排序。
5. 哈希表(hash):类似于关联数组,可以存储键值对。
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Redis在实现ZSet(有序集合)时选择使用跳表而不是红黑树的主要原因包括:

1. **实现简单**:跳表相对于红黑树来说,实现更加简单和直观。跳表的数据结构相对较为简单,易于理解和实现,而红黑树则需要复杂的平衡调整操作,实现难度较大。
2. **性能稳定**:虽然红黑树在理论上的时间复杂度(O(log n))比跳表略优,但跳表在实际应用中的性能表现通常更加稳定。跳表无需频繁的旋转和颜色调整等操作,对于插入、删除等操作的性能更加稳定可靠。
3. **空间占用**:相比红黑树,跳表的实现更加简洁,不需要维护额外的颜色信息和指针关系,因此在一定程度上节省了空间。这对于内存占用敏感的场景而言尤为重要。
4. **易扩展性**:跳表的结构天然支持并发访问和快速查找,适合于分布式环境下的并发操作。而红黑树在分布式环境下的并发性能可能会受到一定影响。
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Redis的ZSet(有序集合)需要同时使用跳表和字典来实现,主要是为了综合利用二者各自的优势,以提高数据结构的性能和效率,具体原因包括:

1. **有序性和快速查找**:跳表(Skip List)作为一种有序数据结构,可以保证元素按照分数有序存储。而哈希表(字典)则提供了快速的查找操作,通过元素的键值直接定位元素,时间复杂度为O(1)。结合跳表和哈希表,可以同时满足有序性和快速查找的需求。
2. **元素唯一性**:跳表可以保证集合中元素的唯一性,即相同的元素只会出现一次。在ZSet中,每个元素在跳表中对应一个节点,在哈希表中对应一个键值对,通过这两者的配合实现了元素唯一性。
3. **排序和范围查询**:ZSet常用于需要按照分数排序和根据分数范围查询元素的场景。跳表提供了按照分数有序排列的功能,使得范围查询操作更加高效。
4. **内存占用和性能平衡**:跳表在实现时相对比较灵活,但消耗的额外内存较多;而哈希表可以高效地存储键值对,但无法保证有序性。利用跳表和哈希表的结合,可以在内存占用和性能之间取得一个平衡,既保证了有序性又提升了查找效率。
7 changes: 7 additions & 0 deletions problems/介绍 Redis的skiplist.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Redis中的skiplist(跳表)是一种有序数据结构,用于实现有序集合(sorted set)数据类型。skiplist通过层级索引的方式来加快元素的查找速度,同时保持元素的有序性。

在skiplist中,每个节点包含一个指向下一个节点的指针,以及若干个指向同一层级的其他节点的指针。通过这种多级索引的方式,skiplist可以在查找时进行跳跃,从而减少查找的时间复杂度,提高了查找效率。

skiplist的插入、删除和查找操作的平均时间复杂度为O(log n),在元素数量较大时依然能够保持较高的性能。相比于传统的平衡树结构,skiplist的实现更加简单,并且在维护有序集合的基础上兼顾了高效的查找性能。

Redis使用skiplist作为有序集合(sorted set)数据类型的底层实现,通过skiplist可以支持有序集合中元素的快速查找、插入、删除等操作。skiplist在Redis中发挥着重要的作用,为有序集合类型带来了高效的操作性能和良好的扩展性。
5 changes: 5 additions & 0 deletions problems/介绍 intset及其升级过程,支持降级吗.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
intset是Redis中用于存储整数集合的数据结构。它是一种紧凑且高效的数据结构,能够在内存中存储一组整数,并且根据整数的类型使用不同的编码方式,包括int16、int32和int64,以节省内存空间。

在Redis中,当一个intset需要插入一个新元素时,会先判断该元素的类型是否超过了当前intset所能存储的最大类型,如果超过了,则会触发升级过程。升级过程会重新分配一个更大的intset,并将原有的元素全部复制到新的intset中,然后再插入新的元素。这样可以确保intset始终选择最适合的编码方式来存储整数,避免浪费内存空间。

至于降级操作,Redis并没有提供直接的降级机制。一旦intset发生了升级,就无法再回到低级别的编码方式。因为降级可能导致数据精度丢失或者造成数据不一致,所以Redis设计上保持了一种"只升级不降级"的策略。因此,在使用intset时,需要根据实际情况选择合适的整数数据范围,避免频繁升级带来的性能损耗。
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
SDS(Simple Dynamic Strings)是Redis自己实现的动态字符串结构,相比于C语言中的普通字符串(以'\0'结尾的字符数组),SDS具有以下优势:

1. 动态扩容:SDS可以根据需要动态分配内存空间,随着字符串长度的增加而自动扩容,避免了C字符串需要手动管理内存大小的问题。
2. 高效获取长度:SDS结构中包含了字符串的长度信息,因此获取字符串长度的操作时间复杂度为O(1),而C字符串需要遍历整个字符串才能获取长度。
3. 二进制安全:SDS可以存储任意二进制数据,不受'\0'结束符限制,适合存储图片、视频等二进制数据。
4. 兼容部分C字符串函数:Redis实现了一些SDS专属的API,并且支持一部分C字符串API,方便在一定情况下进行转换和使用。
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
在Redis中,dict(字典)是一种用于存储键值对的数据结构,它类似于哈希表,可以实现快速的查找、插入和删除操作。dict内部使用哈希表来存储键值对,每个键值对会映射到哈希表中的一个桶(bucket)中。

rehash是指Redis在进行扩容或缩容时,重新计算并重建哈希表的过程。当哈希表中元素数量超过了指定阈值(load factor)时,Redis会触发rehash操作来扩容哈希表,以减少冲突并提高查询效率。反之,如果元素数量变少,Redis也会通过rehash来缩小哈希表,节省内存空间。

渐进式rehash是一种优化技术,用于在进行rehash操作时避免长时间阻塞服务。传统的rehash操作需要一次性将所有键值对重新映射到新的哈希表中,可能会造成短暂的阻塞,影响系统性能。而渐进式rehash则会将rehash操作分解为多个小步骤,每次处理一部分键值对,逐步完成整个rehash过程,让系统在较长时间内平稳进行rehash操作,避免长时间阻塞。

通过渐进式rehash,Redis可以在不影响系统性能的情况下进行哈希表的扩容或缩容操作,保证服务的持续可用性。这种方式使得Redis能够更好地处理大规模数据集的哈希表操作,提升系统的稳定性和性能。
5 changes: 5 additions & 0 deletions problems/介绍intset及其升级过程,支持降级吗.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
intset是Redis中用于存储整数集合的数据结构。它是一种紧凑且高效的数据结构,能够在内存中存储一组整数,并且根据整数的类型使用不同的编码方式,包括int16、int32和int64,以节省内存空间。

在Redis中,当一个intset需要插入一个新元素时,会先判断该元素的类型是否超过了当前intset所能存储的最大类型,如果超过了,则会触发升级过程。升级过程会重新分配一个更大的intset,并将原有的元素全部复制到新的intset中,然后再插入新的元素。这样可以确保intset始终选择最适合的编码方式来存储整数,避免浪费内存空间。

至于降级操作,Redis并没有提供直接的降级机制。一旦intset发生了升级,就无法再回到低级别的编码方式。因为降级可能导致数据精度丢失或者造成数据不一致,所以Redis设计上保持了一种"只升级不降级"的策略。因此,在使用intset时,需要根据实际情况选择合适的整数数据范围,避免频繁升级带来的性能损耗。
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
ziplist是Redis中用于存储小规模列表和哈希集合的紧凑数据结构。ziplist将多个元素连续地存储在一段内存区域中,节省了内存空间,并且在元素数量较少时可以提高访问效率。

连锁更新是指在进行ziplist插入操作时,如果新元素的大小超过了ziplist当前可用的剩余空间,则会触发连锁更新机制。连锁更新会将当前的ziplist转换为一个普通的链表结构(即linked list),然后再进行插入操作,以确保插入成功。

quicklist是Redis中用于存储列表类型的数据结构,它由多个ziplist组成的列表的双向链表。quicklist可以在不同的ziplist之间进行快速的插入和删除操作,同时也支持在两端进行快速的推入和弹出操作,适用于需要频繁修改的列表场景。

lispack是Redis Labs开发的一种新型数据结构,旨在更好地处理大规模的列表数据。lispack结合了quicklist和压缩列表的优势,采用分层结构存储数据,并支持批量、范围等操作,提升了对大规模列表数据的处理性能和效率。lispack的引入使得Redis在处理大型列表时具有更好的灵活性和性能优势。

0 comments on commit 2d42168

Please sign in to comment.