读写分离必要性
垂直扩展限制于硬件资源,无法做到无限扩展,最终无法避免的走向水平扩展。
当单体数据库承受不了过高QPS后,考虑将单体转为主从集群模式。
将读请求通过路由策略+负载均衡路由到从库上,将写请求路由到主库,可以大大缓解高QPS对数据库的冲击。
我之前认为读请求过高,可以考虑加缓存解决。与同事讨论后,才考虑到缓存命中的问题。比如用户查询自己的信息,查询t_user表,每个用户在登录后查询,用户体量很大,这个缓存的命中率很低,缓存也一般情况下不会被使用到。所以读写分离的存在是必要的。
读写分离方案
水平扩展后有多个slave链接地址,腾讯云MySQL云服务介绍了使用中间代理层TProxy进行路由,还是那句话:没有什么是加一层代理不能解决的,如果有,那就再加一层。
代理层多了一跳也会影响一些rtt的耗时,但因为是纯路由,耗时几乎是可以忽略不计的。
综上,业务层面可以不维护Reader和Writer的DataSource和Mapper,当然你需要操作多个数据库的情况另外考虑。
业务代码支持读写分离
为了完善基础架构,也可以在业务层面进行读写分离(这种是客户端路由方式)以适应不同的业务场景。但就像dubbo和springcloud ribbon的客户端负载均衡对比grpc的xds-server和nginx的服务端负载均衡一样,没有哪种方式更有优势,只是针对不同业务场景的见仁见智。
以下是基础架构对于读写分离支持的初步想法,欢迎指教讨论。
扩展点:
1.基于mybatis拦截器
2.基于aop
在sql语句执行前,判断sql执行类型,根据sql执行类型,selectDatasource,选取读库和写库。
📎 参考文章
- 读写分离延迟问题