Redis核心数据结构与分布式锁实现详解

本文涉及的产品
实时计算 Flink 版,1000CU*H 3个月
智能开放搜索 OpenSearch行业算法版,1GB 20LCU 1个月
实时数仓Hologres,5000CU*H 100GB 3个月
简介: Redis 是高性能键值数据库,支持多种数据结构,如字符串、列表、集合、哈希、有序集合等,广泛用于缓存、消息队列和实时数据处理。本文详解其核心数据结构及分布式锁实现,帮助开发者提升系统性能与并发控制能力。

Redis 核心数据结构与分布式锁实现详解

Redis 是一个开源的高性能键值对数据库,广泛应用于缓存、消息队列、实时数据处理等场景。它通过内存存储和高效的数据结构,极大地提升了系统的性能。了解 Redis 核心数据结构及其实现的分布式锁,可以帮助我们在实际开发中更好地利用 Redis。


一、Redis 核心数据结构

Redis 提供了多种数据结构,每种数据结构都能在不同的应用场景中发挥作用。以下是 Redis 提供的几种核心数据结构:

1. String(字符串)

String 是 Redis 最简单的数据类型,可以存储任何类型的字符串,甚至是二进制数据。Redis 的 String 类型支持各种操作,如设置、获取、递增、递减等。

  • 常用命令
  • SET key value:设置一个字符串值。
  • GET key:获取字符串值。
  • INCR key:将字符串值增加 1。
  • APPEND key value:在字符串末尾追加内容。

应用场景:缓存数据,计数器。

2. List(列表)

List 是一个简单的链表数据结构,支持在头部和尾部插入元素。它可以用于实现队列(FIFO)和栈(LIFO)。

  • 常用命令
  • LPUSH key value:将一个或多个值插入到列表头部。
  • RPUSH key value:将一个或多个值插入到列表尾部。
  • LPOP key:移除并返回列表的第一个元素。
  • RPOP key:移除并返回列表的最后一个元素。

应用场景:消息队列,任务队列,最近消息。

3. Set(集合)

Set 是一个无序集合,集合中的每个元素都是唯一的。Redis 提供了多种操作来进行集合的操作,如求并集、交集、差集等。

  • 常用命令
  • SADD key member:向集合添加一个元素。
  • SREM key member:移除集合中的某个元素。
  • SMEMBERS key:获取集合中的所有元素。

应用场景:去重,社交网络中的共同好友,标签系统。

4. Hash(哈希)

Hash 是 Redis 中最常用的键值对集合。它特别适合存储对象(如用户信息),可以通过字段来访问其中的值。

  • 常用命令
  • HSET key field value:设置哈希表中字段的值。
  • HGET key field:获取哈希表中字段的值。
  • HDEL key field:删除哈希表中的字段。

应用场景:存储对象,用户资料,配置信息。

5. Sorted Set(有序集合)

Sorted Set 是 Redis 中的一个带有顺序的集合。每个元素都会关联一个 分数(score),Redis 会根据分数进行排序。与 Set 不同,Sorted Set 中的元素是唯一的,但其顺序是由分数决定的。

  • 常用命令
  • ZADD key score member:将元素添加到有序集合中,并设置分数。
  • ZRANGE key start stop:返回有序集合中指定范围的元素。
  • ZREM key member:移除有序集合中的元素。

应用场景:排行榜,优先级队列,任务调度。

6. Bitmap(位图)

Bitmap 是 Redis 中一种非常节省空间的数据结构,它允许我们在一个位上存储信息,适用于处理大量布尔类型数据的场景。

  • 常用命令
  • SETBIT key offset value:在指定的偏移量处设置位。
  • GETBIT key offset:获取指定偏移量处的位的值。
  • BITCOUNT key:统计位图中值为 1 的位的数量。

应用场景:用户活跃度统计,签到系统,布尔值状态记录。

7. HyperLogLog(超日志)

HyperLogLog 是一种概率性数据结构,用于估算基数(如不同元素的个数)。它能用非常小的内存空间估算大量数据的基数。

  • 常用命令
  • PFADD key element:将元素添加到 HyperLogLog。
  • PFCOUNT key:返回 HyperLogLog 的基数估计值。

应用场景:去重,统计不同用户、IP 的数量等。

8. Geospatial(地理位置)

Redis 通过提供 Geospatial 数据类型,可以存储地理位置的坐标,并进行地理位置相关的查询操作。

  • 常用命令
  • GEOADD key longitude latitude member:添加地理位置坐标。
  • GEODIST key member1 member2:计算两个成员之间的距离。
  • GEORADIUS key longitude latitude radius:根据半径查询范围内的成员。

