一。概述
数据库读写分离,数据多出一份,数据库选用AP模型,为提高数据库性能,必然有数据一致性问题。写及时读,读不到最新数据。
数据库写及时读,未读到最新数据,本身发生概率较小。一般都是高并发,数据实例出现性能问题导致。应首先从减少服务器负载考虑,从尽量避免写及时读考虑。
数据库读写分离后,写及时读应该是数据存储层解决的问题,本不应延伸上层。
通过提高数据库实例性能,可满足大部分写及时读场景。理论上,业务方从编码或产品设计上,可避免写及时读这一操作的发生。
二。不同情况写及时读解决方法
- 数据库不主从读写分离
- 可以读过期数据
以上两种情况什么都不用做,就可解决写及时读问题。
- 由于负载高造成只读实例产生延迟,不能读到最新数据问题及解决办法。
- 只读实例规格过小升级只读实例的规格。
主实例的TPS过高。
- 业务进行优化或者垂直拆分
保证单主实例TPS不会导致只读实例出现延时。
- 主实例大事务
数据量非常大的事务,将大事务拆成小事务。
- 主实例DDL语句执行时间长
业务低峰期执行DDL。
- 延时下掉读实例
阿里云支持此功能。
- 尽量避免写数据库然后又立刻读
情况1.
一次调用,如先是插入,修改数据库中记录,然后立刻又从数据库读这一条记录拿到记录数值是不会发生的。因为之前插入,修改(删除)记录时,就知道入库的记录值,不需要操作后再读一遍数据库。这样也可以减少数据库操作。
情况2.
一次调用,如先是插入数据库中记录,然后立刻又从数据库读这一条记录拿到类似自增ID值。拿到ID是为了后面插入,修改记录关系。理论上业务关系应使用业务code建立,业务code都是代码先产生的。且这种操作一般都要添加事务,一个事务内读写操作都是在主实例,事务提交成功后再整体同步到从实例。
情况3.
一次调用,如先是插入,修改(删除)数据库中记录,然后立刻又从数据库成批读一组包含此记录数据。建议拆分成两次调用。一次调用插入,修改(删除)数据库中记录。一次调用成批查询记录。编码上不行,从产品上设置过度。
- 指定读主实例
- 通过Hint指定
- 阿里云RDS (MySQL)SQL上添加/*FORCE_MASTER*/
/*FORCE_MASTER*/ SELECT * FROM table_name;
- Sharding-JDBC线程变量HintManager设置primaryRouteOnly=true;
HintManager.getInstance().setMasterRouteOnly();
- 添加主实例数据源,指定读住实例
- 思路1:开发一个注解,被打上此注解函数读操作都走主实例数据源。
问题:容易出现业务方为简化开发,全部使用注解操作主库,从而失去了读写分离的意义。
- 思路2,监控所有数据库操作,所有修改记录后1秒内读操作都走主库。
问题:有可能1秒后数据也没同步到从实例,此时读操作转发到从,读不到最新数据。