分布式中间件-redis相关概念介绍

文章目录

    • 什么是redis?
      • 示意图
      • Redis的主要特点
      • Redis的主要用途
      • Redis的工作原理
      • Redis的持久化与备份
    • redis 6.x新增特性
      • 多线程数据加载
      • 客户端缓存
      • 新的 RESP 3 协议支持
      • ACL(Access Control List)功能
      • `新增数据类型`
      • 性能改进
      • 配置文件的改进
      • 其他改进
    • redis数据类型有哪些?
    • redis 部署模式有哪些?
    • redis常见问题
      • 缓存击穿(Cache Stampede)
      • 缓存雪崩(Cache Avalanche)
      • 缓存穿透(Cache Penetration)
      • 数据一致性问题
      • 内存管理问题
      • 并发竞争问题
      • 连接池的使用
    • 其他概念
      • 布隆过滤器
        • 工作原理
        • 特性
        • 应用场景
        • 注意事项
      • 一致性哈希算法
      • 示意图
        • 虚拟节点(Virtual Nodes)
        • 优点
        • 应用场景
      • 实现注意事项
    • 参考文献

什么是redis?

Redis(Remote Dictionary Server)是一个开源的、基于内存的、使用ANSI C语言编写的Key-Value数据库。它支持多种数据结构,并提供丰富的API,使其成为高性能的缓存、消息队列、实时分析等场景的理想选择。以下是关于Redis的详细介绍:

示意图

redis示意图

Redis的主要特点

  • 内存存储:Redis将数据存储在内存中,因此具有非常高的读取和写入性能。
  • 丰富的数据结构:支持字符串(Strings)、哈希(Hashes)、列表(Lists)、集合(Sets)、有序集合(Sorted Sets)等数据结构。
  • 持久化机制:支持两种持久化方式:RDB(Redis Database)和AOF(Append Only File)。
  • 分布式支持:通过集群方式支持分布式部署,提供分片、复制等功能。

Redis的主要用途

  • 缓存:Redis非常适合作为缓存系统,可以大幅提高系统的读写性能。
  • 消息队列:支持发布订阅机制,用于解耦系统的不同组件。
  • 分布式锁:提供原子性的操作,确保在分布式环境下对共享资源的互斥访问。
  • 会话存储:用于存储用户会话信息,提高网站的性能和扩展性。

Redis的工作原理

Redis采用单线程模型处理网络IO和键值对读写操作,避免了多线程带来的上下文切换和竞争条件问题。它使用异步I/O和事件驱动模型来提高并发读写的能力。

Redis的持久化与备份

Redis支持两种主要的持久化方式:RDBAOF。RDB通过生成数据快照文件存储到磁盘中,而AOF记录每一条收到的命令,确保数据的可靠性。
通过上述信息,我们可以看出Redis是一个功能强大、性能高、易用的数据存储和缓存解决方案,适用于多种应用场景。

redis 6.x新增特性

Redis 6.x 相对于之前的版本,引入了多项改进和新特性,增强了其性能、安全性以及功能性。以下是 Redis 6.x 中的一些重要新特性:

多线程数据加载

Redis 6.x 引入了一个实验性的多线程数据加载功能。这意味着在 Redis 启动时,可以从磁盘加载数据到内存的过程中利用多线程来加速这一过程。这对于大型数据库的启动时间有显著的改善作用。

客户端缓存

Redis 6.x 增加了客户端缓存的功能,允许客户端在本地缓存一些常用的数据。这样可以减少客户端与服务器之间的往返通信次数,从而减轻服务器的负载,提高访问速度和效率。

新的 RESP 3 协议支持

Redis 6.x 支持了新的 RESP 3 协议,该协议提供了更丰富的数据类型和更好的性能。RESP 3 协议相比之前的 RESP 2 协议,不仅增加了更多的数据类型和命令支持,还优化了数据传输的效率,提高了 Redis 的性能。

ACL(Access Control List)功能

Redis 6.x 引入了 ACL 功能,这是一项重要的安全特性。通过 ACL,管理员可以更精细地控制不同用户的权限,包括可以执行的命令和可以访问的键。这项功能增强了 Redis 的安全性,允许更复杂的访问控制策略。