应用场景:位置服务,打车系统,附近的商家查询。


二、Redis 分布式锁的实现

分布式锁是解决分布式系统中资源竞争问题的一种机制,Redis 提供了非常高效且简单的分布式锁解决方案。常见的实现方法是通过 Redis 的 SETNX 命令(SET if Not Exists)来实现。

1. 基于 SETNX 实现分布式锁

原理:利用 Redis 的 SETNX 命令,它的作用是设置一个键值对,只有当键不存在时才会成功。这样,如果多个客户端并发请求同一个锁,只有第一个获取锁的客户端能够成功设置该键,其他客户端无法设置成功,从而实现了分布式锁。

  • SETNX 锁的实现流程
  1. 客户端尝试通过 SETNX 命令设置一个锁标识符(如 lock:mylock)并指定锁的超时时间(避免死锁)。
  2. 如果设置成功,客户端就获得了锁。
  3. 如果设置失败,表示锁已被其他客户端占用,客户端可以等待或尝试重试。
  4. 客户端在执行完任务后,删除锁标识符,释放锁。

2. 基于 SET 实现分布式锁(Redis 2.6 版本及以上)

Redis 在 2.6 版本引入了 SET 命令的 NXEX 选项,可以更方便地实现分布式锁,并防止死锁。

  • 命令:SET key value NX EX seconds
  • NX:只有当 key 不存在时,才会设置成功。
  • EX:设置键的过期时间,防止锁被永久占用。

实现步骤

  1. 客户端通过 SET key value NX EX seconds 设置锁。如果锁已存在,则 SET 命令返回失败。
  2. 如果获得锁,客户端可以继续执行任务。
  3. 任务完成后,客户端通过 DEL 命令释放锁。
  4. 由于锁具有过期时间,客户端即使崩溃,锁也会被自动释放。

代码实现(基于 SETNX 实现分布式锁)

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <time.h>

#include <hiredis/hiredis.h>

#define LOCK_KEY "mylock"

#define LOCK_TIMEOUT 10 // 锁超时时间,单位秒

// 获取锁

int acquire_lock(redisContext *c) {

   redisReply *reply;

   reply = redisCommand(c, "SET %s %s NX EX %d", LOCK_KEY, "locked", LOCK_TIMEOUT);

   if (reply->type == REDIS_REPLY_STATUS && strcmp(reply->str, "OK") == 0) {

       freeReplyObject(reply);

       return 1; // txc.qq.com/products/767094/blog/2361017成功获得锁

   }

   freeReplyObject(reply);

   return 0; // txc.qq.com/products/767094/blog/2361016锁已被占用

}

// 释放锁

void release_lock(redisContext *c) {

   redisReply *reply = redisCommand(c, "DEL %s", LOCK_KEY);

   freeReplyObject(reply);

}

int main() {

   struct timeval timeout = {1, 500000}; // 1.5秒超时

   redisContext *c = redisConnectWithTimeout("127.0.0.1", 6379, timeout);

   if (c == NULL || c->err) {

       if (c) {

           printf("Connection error: %s\n", c->errstr);

           redisFree(c);

       } else {

           printf("Can't allocate redis context\n");

       }

       return

php

1 KB

© 菜鸟-创作你的创作

1;

}

// 尝试获取锁

if (acquire_lock(c)) {

   printf("Lock acquired! Performing task...\n");

  // 执行任务

   sleep(5); // 模拟执行任务

   release_lock(c); // 释放锁

   printf("Task completed and lock released.\n");

} else {

   printf("Failed to acquire lock.\n");

}

redisFree(c);

return 0;

php

276 Bytes

© 菜鸟-创作你的创作

}

#### **3. RedLock(Redisson)**

**RedLock** 是 Redis 官方提出的一种分布式锁的实现方案,旨在解决多个 Redis 实例间的锁竞争问题。RedLock 通过多个 Redis 实例来保证锁的可靠性,并防止因单点故障而导致的锁失效。

**基本思路**:

1. 向多个 Redis 实例同时请求锁。

2. 如果大多数实例都返回成功,认为锁被成功获取。

3. 如果没有大多数实例返回成功,则回滚已获得的锁。

Redisson 是基于 RedLock 协议实现的分布式锁库,在 Java 和其他语言中都有实现。

---

### **总结**

Redis 提供了多种强大的数据结构来支持高效的数据存储与处理,包括 String、List、Set、Hash、Sorted Set 等,广泛应用于缓存、队列、任务调度等场景。而分布式锁可以有效避免多个进程或机器之间的资源竞争问题,常用的分布式锁实现方案包括 `SETNX`、`SET` 命令以及 RedLock 协议。

