优化数据库。(废话了)
1、将数据库体积定时的清理保持苗条的身材。
2、表要尽量简单,关系不要太复杂,尽量不要太多索引。
提升配置。
提升配置治标不治本啊。
优化程序。
1、利用客户端缓存,减少对数据库的反复读取,当用户读取一次评论之后便将评论信息写入本地cookie,当用户在一段时间内不停刷新页面的时候,就不让他再读数据库了直接去cookie里面取数据。添加到数据库数据成功的同时也返回数据告诉客户端也添加到cookie里面去。这样用户就知道他自己成功评论了,而且不论他怎么刷都伤不到服务器。
2、利用缓存服务器的缓存,减少对数据库的反复读取,和cookie差不多,只不过是存在了服务器的内存里面。这样比读数据库快,但是需要注意这种情况下,如果用户玩命的刷,服务器还是很伤。就算是读内存还是得读服务器的东西。
3、没必要将所有的评论都放在数据库里,如果评论太多太久远的没有意义的就删了吧。或者干脆静态化了得了,减少数据库的体积。
4、关于同一时间并发的评论,直接先不写数据库,先全写到内存里去合并数量,然后按照数据库能接受的节奏,写进数据库。其实这个也是治标不治本,真正的洪流来了,怎么优化都没用。直接封IP吧。
最后的大招:
告诉用户他的数据已经提交,但是服务器更新需要一定的时间,请不要着急等30秒后刷新看看。这招最简单,根本就不用什么程序。
数据库读写分离和数据一致性的冲突
读写分离: 为保证数据库数据的一致性,我们要求所有对于数据库的更新操作都是针对主数据库的,但是读操作是可以针对从数据库来进行。大多数站点的数据库读操作比写操作更加密集,而且查询条件相对复杂,数据库的大部分性能消耗在查询操作上了。
主从复制数据是异步完成的,这就导致主从数据库中的数据有一定的延迟,在读写分离的设计中必须要考虑这一点。以博客为例,用户登录后发表了一篇文章,他需要马上看到自己的文章,但是对于其它用户来讲可以允许延迟一段时间(1分钟/5分钟/30分钟),不会造成什么问题。这时对于当前用户就需要读主数据库,对于其他访问量更大的外部用户就可以读从数据库。
适当放弃一致性:在一些实时性要求不高的场合,我们适当放弃一致性要求。这样就可以充分利用多种手段来提高系统吞吐量,例如页面缓存、分布式数据缓存、数据库读写分离、查询数据搜索索引化。
因此:
我的想法是要使用读写分离来实现系统吞吐量的提升就要从业务上想办法降低一致性的要求。
对必须要有一致性的功能是无法进行读写分离的,可以采用多库不区分读写以及memcache缓存技术来实现。
脏数据和时间戳,还有数据一致性校验
今天在开发补货管理模块时,要新增加一个接口,功能是可以修改补货管理表里的订单状态。
在数据库里,由一个orderStatus字段来表示订单的当前状态,而这个状态可以由两种用户角色进行修改。一个是加工厂,另一个是供应商。之前在写方法的时候,还没体会到数据一致性的问题。但是昨天由老欧写了一个接口给我看了之后,发现比我写的方法多用到了表里的lastModifiedOn和modifiedBy字段。来校验数据。心里有些疑惑,就让他给我讲讲这方面的东西。
他说:A在修改状态的时候,从前端获取到的状态是1,要将其修改成3.但是在这个过程中,B用户已经把状态修改成2了,那么,A获取到的状态1,就成为脏数据。:
脏数据在临时更新(脏读)中产生。事务A更新了某个数据项X,但是由于某种原因,事务A出现了问题,于是要把A回滚。但是在回滚之前,另一个事务B读取了数据项X的值(A更新后),A回滚了事务,数据项恢复了原值。事务B读取的就是数据项X的就是一个“临时”的值,就是脏数据。
在项目里:整个业务流程由spo.tpl spo.controller.php spo.SCA.php spo.model.php 组成。
tpl显示数据,controller组织数据,SCA发布接口,model实现接口。A用户在修改tpl上显示的数据的时候,一起取到了lastModifiedOn的值为10:00,而SCA里在准备对订单状态进行修改的时候,先从数据库里取出$lastModifiedOn,和传进来的时间戳进行比对,如果两者一致,证明数据一致性没有问题。这时再进行修改。如果两个时间戳不一样,就必须中止写入,重新校验。
在每次更新数据时,都必须执行这一步。不然老欧很生气!后果很严重!
(PS:为什么MySQL里用来表示时间戳的字段要用datetime来存储而不用INT来存储unix时间呢,一个int比datetime更快,另外也不用考虑时区的问题,更方便。明天得问下他才行。)