市面上分布式系统生成唯一ID的方式收集与整理

集群高并发环境下如何保证分布式唯一全局ID生成? 在集群高并发环境下保证分布式唯一全局ID生成是一个具有挑战性的问题。 阅读详情

系统唯一ID是我们在设计一个系统的时候常常会遇见的问题,也常常为这个问题而纠结。生成ID的方法有很多,适应不同的场景、需求以及性能要求。所以有些比较复杂的系统会有多个ID生成的策略。下面就介绍一些常见的ID生成策略。

  1. 数据库自增长序列或字段

最常见的方式。利用数据库,全数据库唯一。

优点:

1)简单,代码方便,性能可以接受。

2)数字ID天然排序,对分页或者需要排序的结果很有帮助。

缺点:

1)不同数据库语法和实现不同,数据库迁移的时候或多数据库版本支持的时候需要处理。

2)在单个数据库或读写分离或一主多从的情况下,只有一个主库可以生成。有单点故障的风险。

3)在性能达不到要求的情况下,比较难于扩展。

4)如果遇见多个系统需要合并或者涉及到数据迁移会相当痛苦。

5)分表分库的时候会有麻烦。

优化方案:

1)针对主库单点,如果有多个Master库,则每个Master库设置的起始数字不一样,步长一样,可以是Master的个数。比如:Master1 生成的是 1,4,7,10,Master2生成的是2,5,8,11 Master3生成的是 3,6,9,12。这样就可以有效生成集群中的唯一ID,也可以大大降低ID生成数据库操作的负载。

  1. UUID

常见的方式。可以利用数据库也可以利用程序生成,一般来说全球唯一。

优点:

1)简单,代码方便。

2)生成ID性能非常好,基本不会有性能问题。

3)全球唯一,在遇见数据迁移,系统数据合并,或者数据库变更等情况下,可以从容应对。

缺点:

1)没有排序,无法保证趋势递增。

2)UUID往往是使用字符串存储,查询的效率比较低。

3)存储空间比较大,如果是海量数据库,就需要考虑存储量的问题。

4)传输数据量大

5)不可读。

  1. UUID的变种

1)为了解决UUID不可读,可以使用UUID to Int64的方法。及

复制代码
///
/// 根据GUID获取唯一数字序列
///
public static long GuidToInt64()
{
byte[] bytes = Guid.NewGuid().ToByteArray();
return BitConverter.ToInt64(bytes, 0);
}
复制代码
1

2)为了解决UUID无序的问题,NHibernate在其主键生成方式中提供了Comb算法(combined guid/timestamp)。保留GUID的10个字节,用另6个字节表示GUID生成的时间(DateTime)。

复制代码
///
/// Generate a new using the comb algorithm.
///
private Guid GenerateComb()
{
byte[] guidArray = Guid.NewGuid().ToByteArray();

DateTime baseDate = new DateTime(1900, 1, 1);
DateTime now = DateTime.Now;

// Get the days and milliseconds which will be used to build    
//the byte string    
TimeSpan days = new TimeSpan(now.Ticks - baseDate.Ticks);
TimeSpan msecs = now.TimeOfDay;

// Convert to a byte array        
// Note that SQL Server is accurate to 1/300th of a    
// millisecond so we divide by 3.333333    
byte[] daysArray = BitConverter.GetBytes(days.Days);
byte[] msecsArray = BitConverter.GetBytes((long)
  (msecs.TotalMilliseconds / 3.333333));

// Reverse the bytes to match SQL Servers ordering    
Array.Reverse(daysArray);
Array.Reverse(msecsArray);

// Copy the bytes into the guid    
Array.Copy(daysArray, daysArray.Length - 2, guidArray,
  guidArray.Length - 6, 2);
Array.Copy(msecsArray, msecsArray.Length - 4, guidArray,
  guidArray.Length - 4, 4);

return new Guid(guidArray);

}
复制代码

用上面的算法测试一下,得到如下的结果:作为比较,前面3个是使用COMB算法得出的结果,最后12个字符串是时间序(统一毫秒生成的3个UUID),过段时间如果再次生成,则12个字符串会比图示的要大。后面3个是直接生成的GUID。