新增数据类型

  • Bitmaps:虽然不是 Redis 6.x 新增的数据类型,但 Redis 6.x 对 Bitmaps 的支持更加完善,提供了更多针对 Bitmaps 的操作命令,使得在处理位图时更加方便。

性能改进

Redis 6.x 包含了一系列的性能改进,包括对内部数据结构的优化以及对命令处理流程的改进,旨在提高 Redis 的整体性能。

配置文件的改进

Redis 6.x 对配置文件进行了改进,使其更加易于理解和维护。例如,通过将一些默认配置项移到单独的配置文件中,简化了主配置文件的内容。

其他改进

除了上述特性外,Redis 6.x 还包含了一些其他改进,比如对 Lua 脚本的支持进行了增强,提供了更多的内置函数;对监控命令进行了改进,使得监控 Redis 实例的行为变得更加直观;以及其他一些小的特性和错误修复。

总的来说,Redis 6.x 的这些新特性使得 Redis 更加强大、灵活,并且更加适应现代分布式系统的需求。这些改进不仅提升了 Redis 的性能,还增强了其安全性和易用性。

redis数据类型有哪些?

Redis的数据类型主要包括以下几种:

  1. 字符串(String)

    • 最基本的数据类型,可以包含任何数据,如数字、字符串、二进制数据等。
    • 支持的操作包括设置值、获取值、追加、自增/自减等。
    • 应用场景:缓存、计数器、配置信息等。
  2. 哈希(Hash)

    • 哈希是一个键值对的集合,其中键是字符串,值也是字符串。哈希适合存储对象,并且可以像数据库中update一个属性一样只修改某一项属性值(Memcached中需要取出整个字符串反序列化成对象修改完再序列化存回去)。
    • 常用命令:HSET, HGET, HGETALL, HDEL, HEXISTS, HINCRBY, HKEYS, HLEN, HMGET, HMSET, HVALS等。
  3. 列表(List)

    • 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到头部(左边)或者尾部(右边)。
    • 常用命令:LPUSH, RPUSH, LPOP, RPOP, LINDEX, LLEN, LRANGE, LINSERT, LREM, LSET等。
  4. 集合(Set)

    • 集合是字符串类型的无序集合。它是通过哈希表实现的,可以做到添加,删除,查找的时间复杂度都是O(1)。
    • 常用命令:SADD, SREM, SMEMBERS, SISMEMBER, SDIFF, SINTER, SUNION, SCARD, SRANDMEMBER等。
  5. 有序集合(Sorted Set)

    • 有序集合和集合相似,但每个字符串元素都会关联一个浮点数类型的分数。元素的分数用来排序,如果两个成员有相同的分数,那么他们的排名按照字典序计算。
    • 常用命令:ZADD, ZREM, ZRANGE, ZREVRANGE, ZINCRBY, ZRANK, ZREVRANK, ZCARD, ZSCORE, ZCOUNT, ZUNIONSTORE, ZINTERSTORE等。
  6. 地理空间(Geospatial)

    • Redis从3.2版本开始增加了对地理空间位置的支持,允许存储地理坐标并执行地理位置查询。
    • 常用命令:GEOADD, GEODIST, GEOHASH, GEOPOS, GEORADIUS, GEORADIUSBYMEMBER等。
  7. HyperLogLog

    • HyperLogLog是一种用于估计集合基数的数据结构,它提供了非常高效的基数估计功能,但会牺牲一定的准确性。
    • 常用命令:PFADD, PFCOUNT, PFMERGE等。
  8. Bitmaps

    • 虽然Redis没有专门的Bitmaps数据类型,但是可以通过使用字符串类型来模拟位图操作。Bitmaps非常适合于处理大量的位级数据,如用户在线状态、日活跃用户统计等。
    • 常用命令:SETBIT, GETBIT, BITCOUNT, BITOP等。

这些复杂数据类型使得Redis能够处理更加丰富的数据操作需求,适用于各种复杂的应用场景。

