iris中xorm需手动配置主从:创建masterEngine(写/强一致读)和slaveEngine(普通读),服务层硬编码路由,禁用SQL自动解析;Redis用于缓存高频低频更新数据,写后主动失效保一致性。

iris 里怎么配 MySQL 主从读写分离
iris 本身不内置读写分离逻辑,得靠底层 ORM 或数据库驱动层支持。你用的是 xorm(从抽奖系统源码可知),它原生支持多数据源配置,主从路由要手动控制——不是自动识别 SELECT 就走从库,而是靠你在 DAO 层显式指定会话类型。
关键点:xorm 的 Engine 实例只对应一个数据库连接池;读写分离需要至少两个 Engine:一个主库(master)用于写和强一致性读,一个或多个从库(slave)用于普通查询。
- 初始化时分别创建
masterEngine和slaveEngine,各自调用xorm.NewEngine,连接串指向不同地址 - 写操作统一走
masterEngine:masterEngine.Insert(...)、masterEngine.Update(...) - 读操作按需选择:
slaveEngine.Find(...)用于列表页/统计类非强一致场景;masterEngine.Get(...)用于刚写完立刻查(如中奖后查最新记录) - 别在事务里混用:事务必须全程绑定同一个
Engine,否则会报session not bound to transaction
为什么不能依赖中间件自动路由 SELECT/INSERT
看似“自动识别 SQL 类型再分发”很省事,但实际在 iris + xorm 组合下极容易出错。xorm 的 Session 是有状态的,一旦开启事务、设置条件、启用缓存,就绑定了当前 Engine 实例。如果中间件试图在执行前解析 SQL 并切换 Engine,会破坏 Session 生命周期,导致:
-
Err: session closed—— 因为中间件把原 session 关了,又开了个新 session 但没传参 - 事务丢失:INSERT 后跟的 SELECT 被发到从库,查不到刚插入的数据
- 预处理语句失效:MySQL 的
PREPARE只在单连接内有效,跨库等于重来
所以真实项目里(比如那个抽奖系统),所有读写路由都是在 service 层硬编码区分的,而不是靠 SQL 解析器。
Redis 在读写分离架构里承担什么角色
它不参与 MySQL 的读写分离,但能大幅降低对从库的查询压力。典型做法是:把高频、低更新频次的读请求(如奖品配置、活动开关、用户当日抽奖次数)直接打到 Redis,命中就返回,不碰任何数据库。
- 用
GET/HGETALL替代SELECT * FROM prizes WHERE id = ? - 用 Lua 脚本保证原子性:比如“扣库存 + 写中奖记录”这种组合操作,避免先查再改引发超卖
- 注意过期策略:MySQL 数据变更后,必须主动
DEL对应 key,或设短 TTL 防止脏读;抽奖系统用的是写后主动失效,不是延迟双删
真正容易被忽略的点是:Redis 不是万能缓存层。一旦你开始用它兜底读请求,就必须同步维护它的数据一致性逻辑——这比单纯配两个 MySQL 连接串复杂得多,但收益也更实在。


















