Mybatisplus的雪花算法及代码生成器的使用
·
1. 雪花算法
1.1 背景:
雪花算法(Snowflake)的使用背景主要源于高并发分布式系统环境下对唯一ID生成的需求。这种需求在像Twitter这样的社交媒体平台上尤为突出,因为Twitter需要处理每秒上万条消息的请求,并且每条消息都必须分配一个唯一的ID。这些ID不仅需要全局唯一,以跨机器、跨时间区分,还需要保持一定的顺序性(尽管不要求连续),以方便客户端排序和后续的数据处理。
1.2 与自动递增的区别
一、生成原理
雪花算法:
- 雪花算法是一种由Twitter开源的分布式ID生成算法。
- 它将64位的long型ID分为四个部分:时间戳(41位)、数据中心ID(5位)、机器ID(5位)和序列号(12位)。
- 通过组合这四个部分来生成全局唯一的ID,其中时间戳确保了ID的顺序性,数据中心ID和机器ID确保了ID的分布式唯一性,序列号则用于在同一毫秒内生成多个ID。
自动递增:
- 自动递增是数据库(如MySQL)提供的一种主键生成机制。
- 它通过自动递增的方式为每条插入的记录生成一个唯一的ID值。
- 在MySQL中,自增ID通常与整数类型的列(如INT或BIGINT)结合使用,当插入新记录时,数据库会自动为该列生成一个唯一的ID值,并在下一次插入时自动递增。
二、适用场景
雪花算法:
- 适用于分布式系统和高并发环境。
- 能够满足全局唯一性和有序性的需求。
- 可以在应用层生成ID,减少对数据库的依赖和压力。
自动递增:
- 适用于单机系统或分布式系统中单个数据库节点的场景。
- 在这些场景下,自增ID能够高效地为每条记录生成唯一的标识符。
- 然而,在分布式系统中,如果多个节点同时生成自增ID,可能会导致ID冲突,需要额外的处理机制(如分表分库时设置不同的起始递增位置)。
三、性能特点
雪花算法:
- 由于其生成ID的算法较为简单,且不需要依赖数据库,因此生成ID的效率较高。
- 同时,由于ID是有序的,可以在一定程度上提高数据库的插入和查询效率。
自动递增:
- 在单机系统或单个数据库节点上,自增ID的生成效率也非常高。
- 但是,在分布式系统中,由于需要处理ID冲突的问题,可能会引入额外的性能开销。
四、全局唯一性保证
雪花算法:
- 通过时间戳、数据中心ID、机器ID和序列号的组合来确保ID的全局唯一性。
- 即使在不同的数据中心和机器上,也能生成唯一的ID。
自动递增:
- 在单机系统或单个数据库节点上,自增ID能够保证唯一性。
- 但在分布式系统中,如果多个节点同时生成自增ID,则无法直接保证全局唯一性,需要额外的处理机制来避免ID冲突。
注:雪花算法是由Twitter公布的分布式主键生成算法,它能够保证不同表的主键的不重复性,以及相同表的 主键的有序性。 即不同表的主键也不同,有利于做数据库的分表
2. SpringBoot常用的主键策略以及使用
2.1 常用的主键策略
2.2 使用
2.2.1Mybatisplus默认使用的是雪花算法
2.2.2也可以自行配置全局的主键策略
mybatis-plus: configuration: # 配置MyBatis日志 log-impl: org.apache.ibatis.logging.stdout.StdOutImpl global-config: db-config: # 配置MyBatis-Plus操作表的默认前缀 table-prefix: t_ # 配置MyBatis-Plus的主键策略(自动递增) id-type: auto2.2.3 也可以设置局部的主键策略
即在实体类的主键上的@TableId 加入type = IdType.ASSIGN_ID(雪花)
@TableId(type = IdType.ASSIGN_ID) private Long id;
3. 代码生成器的使用
2.1 注意
生成的代码可以设置一个单独的文件夹生成(然后再粘贴过来),但是包名要设置正确
2.2 引入依赖
<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-generator</artifactId> <version>3.5.1</version> </dependency> <dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>2.3.31</version> </dependency>2.3 快速生成
注意: 在多数据源配置中,
primary用于指定哪个数据源应该被视为“默认”数据源。当应用需要访问数据库,但没有明确指定使用哪个数据源时,就会使用primary指定的数据源。这通常用于读写分离的场景,其中primary通常指向主数据源(写数据源),而其他数据源作为从数据源(读数据源)使用。
public class FastAutoGeneratorTest { public static void main(String[] args) { FastAutoGenerator.create("jdbc:mysql://127.0.0.1:3306/mybatis_plus? characterEncoding=utf-8&userSSL=false", "root", "123456") .globalConfig(builder -> { builder.author("atguigu") // 设置作者 //.enableSwagger() // 开启 swagger 模式 .fileOverride() // 覆盖已生成文件 .outputDir("D://mybatis_plus"); // 指定输出目录 }) .packageConfig(builder -> { builder.parent("com.atguigu") // 设置父包名 .moduleName("mybatisplus") // 设置父包模块名 .pathInfo(Collections.singletonMap(OutputFile.mapperXml, "D://mybatis_plus")); // 设置mapperXml生成路径 }) .strategyConfig(builder -> { builder.addInclude("t_user") // 设置需要生成的表名 .addTablePrefix("t_", "c_"); // 设置过滤表前缀 //addTablePrefix("t_", "c_")方法的作用并不是直接指定哪些前缀的表应该被生成代码,而是用于排除掉那些表名以指定前缀开头的表,除非这些表在其他地方(如addInclude)被明确指定要生成代码。 }) . templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker 引擎模板,默认的是Velocity引擎模板 .execute(); } }
更多推荐




所有评论(0)