读写分离配置

用 sharding-jdbc 配置来实现读写分离

增删改 在主库 查 在从库 从库的内容为主库的复制 (轮询)

可能会导致数据不一致的情况 主库写入了 还没来得及复制到从库 查的请求就过来了

有两点解决方案

1 采用readis中间件缓存 建立一个标识 查每次都会先访问标识 看有没有 如果有 走主库 没有 走从库

但这个方案会有个严重的问题,也就是每次的读请求都要到缓存中去判断是否存在缓存标记,如果是单机
部署用的是jvm缓存,对性能还好;但如果是集群部署缓存肯定用redis,每次读都要和redis进行交互,这样肯定会影响系统吞吐量。

2 本地缓存标记
zrangewithscores
)用户A发起写请求,更新了主库,并在客户端设置标记,过期时间(预估的主库和从库同步延迟的时间),可以使用cookie实现
2)用户A再发起读请求时,带上这个cookie
3)服务器处理请求时,获取请求传过来的数据,看有没有这个标记
4)有这个业务标记,走主库;没有走从库。

这个方案就保证了用户A的读请求肯定是数据一致的,而且没有性能问题,因为标记是本地客户端传过去的。
但是无法保证其他用户读数据是一致的,但是实际场景很少需要保持其他用户也保持强一致。延迟个几秒也没问题。

创建一个maven 工程,pom文件如下

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.5.RELEASE</version>
        <relativePath/>
</parent>
    <groupId>sharding-master-slave</groupId>
    <artifactId>sharding-master-slave</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-boot-sharding-table</name>
    <description>基于 Spring Boot 2.1.5 使用sharding-sphere + JdbcTemplate 实现读写分离</description>
 
    <properties>
        <java.version>1.8</java.version>
    </properties>
 
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>io.shardingsphere</groupId>
            <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
            <version>3.1.0</version>
        </dependency>
        <dependency>
            <groupId>io.shardingsphere</groupId>
            <artifactId>sharding-jdbc-spring-namespace</artifactId>
            <version>3.1.0</version>
        </dependency>
    </dependencies>
	

核心配置类

    #配置真实数据源
	sharding.jdbc.datasource.names=master,slave
	#主数据库
	sharding.jdbc.datasource.master.type=com.zaxxer.hikari.HikariDataSource
	sharding.jdbc.datasource.master.hikari.driver-class-name=com.mysql.cj.jdbc.Driver
	sharding.jdbc.datasource.master.jdbc-url=jdbc:mysql://10.8.18.73:3306/master?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true
	 
	sharding.jdbc.datasource.master.username=root
	sharding.jdbc.datasource.master.password=123456
	 
	# 从数据库
	sharding.jdbc.datasource.slave.type=com.zaxxer.hikari.HikariDataSource
	sharding.jdbc.datasource.slave.hikari.driver-class-name=com.mysql.cj.jdbc.Driver
	sharding.jdbc.datasource.slave.jdbc-url=jdbc:mysql://10.8.18.74:3306/master?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true
	 
	 
	sharding.jdbc.datasource.slave.username=root
	sharding.jdbc.datasource.slave.password=123456
	 
	# 配置读写分离
	# 配置从库选择策略,提供轮询与随机,这里选择用轮询
	sharding.jdbc.config.masterslave.load-balance-algorithm-		  type=round_robin
	sharding.jdbc.config.masterslave.name=ms
	sharding.jdbc.config.masterslave.master-data-source-name=master
	sharding.jdbc.config.masterslave.slave-data-source-names=slave
	 
	# 开启SQL显示,默认值: false,注意:仅配置读写分离时不会打印日志
	sharding.jdbc.config.props.sql.show=true
	spring.main.allow-bean-definition-overriding=true

下面的类均是为了测试读写分离写的

@SpringBootApplication
	public class Application {
		public static void main(String[] args) {
			SpringApplication.run(Application.class, args);
		}
	}
	 
	 
	@RestController
	public class OrderController {
		@Autowired
		private OrderDao orderDao;
	 
		@RequestMapping(path = "/createOrder/{userId}/{orderId}", method = {RequestMethod.GET})
		public String createOrder(@PathVariable("userId") Integer userId, @PathVariable("orderId") Integer orderId) {
			Order order = new Order();
			order.setOrderId(orderId);
			order.setUserId(userId);
			orderDao.createOrder(order);
			return "success";
		}
	 
		@RequestMapping(path = "/{userId}", method = {RequestMethod.GET})
		public List<Order> getOrderListByUserId(@PathVariable("userId") Integer userId) {
			return orderDao.getOrderListByUserId(userId);
		}
	 
		@RequestMapping(path = "/", method = {RequestMethod.GET})
		public List<Order> getOrderListByUserId() {
			return orderDao.getOrderList();
		}
	}
	 
	 
	 
	 
	public interface OrderDao {
		List<Order> getOrderListByUserId(Integer userId);
	 
		List<Order> getOrderList();
	 
		void createOrder(Order order);
	}
	 
	 
	 
	 
	@Service
	public class OrderDaoImpl implements OrderDao {
		@Autowired
		JdbcTemplate jdbcTemplate;
	 
	 
		@Override
		public List<Order> getOrderListByUserId(Integer userId) {
	//        StringBuilder sqlBuilder = new StringBuilder();
	//        sqlBuilder
	//                .append("select order_id, user_id from order where user_id=? ");
	//        return jdbcTemplate.query(sqlBuilder.toString(), new Object[]{userId},
	//                new int[]{Types.INTEGER}, new BeanPropertyRowMapper<Order>(
	//                        Order.class));
			return null;
	 
		}
	 
		@Override
		public List<Order> getOrderList() {
			String sql = "select order_id, user_id from order_0 ";
	 
			return jdbcTemplate.query(sql, new BeanPropertyRowMapper<Order>(
					Order.class));
		}
	 
		@Override
		public void createOrder(Order order) {
			StringBuffer sb = new StringBuffer();
			sb.append("insert into order_0(user_id, order_id)");
			sb.append("values(");
			sb.append(order.getUserId()).append(",");
			sb.append(order.getOrderId());
			sb.append(")");
			jdbcTemplate.update(sb.toString());
		}
	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值