写点什么

分布式系统改造方案——数据篇,Java 架构师视频

用户头像
极客good
关注
发布于: 刚刚

早期的架构基本都是这样,我们的应用程序在请求数据时,会先从缓存中获取数据,如果缓存中拿不到,再去数据库拿一次,拿成功之后在写入缓存,这样模式应该是很多公司前期开发模式。在这单体架构中会产生很多问题,tom 哥从常见问题的几个方面去帮大家踩坑,并提供解决方案。


数据库




我们的系统一上线,靠着"老奸巨猾"的产品设计的套路,源源不断的用户开始在我们的平台注册,3 个月内用户注册数量已经达到 3000W,这时候单表 3000W 的 user_info 表在瑟瑟发抖,这时候该怎么优化呢,很多同学都会说分库分表,但是具体怎么分呢?tom 哥会采用常见 hash 方案,首先我们可以把用户单独提出来做一个数据库(垂直拆分),这个数据库里我一次创建


user_info_0、user_info_1、....user_info_1023,


1024 张用户表,我们预估每张表 500W 数据,算下来 500W * 1024 = 51 亿 2 千万,这样的用户预估对于大部分互联网公司绝对够用了。但是随之而来带来很多新的问题,历史数据迁移问题、用户信息查询问题等等。先说说历史数据迁移吧。


历史数据迁移




我们的线上系统是一直再跑的,同步又发生在线下,这期间很难做到一致性,看过 tom 哥前面的文章应该知道历史数据迁移的时候会采用数据双写方案,也就是 2 个阶段。


第一阶段上


【一线大厂Java面试题解析+核心总结学习笔记+最新架构讲解视频+实战项目源码讲义】
浏览器打开:qq.cn.hn/FTf 免费领取
复制代码


线我们会同时往老表和新表各写一份,而迁移程序会在线下去跑,当然迁移程序和线上程序也会存在一个先后顺序的问题,假如迁移程序在某个更新线程之后就很有可能会存在覆盖的情况(请广大同学自行脑补这个画面,一定要想明白哦~),所以我们必须加上版本号或者时间戳等方案,判断当前更新的数据是否等于数据库内存在的版本,以保证原子性,尤其是用户余额这一类的字段操作一定要谨慎。


//类似乐观锁的实现模式,如果能够实现幂等更优


update userInfo set balance = balance + #{money} where userId = #{userId} and version = #{version}


第二阶段在线下同步程序跑完之后,这时候老表和新表数据应该基本都一致了,这时候我们可以把老表的操作代码直接删除,查询相关的内容统一更换成新表的操作,然后再上线一次,就成功完成数据迁移的过程了。


用户信息查询




这个也是一个常见的问题场景,假设我们分了 1024 张表,用户数据均匀的落在了在 1024 表内,例如之前我们按照用户手机号去查询时,本来可以轻松的写成


select * from user_info where mobile like '%#{mobile}%'


换成现在的查询方式该怎么写呢


select * from user_info_0 where mobile like '%#{mobile}%'


select * from user_info_1 where mobile like '%#{mobile}%'


···


select * from user_info_1023 where mobile like '%#{mobile}%'


额...这不能把 1024 张表全部循环一遍吧,并且公司的运营人员可能会根据更多用户信息去检索用户,如果我们按照目前的分表方式确实需要过滤全部的表才能找到匹配电话号码的用户,这里要怎么做呢?

用户头像

极客good

关注

还未添加个人签名 2021.03.18 加入

还未添加个人简介

评论

发布
暂无评论
分布式系统改造方案——数据篇,Java架构师视频