当前位置: 首页 > wzjs >正文

wordpress 设置头像api北京seo多少钱

wordpress 设置头像api,北京seo多少钱,高端网站建设有哪些,自己编程做网站主键 ID VS 业务 ID 在数据库设计中,除了主键 ID,一般还需要一个具有唯一索引的业务 ID。二者承担的职责不一样,它们共同满足了我们对于 技术实现 和 业务需求 的双重目标 1. 职责分离原则 主键 ID 业务唯一标识 ID 作用 保证数据库层面…

主键 ID VS 业务 ID

在数据库设计中,除了主键 ID,一般还需要一个具有唯一索引的业务 ID。二者承担的职责不一样,它们共同满足了我们对于 技术实现业务需求 的双重目标

1. 职责分离原则

主键 ID

业务唯一标识 ID

作用

保证数据库层面的唯一性

保证业务层面的唯一性

目标

保证数据存储和关联的可靠性

满足业务规则和外部交互需求

特点

无意义、自增/随机、不可变

有具体业务含义、可读、可暴露

eg:

  1. 商品表的主键 ID 可能是 1、2、3,但商品编码(业务唯一标识)可能是00012517271821。前四位是所处的地区码,中间是随机生成的数字,最后四位是新增这个商品的用户 ID 后四位
  2. 订单表的主键 ID 可能是 1、2、3,但订单编码可能是时间戳拼上今天订单的序号:202505220012

2. 使用场景分析

场景一:防止暴露内部信息
  • 问题:直接暴露自增主键ID,可能泄露业务规模(如用户量、订单量),甚至被恶意遍历数据
  • 解决:使用无规律的业务ID(如UUID、哈希值)对外暴露,隐藏自增主键

场景二:分库分表需求
  • 问题:如果需要分库分表,主键ID就无法保证全局唯一性
  • 解决:通过业务ID实现全局唯一(雪花算法生成的分布式 ID、使用自定义序列生成器生成的 ID)

场景三:业务标识符的灵活性
  • 问题:业务唯一标识可能需要动态规则(如订单号包含日期、地区码),而自增主键无法满足
  • 解决:业务唯一标识ID按业务规则生成,主键ID保持默认策略

3. 技术实现对比

主键 ID

业务唯一标识 ID

数据类型

通常为 int/bigint(高效索引)

可能是 varchar(兼容复杂规则)

唯一性范围

表内唯一

全局唯一(跨表、跨系统)

生成方式

自增/随机

程序生成(UUID、雪花算法、业务规则拼接)

修改性

不可变(与数据生命周期绑定)

可能允许修改(如用户重设唯一用户名)

建议:

  1. 主键ID始终存在:作为数据库的“技术锚点”,用于外键关联、索引优化
  2. 业务唯一标识ID按需设计
    1. 若无需业务唯一标识,可省略
    2. 若需暴露或业务规则复杂,必加,并为其添加唯一索引
  1. 查询优化
    1. 内部关联用ID(更快)
    2. 对外接口用业务ID(更安全)

4. 何时不需要用业务 ID ?

  • 纯内部工具表,无暴露需求
  • 业务标识符可直接复用主键(如简单的配置表)

为什么需要自定义序列生成器?

前面有说过业务ID一般是具有具体业务含义的,我们需要支持根据动态规则来生成具有不同业务属性的业务ID

注意:

自定义序列生成器一般用来生成业务 ID ,但也可以用来生成主键 ID。具体实现方式是由多个维度所决定的。例如:公司觉得主键 ID 使用雪花算法生成的 64 位长整型数字比较占用内存,但是又不想新增一个具备实际业务含义的字段,那就可以选择使用自定义序列生成器生成具备业务属性的主键 ID(合二为一)

下面,我将分别实现 单体架构分布式架构 下的序列生成器。它们最大的区别在于分布式架构下的序列生成器可以保证序列在多个不同的数据库之间也不会出现重复的问题,保证全局唯一性


单体架构实现