redis 部署模式有哪些?

  • 单机部署
    单机部署是最简单的部署方式,适合开发测试环境或者负载较低的应用场景。在单机模式下,所有数据都存储在一个节点上,这种方式易于管理和配置。

  • 主从复制(Master-Slave Replication)
    主从复制是提高 Redis 可用性和扩展性的常用方法。在这种架构中,一个或多个从节点(slave)会实时地从主节点(master)复制数据。当主节点出现故障时,可以将其中一个从节点提升为新的主节点,以减少服务中断的时间。此外,从节点也可以用来处理只读请求,以此来分散主节点的压力。

  • 哨兵机制(Sentinel)
    哨兵是 Redis 提供的一种高可用性解决方案。哨兵(sentinel)是一组运行在独立进程中的程序,它们负责监控主从集群中的各个节点状态,在主节点发生故障时自动完成故障转移,即从从节点中选出一个新的主节点,并重新调整客户端的连接。

  • 集群模式(Cluster)
    Redis 集群允许用户水平扩展 Redis 的内存和吞吐量。集群通过分区数据到不同的节点上来实现数据的分布存储,同时支持数据的自动迁移重新平衡。每个节点只负责数据的一个子集,且集群本身支持一定数量的节点故障。需要注意的是,集群模式下的数据操作是分布式的,因此某些命令可能不可用或者行为会有所不同。

redis常见问题

缓存击穿(Cache Stampede)

当缓存中某个热点数据失效的一瞬间,大量的并发请求直接打到数据库上,导致数据库压力过大。解决方法通常是使用互斥锁(Mutex)或者设置一个过期时间很短的临时缓存项来避免这种情况。

缓存雪崩(Cache Avalanche)

如果大量缓存数据在同一时间失效,会导致后端数据库突然承受大量请求,从而引发系统崩溃。为了避免缓存雪崩,可以采取以下措施:

  • 使缓存的过期时间分布开,而不是集中在同一时间段;
  • 使用限流策略,比如漏桶算法或令牌桶算法;
  • 设置热点数据永不过期;
  • 采用双删策略,即数据先删除,然后延迟一段时间后再真正删除。

缓存穿透(Cache Penetration)

缓存穿透指的是查询一个不存在的数据,如果没有处理好,这个查询就会直接到达数据库,如果没有有效拦截机制的话,如果存在恶意攻击或者代码 bug,就可能对数据库造成过大压力。可以通过以下方式解决:

  • 对于不存在的数据也进行缓存,但设置较短的过期时间;
  • 使用布隆过滤器(Bloom Filter)提前过滤掉不存在的数据;
  • 在应用层增加校验,防止恶意攻击。

数据一致性问题

当缓存和数据库中的数据不一致时,可能导致业务逻辑错误。为了保证数据一致性,可以采用以下方法:

  • 双写一致性,即更新缓存和数据库时,保证两者的顺序一致;
  • 缓存击穿和雪崩预防机制;
  • 使用消息队列来异步更新缓存;
  • 利用分布式事务或最终一致性来保证数据一致性。

内存管理问题

Redis 是内存数据库,所以内存管理非常重要。常见的内存管理问题有:

  • 内存溢出:当 Redis 达到最大内存限制时,需要合理配置 Redis 的内存策略(如 LRU 或 LFU),并定期检查和清理不再使用的缓存数据;
  • 内存碎片:长时间运行后可能会产生内存碎片,需要定期进行内存优化或重启 Redis 实例;
  • 内存占用过高:监控内存使用情况,合理设置 key 的过期时间(TTL),定期清理不必要的数据。

并发竞争问题

当多个并发请求试图修改同一个缓存条目时,可能会出现并发竞争的问题。可以使用 Redis 的原子操作(如 INCRDECR)、Lua 脚本或者分布式锁来解决这个问题。

连接池的使用

在高并发场景下,频繁创建和销毁 Redis 连接会造成不必要的性能损耗。使用连接池可以复用连接,减少系统的整体开销。
解决上述问题时,需要根据具体的业务场景和技术栈来综合考虑,确保系统稳定可靠的同时也要兼顾性能和成本。

其他概念

布隆过滤器

布隆过滤器(Bloom Filter)是一种空间效率极高的概率型数据结构,它用于判断一个元素是否在一个集合中。布隆过滤器的特点是可以非常快速地检测一个元素是否存在于集合中,但是它的判断不是绝对准确的——可能存在一定的误报率(false positive rate),但是不会有误删(false negative),也就是说,如果布隆过滤器说某个元素不在集合中,那它确实不在;但如果它说某个元素在集合中,那这个判断可能是错误的。