ODX}_4N5X$F93OAS~8Z)C

如果想把时间序放在前面,可以生成后改变12个字符串的位置,也可以修改算法类的最后两个Array.Copy。

  1. Redis生成ID

当使用数据库来生成ID性能不够要求的时候,我们可以尝试使用Redis来生成ID。这主要依赖于Redis是单线程的,所以也可以用生成全局唯一的ID。可以用Redis的原子操作 INCR和INCRBY来实现。

可以使用Redis集群来获取更高的吞吐量。假如一个集群中有5台Redis。可以初始化每台Redis的值分别是1,2,3,4,5,然后步长都是5。各个Redis生成的ID为:

A:1,6,11,16,21

B:2,7,12,17,22

C:3,8,13,18,23

D:4,9,14,19,24

E:5,10,15,20,25

这个,随便负载到哪个机确定好,未来很难做修改。但是3-5台服务器基本能够满足器上,都可以获得不同的ID。但是步长和初始值一定需要事先需要了。使用Redis集群也可以方式单点故障的问题。

另外,比较适合使用Redis来生成每天从0开始的流水号。比如订单号=日期+当日自增长号。可以每天在Redis中生成一个Key,使用INCR进行累加。

优点:

1)不依赖于数据库,灵活方便,且性能优于数据库。

2)数字ID天然排序,对分页或者需要排序的结果很有帮助。

缺点:

1)如果系统中没有Redis,还需要引入新的组件,增加系统复杂度。

2)需要编码和配置的工作量比较大。

  1. Twitter的snowflake算法

snowflake是Twitter开源的分布式ID生成算法,结果是一个long型的ID。其核心思想是:使用41bit作为毫秒数,10bit作为机器的ID(5个bit是数据中心,5个bit的机器ID),12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生 4096 个 ID),最后还有一个符号位,永远是0。具体实现的代码可以参看https://github.com/twitter/snowflake。

C#代码如下:

复制代码
///
/// From: https://github.com/twitter/snowflake
/// An object that generates IDs.
/// This is broken into a separate class in case
/// we ever want to support multiple worker threads
/// per process
///
public class IdWorker
{
private long workerId;
private long datacenterId;
private long sequence = 0L;

    private static long twepoch = 1288834974657L;

    private static long workerIdBits = 5L;
    private static long datacenterIdBits = 5L;
    private static long maxWorkerId = -1L ^ (-1L << (int)workerIdBits);
    private static long maxDatacenterId = -1L ^ (-1L << (int)datacenterIdBits);
    private static long sequenceBits = 12L;

    private long workerIdShift = sequenceBits;
    private long datacenterIdShift = sequenceBits + workerIdBits;
    private long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
    private long sequenceMask = -1L ^ (-1L << (int)sequenceBits);

    private long lastTimestamp = -1L;
    private static object syncRoot = new object();

