Shardingsphere 强制主库查询

为什么要强制主库查询?

对于必须要拿到最新结果的请求,强制将其发到主库上。比如,在一个交易平台上,卖家发布商品以后,马上要返回主页面,看商品是否发布成功。那么,这个请求需要拿到最新的结果,就必须走主库。>对于可以读到旧数据的请求,才将其发到从库上。在这个交易平台上,买家来逛商铺页面,就算晚几秒看到最新发布的商品,也是可以接受的。那么,这类请求就可以走从库。

方法一:

public User getByIdFromMaster(Long id) {

        return Optional.ofNullable(id).map(uid -> {
            User user = null;
            HintManager.clear();
            try (HintManager hintManager = HintManager.getInstance()) {
                hintManager.setMasterRouteOnly();
                user = userMapper.getUserById(uid);
            }
            return user;
        }).orElse(null);
    }

方法二:

使用 AOP 思想,自定义注解 DBMaster,代码如下:

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.METHOD})
public @interface DBMaster {
}

在定义注解 Handler,代码如下:

@Slf4j
@Component
@Aspect
public class DBMasterHandler {

    @Around("execution(* cn.beckbi.service.impl.*.*(..))")
    public Object master(ProceedingJoinPoint joinPoint){
        Object[] args = joinPoint.getArgs();
        Object ret = null;
        log.info(joinPoint.toShortString());

        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        DBMaster dBMaster = method.getAnnotation(DBMaster.class);

        HintManager hintManager = null;
        try {
            if (Objects.nonNull(dBMaster)) {
                HintManager.clear();
                hintManager = HintManager.getInstance();
                hintManager.setMasterRouteOnly();
            }
            ret = joinPoint.proceed(args);
        }catch (Exception ex){
            log.error("exception error",ex);
        }catch (Throwable ex2){
            log.error("Throwable",ex2);
        }finally {
            if (Objects.nonNull(dBMaster) && Objects.nonNull(hintManager)) {
                hintManager.close();
            }
        }
        return ret;
    }
}

使用注解,代码如下:

@DBMaster
public User getById(Long id) {
	return this.userMapper.selectByid(id);
}

注意这里的一个方法,HintManager.getInstance(), 进入方法内部,如下:

public static HintManager getInstance() {
	// 直接 new 了一个强制路由管理器
    HintManager result = new HintManager();
    // 注意 HintManagerHolder 是一个 ThreadLocal 类型
    // 所以在使用完之后一定一定要记得把值 remove 掉,否则会出现意想不到的错误哦
    HintManagerHolder.setHintManager(result);
    return result;
}

public static void setHintManager(final HintManager hintManager) {
    // 如果你使用完不清空,这里就会帮你拦截直接抛异常,说你上面存在一个值在使用,没有被销毁。
    Preconditions.checkState(null == HINT_MANAGER_HOLDER.get(), "HintManagerHolder has previous value, please clear first.");
    HINT_MANAGER_HOLDER.set(hintManager);
}
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

魔道不误砍柴功

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值