我有一个包含很多计数器表的网站:
favorite
,follow
,upvote
,downvote
等。
现在每次点击我都会在这些表格中更新/插入一行。
最喜欢的表格
user_id|obj_id|time
关注表格
user_id|obj_id|time
每次点击我都要做更新/插入,即 1次点击= 1 ajax请求到服务器= 1更新/插入这会导致大量调用数据库。
根据数学(据我所知)并且计算次数最少:
1 click = 1 request
1 million click = 1 million request
100 million click/day
= 100 million request/day
= 416k request/hour
= 6830 request/min
= 115 request/sec
有没有更好的方法可以做到这一点?
答案 0 :(得分:0)
您是否已将客户端拆分为与服务器不同的计算机?这是缩放的第一步,次要步骤。
您是否有发送给Slaves的复制和只读查询?这可以允许无限制的读取缩放。 (但这并没有解决UPDATE问题,除了减轻主人的负担。)
单个旋转磁盘上的115个IOP几乎会使其饱和。 innodb_flush_log_at_trx_commit默认为1,这导致每个事务至少1个IOP。一些临时解决方案(直到你的流量再增加10倍)......
SSD - 可能是1000 IOP。
批量更新(例如@N.B.提到的)。这减少了“刷新”数量的100倍。
innodb_flush_log_at_trx_commit = 2 - 几乎消除了冲洗(在某种程度上失去了安全性)。
但是 - 即使你能够足够快地完成UPDATE,你也不需要读取值吗?也就是说,会有争用。您正在做相同的表上有多少个SELECT? 100 /秒可能没问题; 1000 /秒可能会造成太大的干扰而无法正常工作。
桌子有多大?要使其中任何一个工作,它需要足够小,以便始终缓存。
Reddit是另一种方法 - 在那里捕获更新。然后不断提取累积的计数并进行所需的更新。
分片 - 这是您在多台计算机上分割数据的地方。在用户标识的散列或查找(或两者的组合)上拆分很常见。然后UPDATE需要找出要更新的机器,然后在那里执行操作。如果你有10个分片(机器),你可以维持近10倍的更新速率。最终,这是所有重型打击者每天可以处理100M +用户和数十亿次查询的唯一方式。
分区不太可能有所帮助。分区修剪代码还不够高效,无法为这么小的查询避免过多的开销。