”工欲善其事,必先利其器。“—孔子《论语.录灵公》
首页 > 编程 > 了解 UUID:初级开发人员后端工程师指南

了解 UUID:初级开发人员后端工程师指南

发布于2024-11-08
浏览:710

Understanding UUIDs: A Backend Engineer’s Guide for Junior Developers

介绍

作为后端工程师,我们经常负责构建可以扩展和处理大量资源、用户和实体的系统,每个资源、用户和实体都需要唯一的标识。在许多情况下,使用顺序 ID(例如 1、2、3)似乎是一个简单的解决方案,但随着应用程序在分布式系统中增长和扩展,这很快就会成为问题。这就是 UUID(通用唯一标识符)发挥作用的地方。

在这篇博文中,我们将探讨:

  • UUID 是什么
  • UUID 的实际用例
  • 如何在Python中实现UUID
  • 忽略 UUID 的风险
  • 使用 UUID 时的常见错误
  • 使用 UUID 的最佳实践

什么是UUID?

UUID(通用唯一标识符)是一个 128 位数字,用于唯一标识计算机系统中的信息。它被设计为全球唯一,这意味着在不同系统中独立生成的UUID不会发生冲突。

UUID 看起来像这样:

66e69275-c6bc-800c-90a6-2f41cb991502

由32个十六进制数字组成,分五组显示,用连字符分隔,形式为8-4-4-4-12。

UUID 的实际用例

  1. 分布式系统中的数据库密钥:在不同数据库或微服务需要生成唯一ID而不互相通信的系统中,UUID确保唯一性。例如,在分布式电子商务平台中,每个服务可能独立生成订单或交易 ID,UUID 将避免任何冲突。

  2. 会话 ID:UUID 通常用于标识 Web 应用程序中的用户会话。当您需要维护会话信息而不泄露敏感或可预测数据时,它们特别有用。

  3. 文件或资源标识符:当您需要跨不同平台或数据库跟踪文件、文档或任何资源时,可以为每个资源分配一个 UUID,以便于查找,而无需担心重复。

  4. API 和外部引用:在 API 中暴露连续或容易猜测的 ID(例如 user/1、user/2)可能会导致隐私漏洞。通过使用 UUID(例如 user/66e69275-c6bc-800c-90a6-2f41cb991502),您可以减少用户猜测和访问不属于他们的资源的可能性。

在 Python 中实现 UUID

Python 的 uuid 库使生成和管理 UUID 变得简单。方法如下:

import uuid

# Generate a UUID
generated_uuid = uuid.uuid4()
print(f"Generated UUID: {generated_uuid}")

uuid4() 函数根据随机或伪随机数生成随机 UUID,这是 Web 开发中最常见的变体。

示例:使用 UUID 作为数据库中的主键

当使用像 PostgreSQL 这样的数据库时,通常使用 UUID 作为主键。以下是如何使用 SQLAlchemy 在 Python 中进行设置:

from sqlalchemy import Column, String
from sqlalchemy.dialects.postgresql import UUID
import uuid
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class User(Base):
    __tablename__ = 'users'

    id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, unique=True, nullable=False)
    username = Column(String, nullable=False)

# This will generate a UUID primary key for each new user.

在此示例中,我们将 id 字段定义为 UUID,确保每个用户都有一个唯一的标识符,即使跨分布式数据库,也不会与其他记录冲突。

忽略 UUID 的风险

忽略 UUID 而选择顺序或自动递增 ID 可能会带来多种风险:

  1. 安全漏洞:序列 ID 是可预测的,使攻击者可以轻松枚举记录并发现敏感数据。例如,如果用户 ID 是连续的,攻击者可能会尝试猜测其他用户 ID 并访问未经授权的帐户。

  2. 数据冲突:在分布式系统中,依赖自增整数可能会导致ID冲突,特别是当多个服务或数据库在没有中央协调的情况下生成ID时。

  3. 数据迁移和合并问题:当组合数据库或跨系统迁移数据时,具有非唯一的顺序ID可能会导致冲突。 UUID 通过保证唯一性来避免这些问题。

使用 UUID 时的常见错误

  1. 将 UUID 存储为字符串:一个常见的错误是将 UUID 存储为字符串,这会浪费空间并降低查询速度,尤其是在大型数据库中。大多数现代数据库(例如 PostgreSQL)都具有可有效存储 UUID 的本机 UUID 类型。

    错误的

    CREATE TABLE users (
        id VARCHAR(36) PRIMARY KEY
    );
    

    正确的

    CREATE TABLE users (
        id UUID PRIMARY KEY
    );
    
  2. 未使用正确的 UUID 版本:UUID 有多个版本(例如,uuid1()、uuid3()、uuid4()、uuid5()),每个版本都适合特定用途案例。 uuid4() 基于随机数,最常用于在 Web 应用程序中生成唯一 ID。请注意您正在使用哪个版本以及它是否适合您的需求。

  3. 忽略碰撞可能性:虽然 UUID 被设计为唯一的,但发生碰撞的可能性非常小。对于大多数应用程序来说,风险可以忽略不计,但如果您要生成数十亿个 UUID 或在高度敏感的环境中运行,则应该实施冲突检测。