    public IdWorker(long workerId, long datacenterId)
    {

        // sanity check for workerId
        if (workerId > maxWorkerId || workerId < 0)
        {
            throw new ArgumentException(string.Format("worker Id can't be greater than %d or less than 0", maxWorkerId));
        }
        if (datacenterId > maxDatacenterId || datacenterId < 0)
        {
            throw new ArgumentException(string.Format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
        }
        this.workerId = workerId;
        this.datacenterId = datacenterId;
    }

    public long nextId()
    {
        lock (syncRoot)
        {
            long timestamp = timeGen();

            if (timestamp < lastTimestamp)
            {
                throw new ApplicationException(string.Format("Clock moved backwards.  Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
            }

            if (lastTimestamp == timestamp)
            {
                sequence = (sequence + 1) & sequenceMask;
                if (sequence == 0)
                {
                    timestamp = tilNextMillis(lastTimestamp);
                }
            }
            else
            {
                sequence = 0L;
            }

            lastTimestamp = timestamp;

            return ((timestamp - twepoch) << (int)timestampLeftShift) | (datacenterId << (int)datacenterIdShift) | (workerId << (int)workerIdShift) | sequence;
        }
    }

    protected long tilNextMillis(long lastTimestamp)
    {
        long timestamp = timeGen();
        while (timestamp <= lastTimestamp)
        {
            timestamp = timeGen();
        }
        return timestamp;
    }

    protected long timeGen()
    {
        return (long)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds;
    }
}

复制代码

测试代码如下:

复制代码
private static void TestIdWorker()
{
HashSet set = new HashSet();
IdWorker idWorker1 = new IdWorker(0, 0);
IdWorker idWorker2 = new IdWorker(1, 0);
Thread t1 = new Thread(() => DoTestIdWoker(idWorker1, set));
Thread t2 = new Thread(() => DoTestIdWoker(idWorker2, set));
t1.IsBackground = true;
t2.IsBackground = true;

        t1.Start();
        t2.Start();
        try
        {
            Thread.Sleep(30000);
            t1.Abort();
            t2.Abort();
        }
        catch (Exception e)
        {
        }

        Console.WriteLine("done");
    }

    private static void DoTestIdWoker(IdWorker idWorker, HashSet<long> set)
    {
        while (true)
        {
            long id = idWorker.nextId();
            if (!set.Add(id))
            {
                Console.WriteLine("duplicate:" + id);
            }

            Thread.Sleep(1);
        }
    }

复制代码

snowflake算法可以根据自身项目的需要进行一定的修改。比如估算未来的数据中心个数,每个数据中心的机器数以及统一毫秒可以能的并发数来调整在算法中所需要的bit数。

优点:

1)不依赖于数据库,灵活方便,且性能优于数据库。

2)ID按照时间在单机上是递增的。

缺点:

1)在单机上是递增的,但是由于涉及到分布式环境,每台机器上的时钟不可能完全同步,也许有时候也会出现不是全局递增的情况。

  1. 利用zookeeper生成唯一ID

zookeeper主要通过其znode数据版本来生成序列号,可以生成32位和64位的数据版本号,客户端可以使用这个版本号来作为唯一的序列号。
很少会使用zookeeper来生成唯一ID。主要是由于需要依赖zookeeper,并且是多步调用API,如果在竞争较大的情况下,需要考虑使用分布式锁。因此,性能在高并发的分布式环境下,也不甚理想。

  1. MongoDB的ObjectId
    MongoDB的ObjectId和snowflake算法类似。它设计成轻量型的,不同的机器都能用全局唯一的同种方法方便地生成它。MongoDB 从一开始就设计用来作为分布式数据库,处理多个节点是一个核心要求。使其在分片环境中要容易生成得多。
    其格式如下:

前4 个字节是从标准纪元开始的时间戳,单位为秒。时间戳,与随后的5 个字节组合起来,提供了秒级别的唯一性。由于时间戳在前,这意味着ObjectId 大致会按照插入的顺序排列。这对于某些方面很有用,如将其作为索引提高效率。这4 个字节也隐含了文档创建的时间。绝大多数客户端类库都会公开一个方法从ObjectId 获取这个信息。
接下来的3 字节是所在主机的唯一标识符。通常是机器主机名的散列值。这样就可以确保不同主机生成不同的ObjectId,不产生冲突。
为了确保在同一台机器上并发的多个进程产生的ObjectId 是唯一的,接下来的两字节来自产生ObjectId 的进程标识符(PID)。
前9 字节保证了同一秒钟不同机器不同进程产生的ObjectId 是唯一的。后3 字节就是一个自动增加的计数器,确保相同进程同一秒产生的ObjectId 也是不一样的。同一秒钟最多允许每个进程拥有2563(16 777 216)个不同的ObjectId。

实现的源码可以到MongoDB官方网站下载。

谈谈分布式系统中的唯一ID生成 我们目前主流的服务端系统都是分布式的架构。业务分布在不同的机器节点上产生数据,数据也存储在不同的机器节点。为了方便标识数据,我们使用唯一且有序的ID来标识数据。整个分布式系统中,新生成的ID永远不会产生与之前已经生成的ID重复;生成的所有ID可以根据生成的时间进行排序(生成时间晚的排序顺序靠后)我们来看一下市面上的几种主流的ID生成方案。特性/方案Mysql 集群ID数据库雪花算法唯一性按照生成时间的有序性:x::x::x:维护的难易程度难较难易维护易维护。 阅读详情

