当前位置: 代码迷 >> 综合 >> 日志分表
  详细解决方案

日志分表

热度:35   发布时间:2024-02-02 10:58:17.0

  日志通常来说记录只是为了查询问题时可以查到该条记录。所以一般查询该日志表,只会查询最近一段时间的。因此,日志分表不需要通过userId或其它字段进行取模分表。

  那日志怎么分表呢?这里一共提供两个分表方法。一个是根据时间分表;一个是根据表数据总量分表。

  一、根据时间分表

某个表插入时间只能在某个时间范围内,比如说,login_log分成3个表,login_log_1,login_log_2,login_log_3。login_log_1第一次插入时间是2020/07/29,我们设置30天分一次表,那么等到2020/08/29插入时,就要插入到表login_log_2了,等到2020/09/29插入时,就要插入到表login_log_3了。因为我们一共初始化了3张表,所以以后不管什么时候插入数据,都要插入到表login_log_2。

实现方法:初始化创建3个日志表 login_log_1,login_log_2,login_log_3;创建日志插入信息表login_log_insert_info,此表记录当前插入日志表的第一次插入时间(此表只保留一条数据);配置文件配置初始化日志表数  login.log.count=3。

插入日志表时,先查询login_log_insert_info,

1.如果不存在,则插入 login_log_1,同时login_log_insert_info增加log_1的首次插入时间;

2.如果存在,假设查询到的当前插入表号为2,则获取当前插入表首次插入时间距今是否大于30天,

2.1如果小于等于30天,直接插入login_log_2,

2.2如果大于30天,判断查询出来的当前插入表号2是否大于等于配置 login.log.count=3,如果大于等于,继续插入login_log_2;如果小于,则插入login_log_3,并更新login_log_insert_info的表号为3及首次插入时间为当前时间。

二、根据表数据总量分表

逻辑同根据时间分表,不过 日志插入信息表login_log_insert_info 改为 日志插入数据总数统计表 login_log_insert_count,然后判断是否分表时,判断当前表总数是否大于设置的每个表最大插入量。

 

以下代码为根据时间分表的部分逻辑

/*** 〈登录日志接口实现类〉** @author jump* @date 2019/10/12 0012*/
@Service
public class LoginLogServiceImpl implements LoginLogService {/*** 数据库中维护的登录日志表表名号最大值*/@Value("${login.log.table.no.max}")private Integer loginLogTableMax;/*** 每多长时间换个表插入登录日志(单位 月)*/@Value("${login.log.table.interval}")private Integer loginLogTableInterval;private static final String MABP_BASE_LOGIN_LOG_PRE = "mabp_base_login_log_";@AutowiredLoginLogRepository loginLogRepository;@Autowiredprivate SnowflakeGenerator snowflakeGenerator;@Overridepublic void insertLogInLog(InsertLogInLogRequestDTO requestDTO) {String tableNo = "0";//0新增;1更新;2不变String updateInsertInfoType = "2";String typeNew = "0";String typeUpdate = "1";//获取登录日志插入信息LoginLogInsertInfoPO insertInfoPO = loginLogRepository.queryLoginInsertInfo();//获取登录日志表表名后缀if (insertInfoPO != null) {Date firstInsertTime = insertInfoPO.getFirstInsertTime();Date now = new Date();int interval = getMonthInterval(firstInsertTime, now);if (interval > loginLogTableInterval) {int insertNo = Integer.valueOf(insertInfoPO.getTableNo());if (insertNo + 1 <= loginLogTableMax){tableNo = String.valueOf(insertNo + 1);updateInsertInfoType = typeUpdate;}} else {tableNo = insertInfoPO.getTableNo();}} else {updateInsertInfoType = typeNew;}//新增登录日志LoginLogPO loginLogPO = new LoginLogPO();BeanUtils.copyProperties(requestDTO, loginLogPO);loginLogPO.setTableName(MABP_BASE_LOGIN_LOG_PRE + tableNo);loginLogPO.setId(String.valueOf(snowflakeGenerator.nextId()));loginLogRepository.insertLoginLog(loginLogPO);if (typeNew.equals(updateInsertInfoType)) {//新增登录日志插入信息LoginLogInsertInfoPO insertInfoParamPo = new LoginLogInsertInfoPO();insertInfoParamPo.setId(String.valueOf(snowflakeGenerator.nextId()));insertInfoParamPo.setTableNo(tableNo);loginLogRepository.insertLoginInsertInfo(insertInfoParamPo);} else if (typeUpdate.equals(updateInsertInfoType)) {//更新登录日志插入信息LoginLogInsertInfoPO insertInfoParamPo = new LoginLogInsertInfoPO();insertInfoParamPo.setId(insertInfoPO.getId());insertInfoParamPo.setTableNo(tableNo);loginLogRepository.updateLoginInsertInfo(insertInfoParamPo);}}private int getMonthInterval(Date fromDate, Date toDate) {Calendar from = Calendar.getInstance();from.setTime(fromDate);Calendar to = Calendar.getInstance();to.setTime(toDate);int fromYear = from.get(Calendar.YEAR);int fromMonth = from.get(Calendar.MONTH);int toYear = to.get(Calendar.YEAR);int toMonth = to.get(Calendar.MONTH);int month = toYear * 12 + toMonth - (fromYear * 12 + fromMonth);return month;}
}

 

  相关解决方案