Snowflake algorithm implementation principle and accuracy failure problem

1. Implementation principle of snowflake algorithm

        The snowflake algorithm is a globally unique algorithm. It mainly appears in scenarios such as database sharding and table sharding as business primary keys, or as some ID generators such as order numbers. So in terms of global uniqueness, there are many implementation methods, such as UUID, Redis's atomic increment, the auto-increment ID of the global table of the database, etc. However, in actual applications, it also needs to meet the requirements of ordered increment, high performance, timestamp, etc.

        As an algorithm for generating distributed globally unique IDs, the snowflake algorithm consists of a 64-bit long type number and is divided into four parts.
①. In the first part, 1 bit is used to represent the sign bit, which is usually 0 (because the first bit is the sign bit, and because the id will not be a negative number, it is usually 0)
②. In the second part, 41 bits are used to represent the timestamp in milliseconds, using the milliseconds of the system time.
③. In the third part, 10 bits are used to record the working machine ID, so as to ensure the uniqueness of the ID generated on multiple servers.
( If there is cross-computer room deployment, we can also divide it into two 5-bits. The first 5 bits can represent the computer room ID, and the last 5 bits can represent the machine ID. )
④. The fourth part uses 12 bits to represent the sequence number, which represents an increasing sequence and is used to record different IDs generated within the same millisecond.
Splicing these 64 bits into a long type number is the implementation of the snowflake algorithm.
        

2. The problem of loss of accuracy during use 

        When MyBatis-Plus implements addition, deletion, modification, and query, it will use id as the primary key column by default, and when inserting data, it will generate id based on the snowflake algorithm strategy by default. However, if you don't pay attention during use, you will encounter the problem of loss of accuracy.

CREATE TABLE user
(
	id BIGINT(20) NOT NULL COMMENT '主键ID',
        #其他字段省略
);
@Data
public class User {
    private Long id;
//其他成员变量省略

        Use Long type to correspond to database ID data. The snowflake algorithm generates a string of numbers, and the Long type is the standard answer! Set a breakpoint on the backend. See the data response is given to the frontend in JSON,

{
id:1297873308628307970,
//其他属性省略
}

Finally, this data is returned to the front end. After the front end receives it, it modifies the data and the back end receives it again.

The ID received back by the backend becomes: 12978733086283000000, no longer 1297873308628307970

Solution:

①: The id field is changed from Long type to String type. (Not recommended, the performance of String ID query will decrease )

②: The front-end uses String type snowflake ID to maintain accuracy, and the back-end database continues to use Long (BigINT) type   (yes!)

Back-end ID (Long) ==> Jackson (Long to String) ==> The front-end uses String type ID, and the front-end uses js string so the accuracy will not be lost.
@Configuration
public class JacksonConfig {

  @Bean
  @Primary
  @ConditionalOnMissingBean(ObjectMapper.class)
  public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder)
  {
    ObjectMapper objectMapper = builder.createXmlMapper(false).build();

    // 全局配置序列化返回 JSON 处理
    SimpleModule simpleModule = new SimpleModule();
    //JSON Long ==> String
    simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
    objectMapper.registerModule(simpleModule);
    return objectMapper;
  }
}
③: Abandon using the snowflake algorithm and instead use the unique self-increasing ID generated by MySQL. (Okay, it’s your choice)
        When using the @TableId(value = "id", type = IdType.AUTO) statement, it represents the use of the database's auto-increment strategy. Note that for this type, please ensure that the database has set the id auto-increment, otherwise it will be invalid.
        When the class name of the entity class type is inconsistent with the table name of the table to be operated, an error will be reported, and the annotation @TableName can help us solve this problem. My database table name is t_user, entity class name is User, just write @TableName("t_user") on the class name.
//设置实体类对应的表名
@TableName("t_user")
public class User {
    @TableId(value = "id",type = IdType.AUTO)
    private Long id;

When using the @TableId(value = "id") statement, if the primary key in the entity class and table is not id, but other fields, such as uid in the code, MyBatis-Plus will automatically recognize uid as the primary key column, otherwise it will Will report such an error:

Supongo que te gusta

Origin blog.csdn.net/weixin_49171365/article/details/132569210
Recomendado
Clasificación