实现单体架构的序列生成器较为简单,只要想明白两个注意点:

  1. 由于要支持动态规则,所以需要用一张表来存储不同的业务生成序列的对应规则
  2. 我们需要保证业务 ID 唯一,所以每次要记录生成的最后一次数值,确保下次生成的值具有顺序且不重复

想明白了以上两点,我们就来尝试实现吧

实现步骤:

  1. 定义一张表用来配置不同业务的序列生成规则模板
CREATE TABLE `sequence_rule` (`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增列',`module_id` varchar(50) NOT NULL COMMENT '模块ID',`rule` varchar(100) NOT NULL COMMENT '序列规则',`cuid` int(11) NOT NULL COMMENT '当前流水号',`pref` varchar(50) NOT NULL COMMENT '规则前缀',PRIMARY KEY (`id`),UNIQUE KEY `idx_module_id` (`module_id`)
)  COMMENT='序列规则配置';

注意:模块 ID 要单独建立唯一索引,保证唯一性

  1. 定义一张表用来记录不同序列对应生成的值
CREATE TABLE `sequence_record` (`id` bigint(20) NOT NULL AUTO_INCREMENT,`sequence_key` varchar(64) NOT NULL COMMENT '序列编码',`sequence_value` bigint(20) DEFAULT NULL COMMENT '序列值',PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='序列ID记录表';

  1. 定义入口方法 VoucherIdManager.generateIds()
@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
public List<String> generateIds(ModuleEnum moduleEnum, Long length) {if (moduleEnum == null ||length == null) {throw new BizException(200, "缺失必传参数");}return this.buildIds(moduleEnum, length);
}

  1. 核心逻辑为 buildIds()
/*** 构建 ID** @param moduleEnum 模块枚举* @param length 集合长度* @return List<String>*/
private List<String> buildIds(ModuleEnum moduleEnum, Long length) {List<String> ids = new ArrayList<>();// 1.获取序列规则SequenceRule sequenceRule = sequenceRuleService.getByModuleEnum(moduleEnum);String rule = sequenceRule.getRule().toUpperCase();// 2.生成 ID 前缀// ID 规则为: CO[yy][mm][dd][ID000000]  则第二步会生成 CO20230501 这一串前缀String idPref = this.generateIdPref(rule);log.info("idPref -> [{}]", idPref);// 3.生成唯一值Matcher matcher = SEQUENCE.matcher(rule);if (matcher.find()) {// 如果匹配上了,获取 0 的个数  (0 的个数就意味着要生成的随机数的长度)int zeroLength = matcher.end() - matcher.start() - 4;for (int i = 0; i < length; i++) {Long nextSequence = sequenceManager.getNextSequence(idPref);ids.add(idPref + String.format("%0" + zeroLength + "d", nextSequence));}} else {throw new BizException(200, "序列规则配置错误");}return ids;
}

  1. 定义一个类,将数据库中对应序列的属性保存到内存(此处也可替换成 Redis)
private class SequenceHolder {private String key;/*** 当前序列号,初始化是为 0*/private AtomicLong sequenceValue;/*** 数据库保存的序列号*/private long dbValue;/*** 步长,用来判断序列号是否还在给定的步长范围内*/private long step;public SequenceHolder(long step) {this.step = step;}public long nextValue() {if (sequenceValue == null) {// 初始化this.init();}long sequence = sequenceValue.incrementAndGet();if (sequence > step) {// 意味着分配给它的序列号已经用完,需要重新分配this.nextRound();return this.nextValue();} else {return dbValue + sequence;}}private synchronized void nextRound() {if (sequenceValue.get() > step) {// 重新生成下一个序列号dbValue = SequenceManager.this.nextValue(key, step) - step;sequenceValue = new AtomicLong(0);}}private synchronized void init() {if (sequenceValue != null) {return;}dbValue = SequenceManager.this.nextValue(key, step) - step;sequenceValue = new AtomicLong(0);}}

步长 step 的作用是什么?

步长的意思就是一次返回序列号的长度。例如:step=100,则会修改数据库中对应序列的可用值为当前值 + 100,意味着这段区间已经分配给了当前服务。只要 sequenceValue 没有超过这个步长,则可以安全的使用分配给它的这一段区间。如果超过了,则需要重新获取一个新的区间,此区间长度为 step

  1. 实现序列生成逻辑
/*** @Description 序列生成器* @Author Mr.Zhang* @Date 2025/5/25 19:04* @Version 1.0*/
@Slf4j
@Component
public class SequenceManager {@Autowiredprivate SequenceRecordService sequenceRecordService;private static final Map<String, SequenceHolder> holder = new HashMap<>();/*** 获取下一个序列  确保唯一性** @param identity Key* @return*/@Transactional(propagation = Propagation.NOT_SUPPORTED)public long getNextSequence(String identity) {SequenceHolder sequenceHolder = holder.get(identity);if (sequenceHolder == null) {synchronized (holder) {sequenceHolder = holder.get(identity);if (sequenceHolder == null) {sequenceHolder = new SequenceHolder(1);  // 默认为 1sequenceHolder.setKey(identity);sequenceHolder.init();holder.put(identity, sequenceHolder);}}}return sequenceHolder.nextValue();}/*** 获取下一个序列  确保唯一性** @param sequenceKey Key* @return*/private long nextValue(String sequenceKey, long step) {for (int i = 0; i < 10; i++) {SequenceRecord sequenceRecord = sequenceRecordService.querySequence(sequenceKey);int effectRow = sequenceRecordService.nextValue(sequenceRecord.getSequenceValue() + step, sequenceRecord.getSequenceValue(), sequenceKey);if (effectRow == 1) {return sequenceRecord.getSequenceValue() + step;  // 返回下一个可用值}}throw new BizException(200, "获取序列失败");}
}

单体架构的核心代码就是这些。最主要的思路其实是保证序列生成的唯一性。此实现采用步长 + 乐观锁的方式确保不同的服务拿到的是不同的序列值

单体架构实现完整代码已上传到 github 上,感兴趣的朋友可以配合我的讲解看看具体实现代码

GitHub - nowtostudeyday/sequence-generate: 序列生成器。支持单体架构和分布式架构下的序列生成。支持自定义序列前缀,保证全局唯一性

欢迎 star~~

http://www.dtcms.com/wzjs/270148.html

相关文章:

  • 深圳网站设计哪家比较好googleplay安卓版下载
  • 邯郸专业做wap网站微信小程序开发文档
  • 网站开发建设培训搜索引擎营销的案例有哪些
  • 我自己做的一个网站显示证书错误seo排名推广工具
  • 哪个公司做网站专业全国新冠疫情最新情况
  • 贵阳哪家网站建设公司好产品运营主要做什么
  • qq是哪个公司汨罗网站seo
  • 什么是门户类型的网站网络营销推广处点
  • 京东商城网站建设策划书谷歌浏览器下载手机版中文
  • 石家庄商城网站建设今晚日本比分预测
  • 网站建设jwzcq风云榜百度
  • 枣庄手机网站制作武汉百度开户代理
  • 越秀定制型网站建设个人怎么做网络推广
  • 中铁建设集团有限公司梅洪亮江东seo做关键词优化
  • 网站建设托管公司关键词分类
  • 海门政府投资项目建设中心网站免费建设网站平台
  • 上海建筑设计院排名前10广州seo诊断
  • 德州做网站建设的公司哪家好查关键词排名工具app
  • 郑州做商城网站百度投诉电话人工客服24小时
  • 雁塔区网站建设页面优化算法
  • 怎样做网站推友情链接出售网
  • 品牌网站建设专家黄页网推广服务
  • 广西华宇建设集团网站中国新闻网
  • 镇江住房和城乡建设局网站公众号推广合作平台
  • 东莞市住房和城乡建设厅网站北京网站优化方法
  • 可以建公司网站专业搜索引擎seo公司
  • 揭阳企业网站建设公司企业seo排名外包
  • 网站建设服务费发票营销最好的方法
  • 做网站需要学哪些语言网络营销计划书怎么写
  • 可信赖的大良网站建设淘宝宝贝排名查询