Categories
technology|技术 中文

以数据库为中心进行架构设计

互联网项目,除了数据库组建,还经常会用到Cache(如:redis or memcache),MQ(如:kafka or RocketMQ)。无论有多少个组件,一定要以数据库为中心,提供数据访问。所有的Cache数据,都是数据库内数据的拷贝。

核心就两条:

  • 1.以数据库的数据为准
  • 2.如果数据跟数据库不一样,参考第一条

切忌:有时候写数据库,有时候写Cache,有的以db为准,有的读Cache为准。后果是:会经常性出现数据不一致。

程序读取数据的规则:

  • 1.先从Cache读取,如果存在,直接返回;如果不存在,就从db中读取,并写入Cache。
  • 2.如果数据更新,通常是直接更新数据库,然后让缓存失效(也可以直接更新Cache)
  • 3.极少数业务需求(例如:秒杀活动)时间短,并发量极大,可以直接读写Cache,然后等活动结束再写回db。

内部项目的数据分享策略:通过从库+视图+权限控制,提供有限的数据访问权限。从库是独立于主业务之外的从库,只提供内部其它项目使用,所以不会影响主业务的性能;用视图可以控制哪些字段可以被访问,也方便对数据进行过滤和排序。

对外提供数据的策略:通过Rest API+权限控制提供数据访问。外部应用通过参数请求API获取需要的数据,加上白名单机制,以及鉴权规则来对访问进行记录和监控。

如果担心数据库的性能问题,请参考:

支撑10亿用户的技术方案(思路篇)

支撑10亿用户的技术方案(细节篇)

Categories
technology|技术 中文

程序员的进阶思维

这篇文章写给有1年以上工作经验的开发人员。

  • 检验每一个输入参数的合法性
  • 考虑逻辑判断的边界条件
  • 对代码进行合理的封装,提高代码的复用性
  • 站在用户的角度考虑问题

对于游戏产品中出现的兑换码,用户输入兑换码可以领取奖励。 为了方便用户的识别,兑换码中,我们需要去掉哪些容易混淆的字符,如:数字1和字母I, 数字9和字母g。

  • 对于脚本代码,重复执行也不会出现问题

在线上运行时间足够久,我们可能会遇到需要批量修复线上数据的需求。通常我们需要写脚本来进行处理,这个时候一定要考虑到这样的问题:脚本执行可能会中断,或者运维不消息多次执行这个脚本。

  • 学会异常情况:异常情况可考虑加入日志跟踪

对于上线运营的产品,对于异常情况进行汇总分析&重要异常的报警,可以让开发团队先于客服团队发现问题,避免问题上报到高层领导并由高层施压处理问题。高层频繁收到问题的汇报,是研发团队失信的开始。

  • 站在运维部署的角度思考问题

举个最简单的例子:数据库的配置需要放在运维控制的配置文件里,生产环境的数据库配置信息是不能放在代码的配置文件中。

要想成为一名优秀的后端开发工程师,必须是要熟悉运维的,从熟悉linux系统开始,学会用户权限、磁盘管理、网络配置、防火墙、端口等基础知识,然后在单台服务器上下载、编译、按照各种工具,搭建数据库、缓存、web server等基础设置,最后还需要懂得如何搭建集群、监控、备份、安全等。

  • 对新老版本的兼容性

例如:对于某个API,需要调整它的参数格式。这个时候通常是新加一个API,前端的老版本还是访问老的API,新版本访问新的API,等到确认所有的用户都更新到老版本,才可以把老的API下线。

  • 安全性

API中只返回必要的信息,非必要信息不必返回,更不能向他人暴露用户的隐私信息。

  • 对于代码执行结果的线上跟踪方案

笔者在实际工作中遇到了一个需求:原来的用户表的主键是username,其它用户相关的信息都是用username进行关联的。后来发现用户有修改username的需求,这样就需要加入数字uid,并对关联的表数据用id进行重新关联。

相关的执行步骤如下:

1.给每个老用户生成唯一的数字uid,创建新用户的时候自动生成uid(生产环境验证:所有的老用户都加入了uid,所有的新用户创建的时候都会加上新的uid,而且所有的uid都是唯一的)

2.在db的关联记录中都加入加入uid,cache里面用uid关联生成原来一模一样的数据,这样既可以用username,也可以用uid获取数据(生产环境验证:所有的新老信息都有uid关联)

3.代码中逐步切换成用uid获取数据,如果uid获取不到,就用username获取(生产环境加入日志,如果用uid无法获取到信息,就记录日志,直到稳定运行一段时间,无任何相关的日志产生)

4.修改外部依赖于username获取数据的系统

5.确认所有的代码都是用uid关联获取数据之后,方可失效username关联的数据。