通过这些数据结构和分布式锁的实现,我们可以在高并发、大规模分布式系统中保持数据的一致性、可靠性,并有效提高系统性能。

php

514 Bytes

© 菜鸟-创作你的创作

相关文章
|
28天前
|
消息中间件 缓存 NoSQL
Redis各类数据结构详细介绍及其在Go语言Gin框架下实践应用
这只是利用Go语言和Gin框架与Redis交互最基础部分展示;根据具体业务需求可能需要更复杂查询、事务处理或订阅发布功能实现更多高级特性应用场景。
167 86
|
14天前
|
存储 消息中间件 NoSQL
Redis数据结构:别小看这5把“瑞士军刀”,用好了性能飙升!
Redis提供5种基础数据结构及多种高级结构,如String、Hash、List、Set、ZSet,底层通过SDS、跳表等实现高效操作。灵活运用可解决缓存、计数、消息队列、排行榜等问题,结合Bitmap、HyperLogLog、GEO更可应对签到、UV统计、地理位置等场景,是高性能应用的核心利器。
|
28天前
|
存储 缓存 NoSQL
Redis基础命令与数据结构概览
Redis是一个功能强大的键值存储系统,提供了丰富的数据结构以及相应的操作命令来满足现代应用程序对于高速读写和灵活数据处理的需求。通过掌握这些基础命令,开发者能够高效地对Redis进行操作,实现数据存储和管理的高性能方案。
65 12
|
27天前
|
NoSQL Java 调度
分布式锁与分布式锁使用 Redis 和 Spring Boot 进行调度锁(不带 ShedLock)
分布式锁是分布式系统中用于同步多节点访问共享资源的机制,防止并发操作带来的冲突。本文介绍了基于Spring Boot和Redis实现分布式锁的技术方案,涵盖锁的获取与释放、Redis配置、服务调度及多实例运行等内容,通过Docker Compose搭建环境,验证了锁的有效性与互斥特性。
分布式锁与分布式锁使用 Redis 和 Spring Boot 进行调度锁(不带 ShedLock)
|
21天前
|
缓存 NoSQL 关系型数据库
Redis缓存和分布式锁
Redis 是一种高性能的键值存储系统,广泛用于缓存、消息队列和内存数据库。其典型应用包括缓解关系型数据库压力,通过缓存热点数据提高查询效率,支持高并发访问。此外,Redis 还可用于实现分布式锁,解决分布式系统中的资源竞争问题。文章还探讨了缓存的更新策略、缓存穿透与雪崩的解决方案,以及 Redlock 算法等关键技术。
|
27天前
|
存储 消息中间件 NoSQL
【Redis】常用数据结构之List篇:从常用命令到典型使用场景
本文将系统探讨 Redis List 的核心特性、完整命令体系、底层存储实现以及典型实践场景,为读者构建从理论到应用的完整认知框架,助力开发者在实际业务中高效运用这一数据结构解决问题。
|
5月前
|
存储 NoSQL 算法
Redis设计与实现——数据结构与对象
Redis 是一个高性能的键值存储系统,其数据结构设计精妙且高效。主要包括以下几种核心数据结构:SDS、链表、字典、跳跃表、整数集合、压缩列表。此外,Redis 对象通过类型和编码方式动态转换,优化内存使用,并支持引用计数、共享对象和淘汰策略(如 LRU/LFU)。这些特性共同确保 Redis 在性能与灵活性之间的平衡。
|
12月前
|
存储 消息中间件 NoSQL
Redis 数据结构与对象
【10月更文挑战第15天】在实际应用中,需要根据具体的业务需求和数据特点来选择合适的数据结构,并合理地设计数据模型,以充分发挥 Redis 的优势。
231 64
|
存储 NoSQL 算法
「Redis」数据结构与对象
Redis数据结构与对象介绍
125 0
|
NoSQL 算法 Java
Redis进阶 - 数据结构:对象机制详解,一文深入底层分析
我们在前文已经阐述了Redis 5种基础数据类型详解,分别是字符串(string)、列表(list)、哈希(hash)、集合(set)、有序集合(zset),以及5.0版本中Redis Stream结构详解;那么这些基础类型的底层是如何实现的呢?Redis的每种对象其实都由对象结构(redisObject) 与 对应编码的数据结构组合而成, 本文主要介绍对象结构(redisObject) 部分。
Redis进阶 - 数据结构:对象机制详解,一文深入底层分析