工作原理

布隆过滤器由一个很长的二进制向量(bit array)和一系列随机映射函数(hash functions)组成。当一个元素被加入到过滤器时,它会被 k 个不同的哈希函数处理,每个哈希函数都会给出一个位置,这个位置上的比特位将被设置为 1。当需要查询一个元素是否存在于集合中时,同样的 k 个哈希函数会被应用到该元素上,如果所有的比特位都是 1,那么这个元素“可能”存在于集合中;如果其中任何一个比特位是 0,那么可以确定该元素肯定不在集合中。

特性
  1. 空间效率:相比其他数据结构,布隆过滤器可以使用更少的空间来表示一个集合。
  2. 插入和查询速度快:因为布隆过滤器的主要操作是位操作,所以它的速度非常快。
  3. 误报率:布隆过滤器允许有一定概率的误报,但不会有误删的情况。误报率受滤波器大小、哈希函数的数量以及插入的元素数量的影响。
应用场景

布隆过滤器适用于那些对误报有一定容忍度的应用场景,常见的应用场景包括:

  • 网络爬虫:用来判断网页是否已经被抓取。
  • 数据库系统:在数据库索引中,可以用来判断某条记录是否存在,以减少磁盘 I/O 操作。
  • 缓存系统:如 Redis 中的布隆过滤器插件,用来判断一个键是否存在,以减少不必要的缓存查找。
  • 垃圾邮件过滤:用来标记已知的垃圾邮件地址。
注意事项

使用布隆过滤器时需要注意以下几点:

  • 一旦某个元素被加入到布隆过滤器中,就不能再将其删除,除非重建整个过滤器。
  • 误报率随着加入元素数量的增加而增加,因此需要合理估计最大元素数量和分配足够的空间来保持较低的误报率。
  • 选择合适的哈希函数数目和滤波器大小对于控制误报率至关重要。
    总之,布隆过滤器是一个非常有用的工具,尤其是在需要高效存储和查询大量数据的情况下。但是,在使用时也需要考虑到它的局限性和适用场景。

一致性哈希算法

一致性哈希算法(Consistent Hashing)是一种特殊的哈希算法,设计目的是为了在分布式环境中解决数据分片(sharding)和负载均衡的问题。一致性哈希能够有效地应对节点动态变化的情况,比如节点的添加(scale up)或移除(scale down),并且能够尽量减少数据迁移的成本。这使得一致性哈希非常适合用于构建可伸缩的分布式系统,如缓存系统、负载均衡器、分布式存储等。

示意图

一致性哈希算法#### 工作原理
一致性哈希的基本思想是在一个虚拟的圆环上放置数据节点,并将数据项通过哈希运算映射到这个圆环上。每个节点也被哈希到圆环上的某个位置。数据项存储在它映射到的位置顺时针方向上最近的那个节点上。

  • 具体步骤如下:

    1. 计算节点的哈希值:将每个节点的名字(或其他标识符)通过哈希函数转换成一个整数,然后把这个整数映射到一个固定大小的圆环上。
    2. 计算数据的哈希值:同样地,将每个数据项(key)通过相同的哈希函数转换成一个整数,并映射到圆环上。
    3. 定位数据所在节点:对于每一个数据项,找到它在圆环上顺时针方向上的第一个节点,这个节点就是数据应该存储的地方。
虚拟节点(Virtual Nodes)

为了进一步提高负载均衡的效果,一致性哈希引入了虚拟节点的概念。每个物理节点可以在圆环上占据多个位置,这些位置称为虚拟节点。这样做可以增加哈希环上的节点数量,从而更均匀地分布数据。

优点
  1. 数据迁移最小化:当系统中添加或移除节点时,只有少量的数据需要被重新分布,大多数数据可以保持不变。
  2. 可预测性:即使在节点数量发生变化时,一致性哈希算法也能提供一种相对稳定的数据映射方式。
  3. 负载均衡:通过虚拟节点可以实现更好的负载均衡。
应用场景

一致性哈希算法广泛应用于各种分布式系统中,包括但不限于:

  • 分布式缓存:如 Amazon Dynamo 和 Memcached 都采用了类似的技术。
  • 负载均衡:用于分配请求到不同的服务器。
  • 分布式文件系统:如 Google 的 Bigtable 和 Apache 的 Cassandra。