使用 UUID 的最佳实践

  1. 使用 UUID 进行外部引用:在 URL 或 API 中公开 ID 时,优先使用 UUID 而不是顺序 ID。这增强了安全性并使用户更难预测资源 ID。

  2. 以本机格式存储 UUID:使用数据库的本机 UUID 类型来存储 UUID,而不是字符串。这可以减少存储空间并提高查询性能。

  3. 选择正确的 UUID 版本:在大多数情况下,uuid4()(基于随机的 UUID)是在 Web 应用程序中生成唯一标识符的最佳选择。但是,如果您需要确定性生成的 UUID,您可以考虑 uuid3() 或 uuid5() (基于命名空间的 UUID)。

  4. 验证 UUID:从用户输入接受 UUID 时,请始终验证它们以确保它们在处理前格式正确。在Python中,您可以使用UUID对象来检查字符串的有效性。

def is_valid_uuid(uuid_to_test, version=4):
    try:
        uuid_obj = uuid.UUID(uuid_to_test, version=version)
        return str(uuid_obj) == uuid_to_test
    except ValueError:
        return False

# Example usage
print(is_valid_uuid("66e69275-c6bc-800c-90a6-2f41cb991502"))  # True
print(is_valid_uuid("invalid-uuid-string"))  # False

结论

UUID 是用于在分布式系统中生成唯一标识符并确保 Web 应用程序安全性的强大工具。它们可以帮助您避免数据库迁移期间的数据冲突、可预测的 ID 攻击和 ID 冲突等问题。通过了解并遵循 UUID 的最佳实践,您可以构建更强大、可扩展且安全的后端系统。

请记住使用适当的 UUID 版本,将它们正确存储在数据库中,并注意它们的潜在风险。有了这些技巧,您将能够在项目中有效地处理 UUID!


如果您对 UUID 有任何疑问或其他提示,请随时在下面发表评论!快乐编码!