相关推荐

开源跑腿系统智能派单算法与微服务架构深度解析

智能派单算法是同城配送与即时物流系统的核心技术,其核心原理是通过多维度权重计算实现订单与骑手的最优匹配。该技术通过整合实时地理位置、骑手负载、路径顺路度及历史信誉等数据,运用加权评分模型进行决策,旨在提升整体配送效率、优化骑手收入并保障用户体验。在工程实践中,智能派单通常作为独立微服务部署,与订单服务、地理位置服务及消息推送服务协同工作,构成高可用的分布式系统架构。结合预约调度、实时轨迹追踪等关键功能,该技术可广泛应用于校园跑腿、社区配送及本地生活服务等场景。本文以全栈开源跑腿系统为例,深入剖析其微服务架构

weixin_34341229的博客 547

分布式系统唯一ID生成方案汇总

系统唯一ID是我们在设计一个系统的时候常常会遇见的问题,也常常为这个问题而纠结。生成ID的方法有很多,适应不同的场景、需求以及性能要求。所以有些比较复杂的系统会有多个ID生成的策略。下面就介绍一些常见的ID生成策略。 1. 数据库自增长序列或字段 最常见的方式。利用数据库,全数据库唯一。 优点: 1)简单,代码方便,性能可以接受。 2)数字ID天然排序,对分页或者需要排序的结果很有帮助。

phubing 1493

Spring Boot电商后端实战:从架构设计到生产部署的完整指南

在现代企业级应用开发中,微服务架构与高并发处理是构建稳定系统的核心挑战。其原理在于通过服务拆分与异步解耦来提升系统的可扩展性与可靠性。Spring Boot作为Java领域最主流的微服务框架,凭借其约定大于配置的理念和丰富的生态,极大地简化了分布式系统的开发、测试与部署流程,为快速实现业务闭环提供了强大支撑。在电商、金融等高并发场景下,结合Redis实现高性能缓存、利用RabbitMQ进行异步消息处理,已成为保障系统响应速度与最终一致性的关键技术实践。本文基于一个真实、稳定运行多年的中型垂直电商平台后端系统

weixin_32466193的博客 350

JPA @Id 和 @GeneratedValue 注解详解

@Id:  @Id 标注用于声明一个实体类的属性映射为数据库的主键列。该属性通常置于属性声明语句之前,可与声明语句同行,也可写在单独行上。  @Id标注也可置于属性的getter方法之前。 @GeneratedValue:  @GeneratedValue 用于标注主键的生成策略,通过strategy 属性指定。默认情况下,JPA 自动选择一个最适合底层数据库的主键生成策略:Sql

斜阳雨陌 3万+

SpringBoot实战:网吧管理系统架构设计与核心业务实现

在软件开发领域,SpringBoot作为一款广受欢迎的Java框架,以其快速集成和约定大于配置的特性,极大地简化了企业级应用的开发与部署流程。其核心原理在于通过自动配置和起步依赖,让开发者能够专注于业务逻辑的实现,而非繁琐的框架整合。这一技术价值在构建各类业务管理系统时尤为突出,例如需要处理高并发事务、实时数据同步和复杂计费逻辑的场景。本文以一套基于SpringBoot 2.x开发的网吧运营管理平台为例,深入剖析了如何运用**WebSocket**实现机器状态的实时推送,并设计了精确的**计费引擎**来处理

weixin_34101914的博客 294

软件工程:数据字典

数据字典

永远怀着至诚之心拥抱世界 4273

JPA主键生成策略之GenerationType.Auto

场景:公司开发使用Mysql数据库,生产使用Oracle数据库,当同时使用两种数据库时,JPA主键生成策略可以选择GenerationType.Auto来实现。

Wqr_18390921824的博客 4540

