说一说时间戳机制的妙用

2022-07-22  本文已影响0人  天草二十六_简村人

一、时间戳是什么?

时间戳主要是标记数据的变动时间,同时它在实际的查询和操作等接口中,也有它的妙用。

示例,在mysql数据库中,时间戳就是字段modified_date,每次变更的时候,就会更新该字段为now()。

`created_date` datetime DEFAULT NULL COMMENT '创建时间',
`modified_date` datetime DEFAULT NULL COMMENT '更新时间',

二、编程实现

详请参考链接:https://www.cnblogs.com/myesn/p/mybatis-plus-auto-fill-field-value-and-soft-delete.html

/**
     * 创建时间
     */
    @TableField(value = "created_date", fill = FieldFill.INSERT)
    private Date createdDate;

    /**
     * 更新时间
     */
    @TableField(value = "modified_date", fill = FieldFill.INSERT_UPDATE)
    private Date modifiedDate;

需要再实现MetaObjectHandler

@Component
public class MybatisPlusMetaObjectHandler implements MetaObjectHandler {

    @Override
    public void insertFill(MetaObject metaObject) {
        this.strictInsertFill(metaObject, "createdDate", Date.class, DateUtil.date());
        this.strictInsertFill(metaObject, "modifiedDate", Date.class, DateUtil.date());
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        this.strictInsertFill(metaObject, "modifiedDate", Date.class, DateUtil.date());
    }
}
    @CreatedDate
    @Column(name = "created_date", columnDefinition = "datetime DEFAULT NOW() COMMENT '创建时间'")
    private Date createdDate;

    @LastModifiedDate
    @CreatedDate
    @Column(name = "modified_date", columnDefinition = "datetime DEFAULT NOW() COMMENT '更新时间'")
    private Date modifiedDate;

值得注意的是,你如果有手动执行sql语句,也切记把修改时间更新为当前时间。

三、流程图

增量查询.png 增量同步的流程图.png

四、使用场景

3.1、增量查询

不同于分页查询,增量查询的条件是根据时间戳大于传入的时间,也就是只查询变化的数据,而分页查询想要查询出变化了的数据,必须逐页查询所有页码。

举个例子,经常去逛图书馆的你,想要知道最近有些什么新书上架,而非逛遍整个图书馆。图书查询系统,如果有书的上架时间,每次查询新书,就只需根据拿上一次查询时间和图书的上架时间比较。

SELECT * FROM xxx
        WHERE
             <![CDATA[
                 (created_date >= #{timestamp} OR modified_date >= #{timestamp} )
             ]]>

3.2、增量同步

mysql数据库是有事务的,elasticsearch不具备事务,往往我们会使用Mysql来保存、修改或删除数据,复杂查询则交给elasticsearch。其实也就是CQRS架构中,我们会需要同步mysql数据到elasticsearch。

    @XxlJob("orderSyncJobHandler")
    @Transactional(rollbackFor = Throwable.class)
    public ReturnT<String> syncES(String param) {
// 把同步时间保存在redis里
        final String redisKey = indexConfiguration.getKey();

//本次同步时间
        Date thisSyncDate = DateUtil.offsetMinute(new Date(), -1);

        try {
            List<Order> orderList;

            ValueOperations<String, String> operations = redisHandler.getStringValueOperations();

//上一次同步时间
            Date lastSyncDate;
            int offsetMonth = 24;

// 由xxl-job手动指定同步时间
            if (!StringUtils.isEmpty(param)) {
                // 指定时间范围,单位是月,也可以是日,小时,分。
                offsetMonth = Integer.parseInt(param);

                lastSyncDate = DateUtil.offsetMonth(new Date(), -1 * offsetMonth);
            } else {
                // 从redis里取上一次的增量时间点
                if (!StringUtils.isEmpty(operations.get(redisKey))) {
                    lastSyncDate = DateUtil.parse(operations.get(redisKey), DatePattern.NORM_DATETIME_PATTERN);
                } else {
                    // 如果redis的key为空,默认初始化最近24个月的数据
                    lastSyncDate = DateUtil.offsetMonth(new Date(), -1 * offsetMonth);
                }
            }

// 防止数据量过大,这里采用分页查询,使用的是一个do-while循环。
            Pageable pageRequest = PageRequest.of(0, 100, Sort.Direction.ASC, "modifiedAt");
            do {
                orderList = orderRepository.findByModifiedAtGreaterThanEqualAndModifiedAtLessThanEqual(
                        lastSyncDate,
                        thisSyncDate,
                        pageRequest);

// 同步最新数据到es
                for (Order order : orderList) {
                    orderIndexService.sendToESFromDB(order);
                }
                pageRequest = pageRequest.next();
            } while (!orderList.isEmpty());

// 更新本次的同步时间
            operations.set(redisKey, DateUtil.format(thisSyncDate, DatePattern.NORM_DATETIME_PATTERN));

            return new ReturnT<>("定时同步订单数据到ES成功");
        } catch (Exception e) {
            log.error("定时同步订单数据到ES失败", e);
        }
        return ReturnT.FAIL;
    }
上一篇下一篇

猜你喜欢

热点阅读