版本声明 本文转载于:https://dev.to/usooldatascience/understanding-uuids-a-backend-engineers-guide-for-junior-developers-5075?1如有侵犯,请联系[email protected]删除
最新教程 更多>
  • 冰冷的池塘如何帮助您理解 C++ 中未定义的行为?
    冰冷的池塘如何帮助您理解 C++ 中未定义的行为?
    理解初学者的未定义行为对于新程序员来说,未定义行为是一个很难掌握的概念,特别是当他们在工作中遇到过它时实践其具体实施。为了帮助新手理解避免未定义行为的重要性,可以采用一个有效的类比。想象一个结冰的池塘,其中冰的厚度和稳定性是不可预测的。假设你走过池塘一次,它成立。这能保证每次都能安全通过吗?当然不是...
    编程 发布于2024-11-08
  • 在 Go 中使用 WebSocket 进行实时通信
    在 Go 中使用 WebSocket 进行实时通信
    构建需要实时更新的应用程序(例如聊天应用程序、实时通知或协作工具)需要一种比传统 HTTP 更快、更具交互性的通信方法。这就是 WebSockets 发挥作用的地方!今天,我们将探讨如何在 Go 中使用 WebSocket,以便您可以向应用程序添加实时功能。 在这篇文章中,我们将介绍: WebSoc...
    编程 发布于2024-11-08
  • 如何在Vue.js组件中动态加载外部JS脚本?
    如何在Vue.js组件中动态加载外部JS脚本?
    在 Vue.js 组件中动态加载外部 JS 脚本使用支付网关时,集成促进交易的外部脚本变得必要。然而,通常不希望在初始页面加载时加载这些脚本。这就是 Vue.js 提供的解决方案,用于在特定组件中动态加载外部脚本。要实现此目的,请利用 Vue.js 组件中的 Mounted() 生命周期挂钩。 Mo...
    编程 发布于2024-11-08
  • 如何使用 Foreach 循环查找 PHP 数组中的最后一个元素?
    如何使用 Foreach 循环查找 PHP 数组中的最后一个元素?
    使用 PHP 的 foreach 循环查找数组中的最后一个元素在 PHP 中,在 foreach 循环中访问数组的最后一个元素需要与 Java 相比,这是一种更细致的方法,可以直接检查数组长度。使用计数和增量要确定最后一个元素,您可以利用 count( ) 函数,返回数组中的元素数量:$numIte...
    编程 发布于2024-11-08
  • 如何解决Python中的循环依赖问题?
    如何解决Python中的循环依赖问题?
    Python 中的循环依赖解析在 Python 中,当模块相互依赖其定义时,可能会遇到循环依赖。当两个文件(node.py 和 path.py)分别定义类 Node 和 Path,并且每个文件都引用另一个文件时,就会出现这样的情况。最初,path.py 导入 node.py 来访问 Node目的。然...
    编程 发布于2024-11-08
  • rnr:适用于每个项目运行脚本的工具
    rnr:适用于每个项目运行脚本的工具
    嘿,JavaScript 和 TypeScript 开发者! ?您是否厌倦了使用不同的命令来启动各种 JS 项目?好吧,我有一些令人兴奋的消息要告诉你!我创建了一个名为 rnr(发音为“runner”)的工具,它使运行任何 JavaScript 或 TypeScript 项目变得超级容易。 ...
    编程 发布于2024-11-08
  • Java 的可选类型如何简化“Get”调用链中空值的处理?
    Java 的可选类型如何简化“Get”调用链中空值的处理?
    使用可选的“Get”调用链安全导航在 Java 编程中,经常会遇到“get”调用链,如下所示:house.getFloor(0).getWall(WEST).getDoor().getDoorknob();为了避免潜在的 NullPointerExceptions,开发人员通常采用详细的 null ...
    编程 发布于2024-11-08
  • 大泥球:理解反模式以及如何避免它
    大泥球:理解反模式以及如何避免它
    前端开发中最臭名昭著的架构反模式可能是大泥球。术语“大泥球”适用于没有明显结构或模块化组织的系统。代码库有机且混乱地增长,成为维护的噩梦。这是许多开发人员发现自己所处的情况,特别是当他们面临着按时完成任务并开发大量功能的压力时。 这就是当前文章的内容:大泥球反模式以及前端开发中的示例,为什么它如此常...
    编程 发布于2024-11-08
  • 如何正确使用带 Map 参数的“reflect.Call”函数?
    如何正确使用带 Map 参数的“reflect.Call”函数?
    解决reflect包中的.Call使用问题在reflect包中使用.Call函数时,遵守所需的参数格式至关重要。本文将指导您完成正确使用 .Call 函数并操作 in 变量以满足目标方法的过程。提供的示例代码中:params := "some map[string][]string&quo...
    编程 发布于2024-11-08
  • 如何使用 HTML 和 CSS 创建翻页卡动画
    如何使用 HTML 和 CSS 创建翻页卡动画
    在这篇文章中,我们将了解如何使用 HTML 和 CSS 以及渐变背景创建时尚的 3D 翻转卡片动画。 访问我的网站 了解结构 我们将使用卡片的两侧(正面和背面)来创建翻转效果。此效果将在悬停时使用 CSS 过渡激活。 <div class="card"> <...
    编程 发布于2024-11-08
  • Python 中的 len() 函数有多高效?
    Python 中的 len() 函数有多高效?
    Python 中 len() 函数的成本影响len() 函数是 Python 内置功能的组成部分,提供有关各种数据结构的长度的信息。具体来说,它通常与列表、元组、字符串和字典一起使用,以确定它们所包含的元素或字符的数量。与直观的感知相反,len() 函数的计算成本保持不变跨越所有上述数据类型。这意味...
    编程 发布于2024-11-08
  • 如何在 Java 中将 Long 值转换为字节数组并返回?
    如何在 Java 中将 Long 值转换为字节数组并返回?
    在 Java 中将 Long 转换为字节数组并返回在 Java 中,将 long 基本数据类型转换为字节数组 (byte[] ),反之亦然是各种操作的常见任务,例如通过 TCP 连接发送数据。下面是实现此转换的全面解决方案:Long 到 Byte Arraypublic byte[] longToB...
    编程 发布于2024-11-08
  • 如何使用 Selenium 在 Google Chrome 中模拟 Microsoft Edge Mobile?
    如何使用 Selenium 在 Google Chrome 中模拟 Microsoft Edge Mobile?
    使用 Selenium 更改 Google Chrome 中的用户代理在 Selenium 自动化脚本中,为浏览器窗口设置特定的用户代理对于模拟设备行为和确保网站渲染至关重要正如预期的那样。在这种情况下,我们的目标是将 Google Chrome 中的用户代理修改为 Microsoft Edge M...
    编程 发布于2024-11-08
  • 哪种 MySQL 获取函数适合您的 PHP 应用程序:`mysql_fetch_array`、`mysql_fetch_assoc` 和 `mysql_fetch_object` 的比较
    哪种 MySQL 获取函数适合您的 PHP 应用程序:`mysql_fetch_array`、`mysql_fetch_assoc` 和 `mysql_fetch_object` 的比较
    比较 mysql_fetch_array、mysql_fetch_assoc 和 mysql_fetch_object:综合分析mysql 函数系列在从 MySQL 查询中检索结果中起着至关重要的作用在 PHP 中。在这些函数中,mysql_fetch_array、mysql_fetch_assoc...
    编程 发布于2024-11-08
  • Lerna – Monorepo 管理的关键
    Lerna – Monorepo 管理的关键
    欢迎回到莫诺雷波城堡! 现在城堡已经建成,每个房间(项目)都已就位。但如果没有正确的管理,事情可能会变得混乱。谁来帮助城堡顺利运转?这时勒纳登场了——一位强大的巫师,拥有神奇的命令,可以让一切保持秩序。 Lerna 是您在 monorepo 土地上的向导,确保所有房间(项目)同步,所有包都链接,并且...
    编程 发布于2024-11-08

免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。

Copyright© 2022 湘ICP备2022001581号-3