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

devtools/2024/10/17 16:20:40/

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 redisimport timedef acquire_lock(conn, lock_name, acquire_timeout = 10):identifier = str(uuid.uuid4())end = time.time() + acquire_timeoutwhile time.time() < end:if conn.setnx(lock_name, identifier):conn.expire(lock_name, 10)return identifierelif not conn.ttl(lock_name):conn.expire(lock_name, 10)time.sleep(0.001)return Falsedef 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 Truepipe.unwatch()breakexcept redis.exceptions.WatchError:passreturn Falser = 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 redisr = 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 RedisClusterstartup_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)

http://www.ppmy.cn/devtools/126503.html

相关文章

RelationGraph实现工单进度图——js技能提升

直接上图&#xff1a; 从上图中可以看到整个工单的进度是从【开始】指向【PCB判责】【完善客诉】【PCBA列表】&#xff0c;同时【完善客诉】又可以同时指向【PCB判责】【PCBA列表】&#xff0c;后续各自指向自己的进度。 直接上代码&#xff1a; 1.安装 1.1 Npm 方式 npm …

MySQL-08.DDL-表结构操作-创建-案例

一.MySQL创建表的方式 1.首先根据需求文档定义出原型字段&#xff0c;即从需求文档中可以直接设计出来的字段 2.再在原型字段的基础上加上一些基础字段&#xff0c;构成整个表结构的设计 我们采用基于图形化界面的方式来创建表结构 二.案例 原型字段 各字段设计如下&…

Python基础07_推导式函数

目录 一、推导式 1、列表推导式 2、字典推导式 3、集合推导式 4、元组推导式 二、函数 1、定义函数 1.1 def语句 1.2 函数的调用 1.3 return语句 2、函数参数 3、返回值 4、匿名函数 5、变量作用域 6、函数的内存分配 7、函数自调用&#xff08;递归&#xff0…

【C++贪心】2086. 喂食仓鼠的最小食物桶数|1622

本文涉及知识点 C贪心 LeetCode2086. 喂食仓鼠的最小食物桶数 给你一个下标从 0 开始的字符串 hamsters &#xff0c;其中 hamsters[i] 要么是&#xff1a; ‘H’ 表示有一个仓鼠在下标 i &#xff0c;或者’.’ 表示下标 i 是空的。 你将要在空的位置上添加一定数量的食物桶…

基于Spring Boot的大创项目高效管理系统

1系统概述 1.1 研究背景 随着计算机技术的发展以及计算机网络的逐渐普及&#xff0c;互联网成为人们查找信息的重要场所&#xff0c;二十一世纪是信息的时代&#xff0c;所以信息的管理显得特别重要。因此&#xff0c;使用计算机来管理大创管理系统的相关信息成为必然。开发合适…

性能工具之JMeter 通过Java API生成 BeanShell PreProcessor 脚本

文章目录 一、前言二、实现代码三、代码示例四、最后 一、前言 对于上一篇文章&#xff08;性能工具之 HAR 格式化转换JMeter JMX 脚本文件&#xff09;还是有点问题。大家在使用的情况需要注意。 如果多个接口相同 path 路径且不同参数进行查询如&#xff1a; 上面接口如果…

【linux009】文件操作命令篇 - touch 命令

文章目录 touch 命令1、基本用法2、常见选项3、举例4、注意事项 touch 命令 touch 是 Linux 系统中的一个常用命令&#xff0c;用于创建空文件或更新已有文件的时间戳。它既可以用来快速生成新文件&#xff0c;也可以用来修改文件的访问时间&#xff08;access time, atime&am…

【JVM】一文详解类加载器

文章目录 类加载器的概述类加载器的分类启动类加载器(Bootstrap ClassLoader )扩展类型加载器(ExClassLoader)系统类加载器(Application ClassLoader )总结 双亲委派机制概念双亲委派机制的优势 ClassLoaderfindClassdefineClassloadClass&#xff0c;findClass&#xff0c;def…