用 Hashids 优雅解决 C 端自增 ID 暴露问题

Hashids 原理及实现 Hashids是一个将数字转化为长度较短、唯一且不连续的值的库。特点是: 对非负整数都可以生成唯一短id 可以设置不同的盐,具有保密性 递增的输入产生的输出无法预测 代码较短,且不依赖于第三方库 原理 进制转换:将10进制的整数转化为 62 进制(26个字母大小写+10个数字),可扩展为任意进制。 private static String hash(long input, String alphabet) { String hash = ""; final int alphabet 阅读详情

在 C 端系统中,直接对外暴露数据库自增 ID 往往会带来数据枚举、越权访问等安全隐患。本文将从实际业务场景出发,分析自增 ID 暴露的问题本质,并介绍一种基于 Hashids 的可逆 ID 混淆方案。通过 Hashids,我们可以在不改变数据库结构的前提下,实现对外 ID 的安全化与美观化,兼顾安全性、性能与工程可落地性。

本文主要内容:

  • 为什么 C 端系统不能直接暴露自增 ID
  • 解决方案是什么
  • hashids有那些功能
  • hashids的代码实现是什么

为什么 C 端系统不能直接暴露自增 ID?

在后端系统中,我们习惯使用数据库自增 ID,并习惯性的直接返回给C端交互使用,例如:

登录接口在登录成功后返回的用户基础信息
{
    "userId": 100,
    "username": "tom",
    "gender": 1,
    "birthday": "2000-10-12 00:00:00"
}

URL上直接有自增ID:GET /api/user/100

可被枚举

只要有人发现这是自增 ID,例如:GET /api/user/100,自然可以被枚举

/api/user/101

/api/user/102

/api/user/103

......

发现了问题没:

  • 可以轻松遍历接口、爬虫可以批量扫库
  • 哪怕你有登录态、鉴权,只要 权限校验有一个点没兜住,后果极其严重:表数据被批量抓取,隐私数据被遍历、爬光
  • 这类攻击成本极低,甚至不算“攻击”

越权

越权的风险被无限放大,你“以为”你做了鉴权,其实不一定,现实情况往往是:

  • 接口 A 做了用户校验
  • 接口 B 忘了
  • 新接口临时加的,校验漏了
  • 某个内部接口被误暴露

一旦 ID 是可预测的:

  • 攻击者只需要找到 一个没校验的入口
  • 就可以“横向移动”访问所有数据

例如,URL中存在自增ID,在C端非常典型的场景是用户分享链接给朋友,如果朋友修改URL中的ID,就会跳转到本不属于自己能看到的数据内容。

业务信息全暴露

通过 ID 就能看穿你的业务信息,例如:

  • 📈 订单量增长速度

  • 👥 用户规模

  • ⏱️ 业务峰值时段

  • 🧮 是否删过数据(ID 是否断层)

这种在C端用户看来没有意义的数据,如果让用户“看不懂”的 ID,反而更专业。

  • 👉 纯数字 ID,看起来像“内部系统”

  • 👉混淆 ID, 更像“产品设计的一部分”

解决方案

根据以上问题,我们期望有这样一种解决方案可以混淆自增ID

  • 唯一不可重复:数据量内都必须唯一,不能重复
  • 支持可逆:ID可以编码为一个看不出规律的串,也可以解码为原ID,不影响数据库ID字段
  • 高效生成与解析:生成、验证的算法必须保证效率,不能占用太多系统资源
  • 不可预测与安全:无规则混淆,规律性不能很明显,不能轻易被人猜测到,防止爆刷
  • 工程成本低:不改表、不迁数据

常见但不够优雅的解决方案

  • UUID
    • 字符串过长
    • URL、二维码不友好
    • 调试体验差
  • Snowflake / Base64
    • 仍然可能暴露时间信息
    • 前后端实现不统一
  • AES / RSA 加密 ID
    • 性能与复杂度成本高
    • 对“只是隐藏 ID”来说属于过度设计

这个解决方案就是Hashids。

Hashids的核心功能:把一个或多个整数(int / long)转换成一个不可预测、可逆的短字符串。

基本属性

  • 输入是整数(支持long型),输出是字符串(只包含:a-z A-Z 0-9,无其他特殊字符)
  • 可以自定义编码字符
  • 可逆,但不可猜
  • 支持多个ID编码为一个字符串
  • 可控制最小长度,不支持“最长长度”限制,实际长度是不固定的,随输入数字大小变化

典型用途:

  • 数据库自增 ID ,对外展示用字符串,防止 ID 枚举

  • 短链接 / 邀请码 / 兑换码

  • URL / 小程序参数更友好

  • 将多个数字(数组)进行混淆,防止参数被篡改

注意:它是“混淆(obfuscation)”,不是“加密(encryption)”,不能作为密码学类的场景使用。

Hashids内部原理

编码(encdoe)流程:

原始数字 --> 打乱字符表(依赖 salt) --> 选取 guard / separator --> 进制转换(base-N) --> 按规则拼接 --> 输出字符串

核心组成元素

  • 核心组成元素
    • 字符表(alphabet):指定那些字符是输出的结果集
    • 默认字符集:abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890
    • 你也可以自定义(例如只用大小写 + 数字,排除 0/O/I/l),注意字符不能重复。
    • 字符集长度 = 进制 base N
  • salt
    • 决定字符表如何被洗牌
    • 同一个 ID,在不同 salt 下,结果完全不同
    • 不保存 salt,就无法反解
  • separators & guards
    • Hashids 会从 alphabet 中分出两类特殊字符:separators,分隔多个数字。guards,控制最小长度、增强不可预测性。
    • 这一步主要是为了:避免输出模式过于规则,同时支持编码多个数字的场景(encode(1,2,3))

怎么实现可逆性的?

  • 字符表洗牌(consistent shuffle)
  • 在相同 alphabet + salt下,编码同一ID,结果永远相同
for i from alphabet.length-1 downTo 1:
    j = (salt_char_code + i + previous) % i
    swap(alphabet[i], alphabet[j])

怎么转换为字符串的?

  • 假设字符表(alphabet)的长度为62
  • 数字先模62,得到的余数作为下标从字符表中取得一个字符
  • 再除62,直到数字小于0时停止
  • 得到一个字符串

如何支持同时编码多个数字?

例如:encode(1, 2, 3)

1 → abc
2 → k9
3 → z

中间用 separator(也是来自 alphabet,但经过专门筛选)隔开,最终输出:abcXk9Yz

怎么保证最小长度?

  • 在头尾插入 guard

  • 再次洗牌 alphabet

  • 重复直到满足长度,这一步是伪随机填充,不影响 decode。

decode的工作流程?

  • 去掉 guards

  • 用 separators 切分

  • 复原 alphabet 洗牌

  • 每一段做 base-N → long

decode失败怎么处理?

  • salt 不一致 → decode 失败或得到错误值
  • alphabet 不一致 → decode 失败

代码实现

终于到了激动人心的代码实现环节,撸起袖子,敲键盘。

在pom中导入依赖

<dependency>
    <groupId>org.hashids</groupId>
    <artifactId>hashids</artifactId>
    <version>1.0.3</version>
</dependency>

简单用法

import org.hashids.Hashids;
import org.springframework.stereotype.Service;

import java.util.Arrays;

@Service
public class HashidsService {

    //Bean单例,不存在线程安全问题
    private final Hashids hashids = new Hashids();

    public String encode(int code) {
        return hashids.encode(code);
    }

    public String encode(long code) {
        return hashids.encode(code);
    }

    public long decode(String decoded) {
        long[] decodes = hashids.decode(decoded);
        if (decodes.length == 0) {
            throw new IllegalArgumentException("非法ID");
        }
        return decodes[0];
    }

    public String encodeArr(int[] codes) {
        long[] codeArr = Arrays.stream(codes).asLongStream().toArray();
        return hashids.encode(codeArr);
    }

    public String encodeArr(long[] codes) {
        return hashids.encode(codes);
    }

    public long[] decodeArr(String decoded) {
        long[] decodes = hashids.decode(decoded);
        if (decodes.length == 0) {
            throw new IllegalArgumentException("非法ID");
        }
        return decodes;
    }

}

加盐

加盐混淆

  • 防止别人用同样库解你 ID
  • salt 一旦上线 绝对不能改
# application.yml
hashids:
  salt: kjsdfiaosudkskldjfa #混淆用的盐
  min-length: 8 #最小长度
package com.ks.demo.uc.hashids;

import org.hashids.Hashids;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.Arrays;

/**
 * 加盐混淆
 *
 * salt的作用
 * 防止别人用同样库解你 ID
 * salt 一旦上线 绝对不能改
 */
@Service
public class HashidsSaltService {
    @Value("${hashids.salt}")
    private String salt;
    @Value("${hashids.min-length}")
    private int minLength;

    //new在@Value注入之前
    //解决方案:后构造器,在构造器的入参使用@Value,使用@ConfigurationProperties单独注入
    //private Hashids hashidsSalt = new Hashids(salt);

    private Hashids hashidsSalt = null;
    private Hashids hashidsMinLen = null;

    @PostConstruct
    public void init() {
        hashidsSalt = new Hashids(salt);
        hashidsMinLen = new Hashids(salt, minLength);
    }

    public String encode(int code) {
        return hashidsSalt.encode(code);
    }
    public String encode(long code) {
        return hashidsSalt.encode(code);
    }
    public long decode(String decoded) {
        long[] decodes = hashidsSalt.decode(decoded);
        if (decodes.length == 0) {
            throw new IllegalArgumentException("非法ID");
        }
        return decodes[0];
    }

    public String encodeArr(int[] codes) {
        long[] codeArr = Arrays.stream(codes).asLongStream().toArray();
        return hashidsSalt.encode(codeArr);
    }
    public String encodeArr(long[] codes) {
        return hashidsSalt.encode(codes);
    }
    public long[] decodeArr(String decoded) {
        long[] decodes = hashidsSalt.decode(decoded);
        if (decodes.length == 0) {
            throw new IllegalArgumentException("非法ID");
        }
        return decodes;
    }

    public String encodeMinLen(int code) {
        return hashidsMinLen.encode(code);
    }
    public String encodeMinLen(long code) {
        return hashidsMinLen.encode(code);
    }
    public long decodeMinLen(String decoded) {
        long[] decodes = hashidsMinLen.decode(decoded);
        if (decodes.length == 0) {
            throw new IllegalArgumentException("非法ID");
        }
        return decodes[0];
    }

    public String encodeMinLenArr(int[] codes) {
        long[] codeArr = Arrays.stream(codes).asLongStream().toArray();
        return hashidsMinLen.encode(codeArr);
    }
    public String encodeMinLenArr(long[] codes) {
        return hashidsMinLen.encode(codes);
    }
    public long[] decodeMinLenArr(String decoded) {
        long[] decodes = hashidsMinLen.decode(decoded);
        if (decodes.length == 0) {
            throw new IllegalArgumentException("非法ID");
        }
        return decodes;
    }
}

自定义参与编码的字符

字符集规则:

  • 至少 16 个字符
  • 不允许重复字符
# application.yml
hashids:
  salt: kjsdfiaosudkskldjfa #混淆用的盐
  min-length: 8 #最小长度
  #至少 16 个字符,不允许重复字符
  #参与编码的字符,可以剔除调0/O/o,1/I/l等字符,增强可读性
  base-char: 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
package com.ks.demo.uc.hashids;

import org.hashids.Hashids;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.Arrays;

/**
 * 自定义参与编码的字符
 *
 * 字符集规则:
 * 至少 16 个字符
 * 不允许重复字符
 *
 * 使用场景
 * 避免 0/O、l/1 混淆
 * 只允许大写字母
 *
 */
@Service
public class HashidsBaseCharService {
    @Value("${hashids.salt}")
    private String salt;
    @Value("${hashids.min-length}")
    private int minLength;
    @Value("${hashids.base-char}")
    private String baseChar;

    private Hashids hashids = null;

    @PostConstruct
    public void init() {
        hashids = new Hashids(salt, minLength, baseChar);
    }

    public String encode(int code) {
        return hashids.encode(code);
    }
    public String encode(long code) {
        return hashids.encode(code);
    }
    public long decode(String decoded) {
        long[] decodes = hashids.decode(decoded);
        if (decodes.length == 0) {
            throw new IllegalArgumentException("非法ID");
        }
        return decodes[0];
    }

    public String encodeArr(int[] codes) {
        long[] codeArr = Arrays.stream(codes).asLongStream().toArray();
        return hashids.encode(codeArr);
    }
    public String encodeArr(long[] codes) {
        return hashids.encode(codes);
    }
    public long[] decodeArr(String decoded) {
        long[] decodes = hashids.decode(decoded);
        if (decodes.length == 0) {
            throw new IllegalArgumentException("非法ID");
        }
        return decodes;
    }

}

结尾

在文章最后,尝试对自己提问一下问题,来检验你是否真正了解到了本文的核心内容。

  1. C 端自增 ID 暴露会有那些问题?
  2. hashids的核心特性?为什么可以作为混淆自增id的解决方案?
  3. hashids的功能有那些?
  4. 代码怎么写?

本文结束。

Hashids.java使用入门 小型Java类,用于从一个或多个数字生成类似YouTube的哈希值。 由Ivan Akimov从javascripthashids.js移植 它是什么? hashids(哈希ID)从无符号(长)整数创建短的,唯一的,可解码的哈希。 它是为网站设计的,用于URL缩短,跟踪内容或将页面设为私有(或至少不可猜测)。 该算法尝试满足以下要求: 哈希值必须唯一且可解码。 它们应该能够包含多个整数(因此您可以在复杂或集群系统中使用它们)。 您应该能够指定最小哈希长度。 散列不应该包含基本的英语诅咒词. 阅读详情

相关推荐

ESP-Mesh-Lite vs ESP-Mesh:如何选择适合你的物联网组网方案?

本文深入对比了乐鑫ESP-Mesh-Lite与ESP-Mesh两种物联网组网方案的核心差异。重点解析了ESP-Mesh-Lite分布式协议栈架构的优势,即每个节点拥有独立IP,可直接访问外部网络,极大简化了应用层开发。文章从网络架构、性能、开发体验及适用场景等多维度进行分析,为开发者根据项目需求(如分布式数据采集、智能家居或集中控制网络)选择最合适的方案提供了清晰的决策框架。

pluto的博客 816

不想在地址栏中曝光你数据库自增ID的方法

当你想隐藏数据库id时,你可以使用 Hashids 这个开源库,类似的开源项目比较多,这里只针对 Hashids 做个使用说明 .net  版本的资料地址如下: 官网:http://hashids.org/net/ 代码:https://github.com/ullmark/hashids.net 以下是使用方法: using System; using Ha

草青工作室 的专栏 3901

libiec61850实战:手把手教你用C语言动态获取IED设备模型(附完整代码解析)

本文详细介绍了如何使用libiec61850库通过C语言动态获取IED设备模型,包括环境配置、连接建立、模型遍历及错误处理等关键步骤。通过完整的代码示例和实战案例,帮助开发者掌握智能变电站通信中的核心技术,提升工业自动化系统的开发效率。

weixin_42519985的博客 433

Java实现Hashids生成短且唯一的id

Hashids是一款非常小巧跨语言的开源库,可以将数字或者16进制字符串转为短且唯一不连续的字符串,Hashids是双向编码(支持encode和decode),比如,它可以将347之类的数字转换为yr8之类的字符串,也可以将yr8之类的字符串重新解码为347之类的数字。 pom.xml依赖 <dependency> <groupId>org.hashids</groupId> <artifactId>hashids</artifactId

u013014594的专栏 2951

VLA-JEPA:具身智能中潜空间世界模型的工程落地实践

世界模型是具身智能实现环境理解与因果推演的核心基础,其本质是在状态空间中建模‘动作→结果’的动力学规律。传统基于像素或文本的世界模型因高维、非平稳、弱语义等缺陷,在真实机器人场景中鲁棒性差、部署成本高。JEPA(联合嵌入预测架构)通过构建物理约束的潜空间,将视觉-语言-动作(VLA)信号统一编码为低维、可微、可解释的状态表征,显著提升模型对抖动、遮挡、光照突变等干扰的适应能力,并支持实时闭环控制。该范式已在UR5e、Franka等多构型机械臂及Jetson边缘平台完成实测验证,成为VLA系统从实验室走向产线

weixin_34357928的博客 336

R | 提取文件夹内栅格数据的最小值、最大值、标准差和平均值

各位同学好,我们长需要用长时间序列栅格数据的平均值做变量的时间变化分析,用代码能够帮助我们省下很多时间。

qq_48539301的博客 449

Hashids-Java 使用指南

--- ## 项目介绍 **Hashids-Java** 是 Hashids 算法的 Java 实现,它能够将数字(包括长整型)编码成短小、唯一且可解码的字符串,非常适合在公开场合如URL中使用,以隐藏真实的数据库ID。Hashids算法旨在生成看起来随机且不可预测的字符串,同时保留对原数字进行解码的能力。此项目是对原始Hashids库的一个安全且高效的Java版本,适用于希望增强数据隐私的W...

gitblog_00910的博客 482

基于RK3588平台的高分辨率多摄像头系统深度优化:从48M单摄到双摄分时复用的完整解决方案

本文深入解析了RK3588平台的高分辨率摄像头实现方案。重点介绍了:1)RK3588的MIPI PHY硬件架构,包括DCPHY和DPHY的资源配置及工作模式;2)双ISP合成技术,通过并行处理提升48M高分辨率图像的处理能力;3)以OV50C40传感器为例,详细展示了48M单摄系统的硬件连接、I2C设备配置和关键参数设置。文章为开发者提供了从硬件连接到软件配置的完整技术方案,有助于实现高性能嵌入式视觉系统。

