简单认识redis - 7redis实现分布式

1.为什么要实现分布式

一、提升性能

  1. 资源利用最大化
    • 在单台机器上,硬件资源(如 CPU、内存、磁盘 I/O 等)是有限的。随着业务的增长,单个服务器可能无法满足大量并发请求的处理需求。通过分布式系统,可以将负载分散到多个节点上,每个节点处理一部分请求,从而充分利用各个节点的资源,提高整体的处理能力。
    • 例如,一个大型电商网站在促销活动期间会面临海量的用户访问请求。如果仅依靠单台服务器,可能会因为 CPU 满载或内存不足导致响应缓慢甚至系统崩溃。而分布式系统可以将用户请求分配到多个服务器上同时处理,提高响应速度。
  2. 并行处理
    • 分布式系统允许对任务进行并行处理。对于一些复杂的计算任务,如大数据分析、机器学习中的模型训练等,可以将任务分解成多个子任务,并在不同的节点上同时执行这些子任务。
    • 例如,在处理海量数据的排序任务时,可以将数据分成多个部分,每个部分在一个独立的节点上进行排序,最后再将各个部分的排序结果合并起来,这样可以大大缩短任务的处理时间。

二、提高可用性和容错性

  1. 避免单点故障
    • 在单服务器架构中,如果服务器出现故障(如硬件故障、软件故障、网络故障等),整个系统将无法正常运行。而分布式系统由多个节点组成,即使某个节点出现故障,其他节点仍然可以继续提供服务,系统整体不会完全瘫痪。
    • 例如,一个分布式文件存储系统中,数据被复制到多个节点上。如果其中一个存储节点发生故障,用户仍然可以从其他副本节点获取数据,从而保证了系统的可用性。
  2. 容错性增强
    • 分布式系统可以通过冗余备份和故障恢复机制来提高容错能力。可以在多个节点上保存相同的数据副本,当某个节点的数据损坏或丢失时,可以从其他副本节点恢复数据。
    • 例如,在一些分布式数据库系统中,采用主从复制的方式,主节点负责数据的写入操作,从节点复制主节点的数据并提供读操作。当主节点出现故障时,可以迅速将从节点提升为新的主节点,继续提供服务并恢复数据。

三、满足大规模数据存储和管理需求

  1. 存储容量扩展
    • 随着业务的发展,数据量会不断增长,单台服务器的存储容量可能无法满足需求。分布式系统可以通过添加更多的存储节点来扩展存储容量,几乎没有理论上的存储上限。
    • 例如,云存储服务提供商(如 Amazon S3、Google Cloud Storage 等)采用分布式存储架构,可以存储海量的用户数据,通过不断增加存储节点来满足用户日益增长的存储需求。
  2. 数据分布与管理
    • 对于大规模数据,分布式系统可以采用合适的数据分布策略(如数据分片等)将数据合理地分布在不同的节点上,便于数据的管理、查询和更新操作。
    • 例如,在一个全球范围的社交网络应用中,用户数据可以根据地域或用户 ID 等规则分布在不同的服务器上,这样既方便了数据的就近访问,也提高了数据管理的效率。

二. Redis 实现分布式的几种常见方式

一、分布式锁

  1. 原理

    • 在分布式系统中,不同进程可能需要对共享资源进行互斥访问。Redis 的 SETNX(SET if Not eXists)命令可以用于实现分布式锁。当一个进程想要获取锁时,它尝试使用 SETNX 命令设置一个特定的键值对(例如,键为 "lock_key",值可以是进程标识或随机字符串)。如果 SETNX 命令返回 1,表示锁获取成功,因为键不存在;如果返回 0,表示锁已经被其他进程获取。
    • 为了防止死锁,获取锁的进程还需要设置一个过期时间(可以使用 EXPIRE 命令)。这样,即使进程在持有锁期间崩溃,锁也会在过期后自动释放。
  2. 示例代码(使用 Python 和 Redis - Python 客户端 redis - py)

    复制代码
    import redis
    import time
    
    def acquire_lock(conn, lock_name, acquire_timeout = 10):
        identifier = str(uuid.uuid4())
        end = time.time() + acquire_timeout
        while time.time() < end:
            if conn.setnx(lock_name, identifier):
                conn.expire(lock_name, 10)
                return identifier
            elif not conn.ttl(lock_name):
                conn.expire(lock_name, 10)
            time.sleep(0.001)
        return False
    
    def release_lock(conn, lock_name, identifier):
        pipe = conn.pipeline(True)
        while True:
            try:
                pipe.watch(lock_name)
                if pipe.get(lock_name) == identifier:
                    pipe.multi()
                    pipe.delete(lock_name)
                    pipe.execute()
                    return True
                pipe.unwatch()
                break
            except redis.exceptions.WatchError:
                pass
        return False
    
    
    r = redis.Redis(host='localhost', port = 6379, db = 0)
    lock_name = "my_lock"
    identifier = acquire_lock(r, lock_name)
    if identifier:
        # 执行业务逻辑
        print("获取锁成功,执行业务逻辑")
        release_lock(r, lock_name, identifier)
    else:
        print("获取锁失败")