Gromacs基础教程一:入门建议

本系列教程针对的群体:非计算化学专业,而是偏生物方向的、有少量分子动力学模拟需求的人群。

m0_67843839的博客 8572

手把手教你搭建SpringCloud项目(十八)集成Sleuth分布式链路跟踪

今天这篇文章介绍一下链路追踪相关的知识,以Spring Cloud Sleuth和zipkin这两个组件为主。 为什么需要链路追踪? 大型分布式微服务系统中,一个系统被拆分成N多个模块,这些模块负责不同的功能,组合成一套系统,最终可以提供丰富的功能。在这种分布式架构中,一次请求往往需要涉及到多个服务,如下图: 服务之间的调用错综复杂,对于维护的成本成倍增加,势必存在以下几个问题: 服务之间的依赖与被依赖的关系如何能够清晰的看到? 出现异常时如何能够快速定位到异常服务? 出现性能瓶颈时如何能够迅速定位哪个

〆、挽风的博客 3542

【AI平台】n8n入门2:第一个工作流,调用本地大模型

n8n是一款开源的,专注于AI工作流构建,支持灵活的自定义与集成。就是可以把大模型和其他工具联合起来,这就厉害了。而且,免费功能又强大,目前很火,来研究一下。

正经教主是个热衷于正经学习分享的教主。 4531

【万字长文】学习Armv8架构虚拟化一篇就够了

这里我们将介绍一些基础的Hypervisor和虚拟化的理论知识。如果你已经有一定的基础或是已经熟悉了这些概念,可以跳过这部分内容。我们用Hypervisor这个词来定义一种负责创建,管理以及调度虚拟机(Virtual Machines, VMs)的软件。Stage 2 转换允许Hypervisor控制虚拟机的内存视图。具体来说,其可以控制虚拟机是否可以访问特定的某一块物理内存,以及该内存块出现在虚拟机内存空间的位置。这种能力对于虚拟机的隔离和沙箱功能来说至关重要。

叫好与叫座虽然不是对立面,但想在同一个作品中达到双重效果很难。 5312

接上一篇:分布式调用链追踪系统设计

经过一番探索,一个分布式调用链系统的核心组件和实现原理浮出水面,当然,其中还有很多细节需要处理,例如采样的频率,全局唯一 ID 的生成算法,UI界面等等。Agent 虽然监控、生成了足够多的数据,但是单个 Agent 无法获得全局视图,我们需要一个全局的收集器来把 Agent 的数据收集上来,这样才能生成全局的调用链。所以必须得有一个独立的组件,在不干扰微服务的情况下,监控微服务之间的调用,把这些 ID 生成, 这个独立的组件就是 Agent。

m0_74530944的博客 1032

DSP在线升级方案:TMS320C6678使用网络或者串口输出升级数据进行固件升级

下面这段先引用创龙的说明 IBL 运行后, 将从 NOR FLASH 或 NAND FLASH 的 0x00080000 地址引导 ELF/BBLOB 格式 用户程序。 当引导 ELF 格式用户程序时, IBL 会解析用户程序头部信息,并根据头部信息 拷贝不同的代码段至指定 CPU 内存地址,然后将 PC 指针跳转至_c_int00, 再运行用户程 序。当引导 BBLOB 格式用户程序时,由于无头部信息, IBL 会将用户程序拷贝至 0x9E000000 (该内存地址为 IBL 代码指定),并将 PC..

ToneChip的专栏,一个传统的嵌入式码农,裸机编程 1941

模板驱动型文档自动化:让文档生成变成填空题

文档自动化是提升内容生产效率的关键技术,其核心在于将重复性文档工作解耦为可复用模板、结构化数据与样式规则。相比AI生成的不确定性或规则引擎的高学习成本,模板驱动方案以确定性填充、低代码配置和强样式继承为优势,天然适配咨询报告、法律文书、教育材料等标准化产出场景。它通过动态内容填充实现千人千面的精准输出,依托样式一致性保障确保品牌规范落地,最终在PDF/DOCX双格式导出中完成从‘能用’到‘可信’的跨越——本文即围绕这一轻量级但高实效的文档生产力范式展开深度实践解析。

