继续回答星水友的问题:盘口数据变化频繁,如何做缓存和推送,如何降低数据库压力?每个人的灵感。1.业务抽象很多客户关注市场,假设百万级别;数据量不一定大,市场上交易的股票数量,假设为10000只水平;写入量比较大,每秒发生很多事务,假设每秒几百级;计算比较复杂,有求和/分组/排序等操作;2.潜在的技术妥协1.如何选择客户端和服务器之间的连接方式?首先,手残客户端与服务器建立TCP长连接,短连接不会在每次请求时都建立和销毁,这样可以大大提高性能,减轻服务器压力。2、如何满足业务的实时性?盘口业务对数据的实时性要求高,服务端可以通过TCP长连接推送,保证消息的实时性。由于推送量巨大,可以独立推送集群,独享推送。推送集群独立后,可以通过增加推送服务器的数量来线性提升推送能力。如上图,假设有100W用户接收实时推送:搭建专用推送集群,与客户端保持tcp长连接,实时推送中每个推送服务保持10W长连接,10个推送服务可以服务100W用户推送集群与业务集群之间,通过MQ解耦,推送集群只推送消息,不进行任何业务逻辑计算,推送消息的内容由业务集群计算。最快推送到10W个客户端连接吗?如果消息量不大,比如每隔几秒发一条消息,可以开多个线程,比如100个线程,推送画外音:对应水友说的,如果量不大,您可以达成交易并推动交易。如果消息量过大,比如每秒几百条,可以暂存消息一秒,分批推送画外音:对应水友说的,如果消息量巨大,批量推送是个好方法。4、如何满足数据量、写入量、扩展性?存量少,数据量不是瓶颈。pipeline数据写入量在每秒几百级甚至上千级,数据库写入性能不是瓶颈。理论上,图书馆可以抵制它。如果每秒写入量达到10000级,可以在数据库层面进行水平切分,将不同股票的流量拆分到不同级别切分的库中,这样对数据库的写入量就可以成线性关系增加。画外音:横向拆分后,同一只股票的数据在同一个库中,不同股票的数据可能在不同的库中。理论上是不需要跨库查询的。如果每秒写入量达到10万、百万,还可以加MQ缓冲请求,削峰填谷,保护数据库。不管怎么说,按照这个业务的数据量和写入量,单库应该是没有问题的。5、如何满足复杂的业务逻辑操作?这个业务写的量不大,但是读的量很大。一定不能每次读请求都sum/groupby/orderby,这样数据库肯定处理不了。水友们已经想到了可以通过缓存来减轻数据库的压力,但是又担心“随着时间的推移,这种偏差必然会慢慢增大”。关于缓存一致性的放大,可以这样做:做一个异步线程,每秒访问一次数据库,计算复杂的业务逻辑,放到高可用缓存中。所有的读请求不再与业务逻辑计算耦合,所有这样,复杂业务逻辑的计算只会每秒执行一次,直接从高可用缓存中读取结果。问题是一秒内可能有很多流写入数据库,但不会实时反映到缓存中。在最坏的情况下,用户会在一秒前读取差点数据。无论如何,这是性能和一致性之间的设计权衡。以上所有方案都是基于在线客户数量庞大,推送消息庞大的前提,采用推送方案。很多时候,工程师会胡乱猜测,把问题想得很复杂,把计划搞得很复杂。如果在线人数较少,用户可以接受较长的延时(比如5s),可以采用轮询拉取方案:取消整个push集群和MQ集群;异步线程每1s写入一次高位数据,缓存可以使用一次;客户端每5s轮询一次拉取最新的盘口数据,只从缓存中拉取;完成!反正一定不能每次读请求都按sum/groupby/order计算,这个最需要优化。3.总结长连接的性能比短连接好很多倍。当推送量很大时,推送集群需要和业务集群解耦。可扩展,MQ缓冲区可以保护复杂的数据库业务。当读取量巨大时,加入缓存和时序计算可以大大减轻数据库的压力。想法比结论更重要。希望每个人都能有所收获。【本文为专栏作者《58神剑》原创稿件,转载请联系原作者】点此阅读更多该作者好文
