版本控制维护数据最终一致性

在业务开发中,经常需要维护缓存和快照的数据最终一致性;

备忘录模式: 保存一个对象的某个状态,以便在适当的时候恢复对象。

直接上代码吧!!!

1.缓存相关接口

CacheService.class 缓存接口定义
public interface CacheService<T extends Version> {
    /**
     * 存redis缓存和版本号
     *
     * @param t
     */
    void saveCache(T t);

    /**
     * 存redis缓存和版本号
     *
     * @param dataList
     */
    void saveCacheList(List<T> dataList);

    Map<Integer, Long> idVersionCacheMap();
}
ConsistencyService.class 数据一致性接口定义
public interface ConsistencyService {

    /**
     * 数据一致性维护
     */
    void keepConsistency();
}
AbstractCacheService.class 定义cache的基础接口和实现数据一致性的模板方法
public abstract class AbstractCacheService<T extends Version> implements ConsistencyService, CacheService<T> {

    @Autowired
    private SnapshotService<T> snapshotService;

    /**
     * 保存数据
     * 
     * @param t
     */
    public void save(T t) {
        // 先存快照
        snapshotService.save(t);
        // 再存redis
        saveCache(t);
    }

    List<T> check() {
        // 获取redis的版本map
        Map<Integer, Long> idVersionCacheMap = idVersionCacheMap();

        // 获取快照的版本
        Map<Integer, Long> idVersionSnapshotMap = snapshotService.idVersionMap();

        // 需要修复的数据
        List<Integer> needFixIds = new ArrayList<>();

        idVersionSnapshotMap.forEach((id, versionCache) -> {

            Long versionSnapshot = idVersionCacheMap.get(id);

            if (Objects.isNull(versionSnapshot)) {
                // 快照为null,跳出本次循环;
                // 理论上可以加上无版本删除逻辑
                return;
            }

            // redis的版本>数据库的版本;需要修复数据
            if (versionCache.compareTo(versionSnapshot) > 0) {
                needFixIds.add(id);
            }
        });

        // 需要修复的数据集合
        return snapshotService.list(needFixIds);
    }

    /**
     * 保持数据一致性
     */
    public void keepConsistency() {
        List<T> dataList = check();
        if (CollectionUtils.isEmpty(dataList)) {
            return;
        }

        // 保存redis数据
        saveCacheList(dataList);
    }
}
MenuCacheService.class 菜单缓存接口
@Service
public class MenuCacheService extends AbstractCacheService<MenuData> {

    @Override
    public void saveCacheList(List dataList) {
        // 保存redis
        // 保存版本号
    }

    @Override
    public void saveCache(MenuData t) {
        // 保存redis
        // 保存版本号
    }

    @Override
    public Map<Integer, Long> idVersionCacheMap() {
        return null;
    }
}

2.快照相关接口

SnapshotService.class 快照接口定义
public interface SnapshotService<T extends Version> {

    Map<Integer, Long> idVersionMap();

    void save(T t);

    List<T> list(List<Integer> ids);
}
MenuSnapshotMenuService.class 菜单快照接口
@Service
public class MenuSnapshotMenuService implements SnapshotService<MenuData> {

    @Override
    public Map<Integer, Long> idVersionMap() {
        // 数据库查询版本的map
        return null;
    }

    @Override
    public void save(MenuData o) {
        // 保存快照到数据库
    }

    @Override
    public List<MenuData> list(List<Integer> ids) {
        // 查询指定的快照
        return null;
    }
}

3.监控

VersionMonitor.class 版本监控,维护数据一致性
@Component
public class VersionMonitor {

    @Autowired
    List<ConsistencyService> consistencyServices;

    public void start() {
        consistencyServices.forEach(ConsistencyService::keepConsistency);
    }
}

4.实体

Version.class 版本实体
@Data
public class Version {
    private Long version;
}
MenuData.class 菜单实体
@Data
public class MenuData extends Version {

}

QQ交流群: 132312549

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值