二、分布式计数器

  1. 原理

    • Redis 的 INCR(INCRement)命令可以用于实现分布式计数器。多个进程可以安全地对同一个 Redis 键执行 INCR 操作,Redis 会原子性地增加键的值。例如,可以用它来统计分布式系统中的某个事件发生的次数,如网站的访问次数、消息的发送次数等。
  2. 示例代码(继续使用 Python 和 redis - py)

    复制代码
    import redis
    
    r = redis.Redis(host='localhost', port = 6379, db = 0)
    counter_key = "visit_count"
    r.incr(counter_key)
    count = r.get(counter_key)
    print(f"当前访问次数: {count.decode('utf - 8')}")

三、数据分片(Sharding)

  1. 原理
    • 当数据量过大时,将数据分布到多个 Redis 实例(节点)上可以提高存储能力和性能。有多种数据分片方法,例如范围分片、哈希分片等。
    • 哈希分片是比较常用的一种。通过对数据的键进行哈希计算,然后根据哈希结果将数据分配到不同的 Redis 节点。例如,计算键的 CRC16 或 CRC32 哈希值,然后将哈希值对节点数量取模,确定数据应该存储到哪个节点。
  2. 示例实现(概念性)
    • 假设我们有 3 个 Redis 节点,节点 1(IP: 192.168.1.101)、节点 2(IP: 192.168.1.102)和节点 3(IP: 192.168.1.103)。

    • 对于要存储的键 "user:123",首先计算其哈希值(假设使用 CRC16),得到哈希值为 12345。然后 12345 % 3 = 0,所以数据应该存储到节点 1。

    • 在实际应用中,需要构建一个中间层来处理数据分片逻辑,使得应用程序不需要关心数据具体存储在哪个节点,这个中间层负责根据分片规则将操作转发到正确的 Redis 节点。

四、Redis Cluster(集群模式)

  1. 原理
    • Redis Cluster 是 Redis 官方提供的分布式解决方案。它将数据自动分片到多个节点上,并且提供了一定的高可用性。
    • Redis Cluster 使用哈希槽(Hash Slot)来进行数据分片,共有 16384 个哈希槽。每个节点负责一部分哈希槽。当客户端想要操作某个键时,通过对键进行 CRC16 哈希计算,然后对 16384 取模,得到哈希槽编号,再根据哈希槽编号找到负责该槽的节点进行操作。
    • 它还提供了主从复制功能,每个主节点可以有一个或多个从节点。当主节点故障时,从节点可以被提升为新的主节点,保证了系统的可用性。
  2. 部署和使用
    • 部署 Redis Cluster 通常需要配置多个 Redis 节点,指定每个节点的角色(主节点或从节点)、IP 地址、端口等信息。

    • 在应用程序中,使用支持 Redis Cluster 的客户端(如 redis - py - cluster 等)来与集群进行交互。客户端会自动根据键计算哈希槽,并将操作发送到正确的节点。例如:

      from rediscluster import RedisCluster

      startup_nodes = [{"host": "192.168.1.101", "port": 7000},
      {"host": "192.168.1.102", "port": 7000},
      {"host": "192.168.1.103", "port": 7000}]
      rc = RedisCluster(startup_nodes = startup_nodes, decode_responses=True)

      rc.set('key1', 'value1')
      value = rc.get('key1')
      print(value)

相关推荐
liangsheng_g5 分钟前
Spring事务传播行为分派与挂起恢复源码实战
数据库·sql·spring
蓝速科技19 分钟前
信创终端 POC 测试实战与选型避坑指南丨蓝速科技
运维·数据库·人工智能·科技·自然语言处理
风哥2号34 分钟前
数据库教程FGMT29‑Linux平台MySQL5.7安装配置与管理入门
数据库
九皇叔叔35 分钟前
从本地事务到分布式事务
java·分布式·分布式事务·cap·base
杨云龙UP1 小时前
MySQL Host is blocked because of many connection errors 导致 JDBC 连接失败排查与解决
linux·运维·网络·数据库·sql·mysql·登录失败
这个DBA有点耶3 小时前
数据库数据同步解决方案怎么选?6款主流工具横向对比与信创选型指南
数据库·架构·dba
刃神太酷啦3 小时前
Redis 核心进阶:哨兵、集群、缓存问题与分布式锁详解----《Hello Redis!》(6)
linux·c语言·数据库·c++·redis·分布式·缓存
小雷信息医学3 小时前
不会写复杂代码也能发 SCI?手把手教你用 InSpireR 交互系统一键提取、合并与导出临床科研宽表【第三章】
数据库
旺仔不是程序员3 小时前
复合索引最左前缀原则:PostgreSQL 的 WHERE 为什么必须命中第一列
数据库·后端·sql
旺仔不是程序员3 小时前
字段类型不一致:PostgreSQL 报错与索引失效的第一元凶
数据库·后端·sql