weixin_30698297的博客 437

使用MATLAB中的Simulink工具来构建一个微电网系统的仿真平台

微电网是指由分布式电源(如太阳能、风能等)、储能装置、负载以及控制和保护装置组成的局部电力系统。它可以独立于主电网运行,也可以与主电网并联运行。本示例将以一个简单的微电网为例,展示如何利用Simulink进行微电网接入与孤岛运行策略的设计与仿真。分布式电源:模拟太阳能光伏板或风力发电机等分布式电源。储能装置:用于存储多余能量或补充不足能量。负载:模拟实际用电需求。双向变流器:实现直流与交流之间的转换,并支持并网和孤岛模式切换。控制器:负责管理微电网的运行模式,包括并网控制和孤岛控制。

xiaoheshang_123的博客 345

扩散模型中的UNET

一、为什么UNET模型可以用于去噪网络 二、扩散模型中的UNET是一个条件去噪网络,怎么实现的 三、UNET用于分割和用去去噪的区别

m0_37737957的博客 3816

探索微服务架构中的链路追踪

简介:一个用于分布式追踪的Spring组件,集成了多个链路追踪系统(如Zipkin和OpenTelemetry)。优点:与Spring生态系统高度集成,配置简单,支持自动生成和传播追踪信息。缺点:主要针对Spring框架,非Spring项目使用时需要额外适配。Zipkin简介:一个开源的分布式追踪系统,用于收集、存储和展示追踪数据。优点:简单易用,提供了直观的Web界面,广泛支持各种语言和框架。缺点:功能相对简单,缺乏一些高级功能。

Javajdkbz的博客 1236

Qt | linux+openCV+Qt6.5.3环境搭建成功版(带例子)

opencv安装 Qt 实战举例

Qt历险记,专注Qt技术,三年医疗设备研发经验,1年机器视觉研发经验,半年柔性传感研发经验。 1885

学习高并发难吗?Java高并发手册挺好,值得看看

近年来在大厂的面试中,高并发不但占比较多,而且已经不局限于并发工具的使用,更多的会深入到底层实现原理,这样能考察候程序员的内功,看其是否能知其所以然。关于市面上关于Java并发编程的资料感觉有些知识点不是很清晰,于是展开了对Java并发编程原理的讨论。在这收集整理了这份Java并发系统设计手册,分享给大家。基础篇高并发系统:它的通用设计方法是什么?架构分层:我们为什么一定要这么做?系统设计目标(一)如何提升系统性能?系统设计目标(二):系统怎样做到高可用?系统设计目标(三):如何让系统易于扩展?Scale-

JavaShark的博客 235

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

百度核心系统工程师笔试复盘:考点拆解与备战指南

计算机基础是系统工程师岗位的基石。操作系统、网络协议、分布式系统等底层知识,决定了能否应对大规模基础设施的挑战。理解页面置换、零拷贝、IO模型、TCP状态机、CAP与Raft等核心概念,不仅有助于剖析系统设计原理,还能在实际工程中定位性能瓶颈。海量数据场景下的TopK、LRU缓存淘汰、布隆过滤器等算法,直接体现了对空间与时间的权衡能力。从分布式锁的选型到多线程并发日志处理,每一个考点都指向真实业务中的可靠性、性能与一致性需求。本文基于百度核心系统工程师校招笔试的回顾,拆解各模块考察逻辑、典型题型与答题框架,

weixin_34151004的博客 871

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

AI Agent与Agentic AI:从单任务自动化到多智能体协同的本质区别与选型指南

在人工智能领域,智能体(Agent)技术正从自动化工具向自主系统演进。其核心原理在于赋予模型感知、规划、行动与学习的能力,通过集成外部工具与环境交互来解决实际问题。这项技术的价值在于显著提升任务执行的自动化程度与智能化水平,广泛应用于个人助手、客服、内容生成等场景。随着需求复杂化,单一的AI Agent在处理定义清晰的任务时表现出色,而面对开放域、动态变化的复杂问题,则需要Agentic AI范式。后者通过构建多智能体(Multi-Agent)系统,实现智能体间的协作、规划与涌现行为,以解决如自动化科研、复