FJN110的博客 673

Java:SpringBoot整合Hashids,实现数据ID加密隐藏

4、添加自定义序列化器和反序列化器。6、hashids工具类。

彭世瑜的博客 1268

华为OD机试 - 最快到达医院的方法(Python/JS/C/C++ 2024 E卷 100分)

刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、发现新题目,随时更新,全天优快云在线答疑。

学Java,找哪吒 2169

基于matlab的CNN验证码识别系统(UI界面版)

基于matlab的CNN验证码识别系统(UI界面版),CNN验证码识别系统包括数据集处理、模型搭建、模型训练、界面设计与实现

在职AI算法工程师,擅长计算机视觉,YOLO目标检测、分割等,擅长web、pyqt界面可视化,好内容持续更新中,来这里跟大家一起学习,共同进步 481

Hashids的使用

目录 1、Hashids的简介... 2 2、hashids加密和解密单个id. 2 3、变更salt加密和解密单个id. 2 4、hashids加密和解密多个id. 3 5、hashids自定义设置最小哈希长度... 3 6、hashids自定义设置哈希字母表... 4 1、Hashids的简介 Hashids是一个小型的开源库,它从数字生成简短的、惟一的、非顺序的id。它...

Aaron_Run的博客 1万+

C# 实现 Modbus 通信全教程(支持 TCP 和 RTU,含完整错误处理)

