双十一大促那会儿,你抢到那款限量耳机没?点‘立即购买’的瞬间,页面秒开、库存实时刷新、订单立马生成——背后不是服务器多牛,而是数据库悄悄分了工。
读和写,本来就不该挤在一张表里
就像一家奶茶店,老板既要接单(写),又要报库存、查订单、回顾客消息(读)。一个人干所有事,高峰期肯定手忙脚乱。数据库也一样:用户注册、下单、改地址是‘写操作’;商品列表加载、订单查询、个人中心展示是‘读操作’。写要保证数据准确,读只管快和稳——硬塞进同一个库,就像让收银员同时炒茶、打包、算账,不出问题才怪。
怎么分?主库写,从库读
常见做法是配一个主库(Master)专管增删改,再挂两三个从库(Slave)只负责查。主库把变更日志(比如 MySQL 的 binlog)实时同步给从库,延迟通常控制在毫秒级。应用层一发查询请求,就自动路由到从库;一发下单请求,就直奔主库。
代码层面也不复杂,比如用 Spring Boot + ShardingSphere 做简单路由:
spring:
shardingsphere:
props:
sql-show: true
datasource:
names: master,slave0,slave1
master:
driver-class-name: com.mysql.cj.jdbc.Driver
jdbc-url: jdbc:mysql://master-db:3306/shop?useSSL=false
username: root
password: 123456
slave0:
driver-class-name: com.mysql.cj.jdbc.Driver
jdbc-url: jdbc:mysql://slave0-db:3306/shop?useSSL=false
username: root
password: 123456
rules:
- !READWRITE_SPLITTING
dataSources:
readwrite_ds:
writeDataSourceName: master
readDataSourceNames: [slave0, slave1]
不是所有读都能甩给从库
刚下单完立刻去‘我的订单’查,结果页面显示‘暂无订单’——这事儿真发生过。原因?从库还没同步完主库的最新记录。这时候就得‘强制走主库’:比如在 SQL 注释里加 /*+ FORCE_MASTER */,或者接口加个参数 ?force_master=true,告诉路由层‘这次我信主库’。
小公司也用得上
别以为这是大厂专利。一台 4 核 8G 的云服务器跑 MySQL 主库,再加一台同配置的从库,用 Keepalived 做故障切换,配合 Nginx 把读请求按权重分发过去——不到五百块/月,就能扛住日活 5 万的社区类 App。关键不是堆机器,是让每台机器干它最熟的活。