djph26741的博客 436

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

2025 Java面试核心指南:JVM、并发、框架原理与系统设计深度解析

Java作为企业级应用开发的主流语言,其技术生态围绕JVM(Java虚拟机)构建,理解JVM的内存模型、垃圾回收机制是掌握Java程序性能调优的基础。并发编程则是提升系统吞吐量的关键技术,涉及线程安全、锁机制及并发工具包(JUC)的应用。在分布式架构成为主流的今天,对Spring框架IoC/AOP原理、MySQL索引与事务、Redis缓存及消息队列等核心组件的深入理解,是构建高可用、高性能系统的基石。本文聚焦Java面试中的高频考点与实战场景,通过剖析JVM内存调优、HashMap扩容机制、秒杀系统设计等典

weixin_33770878的博客 533

网易系统运维校招笔试复盘:从系统设计到高可用与故障排查

运维工程师的笔试考察早已不是单纯背诵命令,而是面对真实生产环境时,如何运用系统设计思维、高可用架构理念和故障排查方法论解决问题。从操作系统、网络协议到脚本自动化,底层能力决定技术深度;从监控告警体系、安全加固到变更管理,稳定性素养则体现工程视野。本文以网易系统运维校招笔试为线索,拆解从零搭建生产系统的设计逻辑、接口鉴权与数据安全要点,以及故障处理优先级和复盘方法,帮助求职者建立体系化运维认知,从容应对大厂SRE岗位的挑战。

500

知识图谱构建实战:从数据抽取到应用落地的完整指南

知识图谱作为结构化语义知识库,其核心在于将非结构化信息转化为机器可理解的关联网络。其技术原理基于图数据结构,通过实体和关系构建网络,相较于传统关系型数据库,在处理复杂、多变的关联查询时展现出高效与灵活的优势。这一技术为人工智能提供了可解释、可追溯的领域知识,极大地增强了AI的推理能力与可靠性。其应用场景广泛,从智能搜索、个性化推荐到风险控制与决策支持,已成为众多智能化系统的核心基础设施。本文聚焦于知识图谱的工程化构建流程,详细拆解了从知识建模、数据抽取、融合对齐到存储选型与应用开发的全链路实践,并结合实体对

csdndownload11123的博客 391

云计算运维培训机构怎么选?从考察清单到学习路线全解析

云计算已成为企业IT基础设施的核心,而云计算运维岗位要求工程师掌握Linux、容器、Kubernetes等关键技术。随着云原生理念普及,企业更看重候选人能否用代码管理基础设施,单纯依赖培训机构宣传的“就业率”难以验证真实水平。从学习路线看,系统基础、容器编排、自动化DevOps以及公有云实践是四大核心模块;从选班策略看,课程版本、项目深度、师资与就业数据才是考察重点。无论你选择千锋教育、聚云高科还是觉行教育,都应先明确自身阶段,再用考察清单逐项验证,并亲自完成一套Kubernetes集群搭建与部署,才能真正

weixin_34032621的博客 338

Java秋招面试八股文通关指南:JVM到Redis核心考点全拆解

技术面试是检验开发者知识体系与工程能力的重要关口,尤其在秋招场景下,扎实的基础知识往往决定了候选人能否在激烈竞争中突围。面试官通过追问JVM内存模型、并发机制、Spring原理等核心问题,考察候选人对底层实现的理解深度;而常用的排序算法如冒泡排序、快速排序的编写能力,则直观反映基础编码功底。针对实际开发中常见的java: outofmemoryerror: insufficient memory问题,更需要从内存区域划分与垃圾回收机制入手系统掌握。本文从构建知识地图、高频考点拆解、结构化表达三个维度,系统梳

weixin_30367873的博客 304
上一篇: Spring源码阅读之-BeanFactory(一)
下一篇: IntelliJ IDEA 常用快捷键
weiythi
博客等级 码龄16年 23粉丝 48原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值