环境准备:安装 NModbus4 库,明确设备参数(IP/串口、地址、数据类型);连接设备:TCP 用 TcpClient,RTU 用 SerialPort,注意超时和参数匹配;读写数据:根据数据类型调用对应方法(读保持寄存器用 ReadHoldingRegisters);错误处理:捕获连接、超时、协议等异常,针对性排查问题。掌握这些后,即可轻松实现与工业设备的 Modbus 通信,为上位机开发提供稳定的数据交互能力。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 2066

推荐项目:pg_hashids - 让数据库ID更加安全、简洁!

推荐项目:pg_hashids - 让数据库ID更加安全、简洁! 项目介绍 在数字世界中隐藏敏感信息是至关重要的。pg_hashids,一个轻量级的开源工具,正是为了解决这一需求而生。它能将单调乏味的整数转换成短小、唯一且非顺序的字符串ID。例如,347瞬间变成“yr8”。不仅加密美观,还能轻松解码,使得数据传输和展示既安全又便捷。 项目技术分析 pg_hashids基于高效的C语言库hash...

gitblog_00565的博客 349

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

Flutter 组件 sqids 的适配 鸿蒙Harmony 实战 - 优雅地生成短 ID、保护业务隐私数据及不规则字符串混淆方案

是非常危险的行为。这不仅会让对手轻易推测出你的用户总量和业务规模,更可能由于不小心暴露了敏感资源的索引而引发安全风险。sqids(原 Hashids 的进化版)是一款优雅的开源库,它能将一串数字(如[1, 2, 3])转化为一段极简、不规则且唯一的字符串(如86Rf07适配到 OpenHarmony 平台后,无论是在处理本地数据库的防爬虫索引,还是在多端协同的资源分享链接中,sqids都提供了一套开箱即用、无损(可逆向解码)且高度可定制的混淆方案。本文将带你实战演示sqids在鸿蒙应用中的精妙应用。

好代码自己会说话,烂代码才需要注释来圆谎 4869

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

基于Knuth哈希的ID混淆技术:Optimus原理、实现与应用场景

在系统设计与API开发中,数据标识符(ID)的安全暴露是一个常见挑战。直接暴露连续或可预测的ID可能导致数据爬取、业务规模推测等安全与隐私风险。从技术原理层面,混淆技术通过可逆的数学变换,在保持ID功能性的同时隐藏其原始序列。其中,基于Knuth乘法哈希算法的ID混淆方案,通过模运算与异或操作实现高效可逆映射,其核心价值在于平衡了性能开销与基础安全需求。这种方案特别适用于API接口、前端资源展示等需要隐藏内部ID真实值的场景。本文以Optimus库为例,深入解析了其参数生成、加解密实现,并对比了Hashid

weixin_34221112的博客 372

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

golang 自定义类型不能使用nil_Go json使用的奇技淫巧

基本使用package main import ( "encoding/json" ) type A struct { B int C string } func main() { buf, err := json.Marshal(A{B: 1, C: "Hello"}) if err != nil { panic(err) }...

weixin_35750747的博客 695

ServiceStack安全防护终极指南:认证、授权与加密实战方案

在现代Web服务开发中,API安全是构建可靠系统的基石,涉及认证、授权与数据保护等多个层面。认证机制负责验证用户身份,常见方案包括基于会话的认证和JWT令牌认证,前者通过持久化会话解决横向扩展问题,后者则利用非对称加密确保令牌安全。授权体系则基于角色与权限模型,通过精细化控制决定用户可访问的资源与操作,结合动态权限与资源级授权策略,实现灵活的访问控制。数据安全方面,TLS/SSL加密传输与字段级加密技术保障了数据在传输与存储过程中的机密性。这些安全技术的核心价值在于构建防御纵深,防止数据泄露与未授权访问,广

cnvdkx2837的博客 432

Hashids.java使用介绍

Hashids.java使用介绍基本介绍它是什么用法编码一个数字解码用不同的盐解码编码多个数字编码并指定最小哈希长度指定自定义哈希字母编码和解码“ MongoDB” ID随机性重复号码坏哈希局限性项目地址: 基本介绍 它是什么 小型Java类,用于从一个或多个数字生成类似YouTube的哈希值。 hashids(哈希ID)从无符号(长)整数创建短的,唯一的,可解码的哈希。 它是为网站设计的,用于U...

qq_29144139的博客 1720

hashids

它的原理就是从数字经过一个加盐(salted)算法产生一个哈希(hash)字符串。这样算法就是通过混淆使结果具有不可预测性,而唯一性依然由数字本身来达成,从而得到(类似 youtube 里的)足够短,不可预测且唯一的 ID。安装:npm install hashids简单例子:let Hashids = require('hashids');let hashids = new Hashids();...

JQG的博客 3414

Spring AI + GPT-5.5 + Ollama 配置教程:Base URL、超时与流式调用

由于不同 Spring AI、Spring Boot 小版本之间仍可能存在差异,创建项目时应检查 Spring Initializr、Spring AI BOM 和官方兼容矩阵,不要直接复制旧教程中的 Starter 名称和版本号。多人项目最好隔离不同客户端,并在脱敏前提下记录最终 URL、状态码、请求耗时、请求 ID 和模型 ID。Spring AI 接入模型 API,至少要同时确认 Starter、Base URL、请求路径、API Key、模型 ID、连接超时、读取超时和流式客户端这 8 项。

2601_95893075的博客 225

InnoDB 内存结构总览:Change Buffer、AHI 与 Log Buffer

本文系统梳理InnoDB内存结构中的ChangeBuffer、Adaptive Hash Index(AHI)与LogBuffer。ChangeBuffer缓存二级索引页不在内存时的变更,减少随机IO,仅在页加载时合并;聚簇索引修改立即执行,因数据本身不可延后。AHI基于高频等值查询自动构建哈希索引,加速定位,仅支持等值操作。LogBuffer为redo log内存缓冲,配合磁盘日志实现崩溃恢复。三者均服务于性能优化,其中ChangeBuffer与AHI共享BufferPool空间,而LogBuffer独立

bksczm的博客 45

V8 机制、手写核心函数与 TypeScript 类型体操

或固定初始化(如数组先定长、对象先给全字段)保持类型与形状稳定;这些都比"换框架"更基础。只能处理纯数据(丢函数、Date、RegExp、循环引用报错)。生产级深拷贝要处理:原始值短路、循环引用、V8(Chrome / Node 的 JS 引擎)不是"解释一行跑一行"那么简单,它用。图:V8 执行流程——解释执行 + 热点优化,优化失败会 Deopt 回退。JS 内存自动管理,但"自动"不等于"不会漏"。是"固定间隔最多执行一次"。手写 Promise 是"懂异步"的试金石。是"停下后才执行最后一次",

qq_38468358的博客 330
上一篇: 如何在系统中正确判定工作日与节假日?从需求分析到技术设计与实现
下一篇: 如何用SSH访问远程服务器上的内网服务(如:MySQL、Redis、Kafka)?
ALGO阿狗
博客等级 码龄9年 64粉丝 149原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值