实现注意事项

虽然一致性哈希具有很多优点,但在实际应用中也需要考虑一些问题,例如:

  • 当节点较少时,哈希环上的分布可能会不均匀,导致某些节点负载过重。
  • 节点的添加或移除仍然会对部分数据造成影响,需要权衡利弊。
  • 选择合适的哈希函数以及合理的虚拟节点数量也是实现过程中需要注意的问题。
    一致性哈希提供了一种优雅的方式来处理分布式系统中的数据分布问题,特别是在需要动态调整节点数量的情况下,能够有效地减少数据迁移带来的开销。

参考文献

  • 如果英文不好,可以点击这里,获得更加详细的说明信息。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/54315.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

02 基于STM32的按键控制继电器驱动电机

本专栏所有源资料都免费获取,没有任何隐形消费。 注意事项:STM32仿真会存在各种各样BUG,且尽量按照同样仿真版本使用。本专栏所有的仿真都采用PROTEUS8.15。 本文已经配置好STM32F103C8T6系列,在PROTUES仿真里,32单片…

Doker学习笔记--黑马

介绍:快速构建、运行、管理应用的工具 在不同的服务器上部署多个应用,但是往往不同应用之间会有冲突,因为它们所依赖的环境,函数库,配置都不一样,此时docker在运行时形成了一个隔离环境(容器&am…

【C++篇】C++类与对象深度解析(三):类的默认成员函数详解

文章目录 【C篇】C类与对象深度解析(三)前言4. 运算符重载基本概念4.1 运算符重载的基本概念4.2 重载运算符的规则4.3 成员函数重载运算符4.4 运算符重载的优先级与结合性4.5 运算符重载中的限制与特殊情况4.5.1 不能创建新的操作符4.5.2 无法重载的运算…

QT 带箭头的控件QPolygon

由于对当前项目需要绘制一个箭头控件&#xff0c;所以使用了QPainter和QPolygon来进行绘制&#xff0c;原理就是计算填充&#xff0c;下面贴出代码和效果图 这里简单介绍下QPolygon QPolygon是继承自 QVector<QPoint>那么可以很简单的理解为&#xff0c;他就是一个点的…

Leetcode面试经典150题-138.随机链表的复制

题目比较简单&#xff0c;重点是理解思想&#xff0c;random不管&#xff0c;copy一定要放在next 而且里面的遍历过程不能省略 解法都在代码里&#xff0c;不懂就留言或者私信 /* // Definition for a Node. class Node {int val;Node next;Node random;public Node(int val…

springboot-创建连接池

操作数据库 代码开发步骤&#xff1a; pom.xml文件配置依赖properties文件配置连接数据库信息&#xff08;连接池用的是HikariDataSource&#xff09;数据库连接池开发 configurationproperties和value注解从properties文件中取值bean方法开发 service层代码操作数据库 步骤&am…

数据分析师的得力助手:vividime Desktop让数据分析变得更简单高效

在数据驱动决策的今天&#xff0c;数据分析已成为企业不可或缺的一部分。面对海量的数据和复杂的业务需求&#xff0c;一款高效、易用的报表工具显得尤为重要。本文将深入解析为何一款优秀的报表工具对于数据分析至关重要&#xff0c;并以市场上备受好评的免费BI工具——vividi…

集成学习详细介绍

以下内容整理于&#xff1a; 斯图尔特.罗素, 人工智能.现代方法 第四版(张博雅等译)机器学习_温州大学_中国大学MOOC(慕课)XGBoost原理介绍------个人理解版_xgboost原理介绍 个人理解-CSDN博客 集成学习(ensemble)&#xff1a;选择一个由一系列假设h1, h2, …, hn构成的集合…

YOLOv10改进系列,YOLOv10损失函数更换为Powerful-IoU(2024年最新IOU),助力高效涨点

改进前训练结果: 改进后的结果: 摘要 边界框回归(BBR)是目标检测中的核心任务之一,BBR损失函数显著影响其性能。然而,观察到现有基于IoU的损失函数存在不合理的惩罚因子,导致回归过程中锚框扩展,并显著减缓收敛速度。为了解决这个问题,深入分析了锚框扩展的原因。针…

【网络】详解HTTP协议的CGI机制和CGI进程

目录 引言 CGI机制模型 伪代码示例 个人主页&#xff1a;东洛的克莱斯韦克-CSDN博客 引言 CGI机制是HTTP协议提供的偏底层的一套机制&#xff0c;也是非常重要的机制——它让大量的业务进程和HTPP协议解耦。而CGI进程是业务层的&#xff0c;用来处理各种数据&#xff0c;比…

OpenCV结构分析与形状描述符(24)检测两个旋转矩形之间是否相交的一个函数rotatedRectangleIntersection()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 测两个旋转矩形之间是否存在交集。 如果存在交集&#xff0c;则还返回交集区域的顶点。 下面是一些交集配置的例子。斜线图案表示交集区域&#…

孙怡带你深度学习(2)--PyTorch框架认识

文章目录 PyTorch框架认识1. Tensor张量定义与特性创建方式 2. 下载数据集下载测试展现下载内容 3. 创建DataLoader&#xff08;数据加载器&#xff09;4. 选择处理器5. 神经网络模型构建模型 6. 训练数据训练集数据测试集数据 7. 提高模型学习率 总结 PyTorch框架认识 PyTorc…

Vue2电商平台项目 (三) Search模块、面包屑(页面自己跳自己)、排序、分页器!

文章目录 一、Search模块1、Search模块的api2、Vuex保存数据3、组件获取vuex数据并渲染(1)、分析请求数据的数据结构(2)、getters简化数据、渲染页面 4、Search模块根据不同的参数获取数据(1)、 派发actions的操作封装为函数(2)、设置带给服务器的参数(3)、Object.assign整理参…

如何通过OceanBase的多级弹性扩缩容能力应对业务洪峰

每周四晚上的10点&#xff0c;都有近百万的年轻用户进入泡泡玛特的抽盒机小程序&#xff0c;共同参与到抢抽盲盒新品的活动中。瞬间的并发流量激增对抽盒机小程序的系统构成了巨大的挑战&#xff0c;同时也对其数据库的扩容能力也提出了更高的要求。 但泡泡玛特的工程师们一点…

Redhat 7,8,9系(复刻系列) 一键部署Oracle19c rpm

Oracle19c前言 Oracle 19c 是甲骨文公司推出的一款企业级关系数据库管理系统,它带来了许多新的功能和改进,使得数据库管理更加高效、安全和可靠。以下是关于 Oracle 19c 的详细介绍: 主要新特性 多租户架构:支持多租户架构,允许多个独立的数据库实例在同一个物理服务器上…

JDBC API详解一

DriverManager 驱动管理类&#xff0c;作用&#xff1a;1&#xff0c;注册驱动&#xff1b;2&#xff0c;获取数据库连接 1&#xff0c;注册驱动 Class.forName("com.mysql.cj.jdbc.Driver"); 查看Driver类源码 static{try{DriverManager.registerDriver(newDrive…

java十进制码、六进制码和字符码的转换

一、字符转换为ASCII码&#xff1a; int i(int)1; 二、ASCII码转换为字符&#xff1a; char ch (char)40; 三、十六进制码转换为字符&#xff1a; char charValue (char)\u0040; package week3;public class check_point4_8 {public static void main(String[] args) {S…

谷歌怎么像图里这样多开贴吧号??

&#x1f3c6;本文收录于《CSDN问答解惑-专业版》专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收…

数据库三范式和ER图详解

数据库设计三范式 第一范式&#xff1a;要求数据表中的字段&#xff08;列&#xff09;不可再分(原子性) 第二范式&#xff1a;不存在非关键字段(非主键)对关键字段(主键)的部分依赖 ps: 主要是针对联合主键,非主键不能只依赖联合主键的一部分 联合主键,即多个列组成的主键 第…

Python | Leetcode Python题解之第414题第三大的数

题目&#xff1a; 题解&#xff1a; class Solution:def thirdMax(self, nums: List[int]) -> int:a, b, c None, None, Nonefor num in nums:if a is None or num > a:a, b, c num, a, belif a > num and (b is None or num > b):b, c num, belif b is not No…