性能优化实战-欧洲杯足彩官网

`
hbxflihua
  • 浏览: 653119 次
  • 性别:
  • 来自: 杭州
最近访客
博主相关
  • 博客
  • 微博
  • 相册
  • 收藏
  • 社区版块
    • ( 0)
    • ( 0)
    • ( 1)
    存档分类
    最新评论

    性能优化实战-2

     

    我们在做架构设计的时候,会提到几个关键词:高性能、高可用、可扩展、安全性、伸缩性、低成本等等。对于用户量不大、并发量不高的系统,我们没必要去追求高性能,甚至连架构设计都可以免了。

    那么什么样的系统需要做性能优化呢?当你发现系统响应越来越慢,慢到已经影响到用户体验的时候;

     

    网站性能优化的手段:

    1、 web前端优化;

    减少http请求;

    使用浏览器缓存;

    静态资源压缩;

    减少cookie传输;

    cdn加速;

    反向代理;

     

    2、 应用服务性能优化;

    分布式缓存,通过添加缓存来提高应用层的响应效率;

    消息异步化:线程、队列等等;

    集群服务;

    代码优化:事务粒度调整、算法优化等;

     

    3、 数据库层优化;

    表结构优化、sql优化,索引等等;

     

    我们先看看交易所币币交易的业务流程:

     

    拿委托来说,原有的逻辑如下:

    用户登录后发起委托申请;

    后台进行用户状态、资金密码可用、货币状态等校验;

    校验通过后将委托单入库并冻结用户可用余额;

    将委托单发送给撮合队列进行撮合;

     

    通过梳理委托业务流程,我们发现委托的性能瓶颈主要在数据库层面,包括第二步的校验和第三步的数据持久化。而第四步的入队列操作比较简单,简单来说就只是一个队列消息发送,原则上并不会产生性能瓶颈。

     

    第二步的校验如何进行优化?校验是必须的,不校验是不可能的,这辈子都不可能。那那那怎么办?

    校验数据读缓存。

    首先,用户登录时已经将用户信息放入session,用户状态校验直接拿session信息进行比对就可以了。考虑到用户登录后用户状态信息可能会调整,那么在调整后需要将用户信息及时更新到session。另外,测试在做登录压测的时候,发现登录接口的吞吐量一直上不去,查表发现用户表数据量比较大,登录是通过手机号码进行登录的,所以我们对用户表的手机号码列加了唯一索引。

    资金密码可用的校验需要查用户密码策略表进行交易。用户密码策略基本属于较少变更的信息,可以将密码策略加入常驻缓存(一直放在缓存)。另外,为提高用户密码策略表的查询效率,对密码策略表创建用户id和货币id联合索引。

    我们直接将货币信息、货币对信息加入常驻缓存,后台货币有调整时及时更新至缓存,所以货币状态的校验也改成了缓存读取数据并做校验。

     

    第三步的数据持久化怎么办?第三步操作还涉及到用户可用余额的校验,用户可用余额校验必须要在用户发起委托申请时来做,看来这一步不能省。那还有优化的空间么?

    我们借鉴了互金资产交易系统中防超投的处理方案,将用户可用余额添加到缓存。有人会问,如果数据库数据和缓存数据不一致怎么办?欧洲杯足彩官网的解决方案是缓存操作和数据库操作都保持同步,如果不能同步更新,那至少也需要保证缓存数据和数据库数据的最终一致。

    具体到委托申请这块,我们先冻结缓存中的用户可用余额,然后将委托单加入撮合队列,在进行撮合的时候再将冻结金额持久化到数据库。

     

    简单总结一下委托下单的优化点:

    数据校验读缓存,以减少频繁查库带来的数据库压力;

    数据持久化先入队列,延迟写入数据库,以降低数据库的压力;

    为数据库表添加必要的索引,提高查询效率;

     

     

    接下来,我们看下挂单撮合的业务流程:

    冻结可用金额持久化和委托单持久化;

    从对方队列队首取出委托单进行撮合;

    撮合成功后将撮合结果添加到撮合持久化队列;

     

    我们以挂买委托单为例来了解一下撮合的操作流程:

    1、在挂买委托单过来之后,从卖队列(所有未撮合完成的卖委托单组成的集合)中弹出队首的卖委托单。

    2、如果无卖委托单或者卖委托单的价格高于买委托单的价格,则不进行撮合,将买委托单加入买队列集合。如果卖委托不为空,将卖委托重新加入卖队列。

    3、如果卖委托单价格低于或者等于买委托单价格,则进行撮合,撮合成交量取买卖委托单剩余挂单量的最小值。

    4、撮合完成的委托单不再加入队列,未完成的需要重新加入队列,加入队列的规则如下:

    买队列中按价格从高到低排列,如果买委托队列为空或队首的挂单价小于当前订单挂单价,将该单加入对队首,否则遍历插入相应位置。

    卖队列中按价格从低到高排列,如果卖委托队列为空或队首的挂单价大于当前订单挂单价,将该单加入对队首,否则遍历插入相应位置。

     

     

    第一步的可用冻结和委托单持久化操作原本是在委托申请时入库的,现在移到这里排队入库。这里没有较为明显的优化点,要么继续将持久化操作后置,要么是改为批量入库。

    第二步操作是内存的操作,优化主要集中在算法上;

    第三步操作和委托的第四步操作类似,仅仅是消息入队列,原则上不会产生性能瓶颈。

     

    下面重点讲一下第二步撮合操作在算法上的优化:

    1、原有的挂买、挂卖未撮合完成的委托单都放在本地内存中,为了更好的支持集群服务,我们首先将买卖队列由本地缓存改为redislist类型缓存;

    2、将撮合队列由原来的单个队列按业务拆分成挂买撮合、挂卖撮合和撤单三个队列,队列拆分类似于服务的横向扩展,可以在一定程度上提高系统的吞吐量,提升队列的处理能力,防止队列中消息堆积过于严重拖慢了整个服务的处理速度;

    3、挂买撮合、挂卖撮合开启多线程服务,每个队列开启10个线程,支持单机环境的并发操作;

    4、未撮合完成的委托单入缓存的优化,在第一次改版中,我们借助于redislist集合的加入、弹出等单线程操作,取得了很好的效果。但是在高并发场景下,会出现可以撮合却未进行撮合等问题。

    5、针对产生的问题,先是加了自动撮合定时器来自动撮合价格合适的买卖委托单,但是效果不是很明显。

    6、我们分析买卖队列数据,发现部分委托单存在排序错乱的情况。我们的算法其实没什么问题,但是在高并发下确实存在该问题。针对这个问题,大家首先想到的是加锁,通过锁来控制队列的进出,进而保证队列集合按价格顺序排列。但是这里又必须支持集群,如果加锁,势必会影响性能。那怎么办?有没有什么办法,既能支持多线程服务,还不需要加锁?

    7、启用lua脚本,将委托单的入队列操作单独抽取出来,改为lua脚本实现。

     

     

    简单总结一下撮合操作的优化点:

    队列拆分将操作频繁的队列(如撮合队列)按业务拆分;

    队列多线程     买卖队列开启多线程服务;

    使用lua脚本  提高委托单入队列的效率;

     

     

     

    然后,我们来看看撮合持久化的业务如何做持久化?

    原有的撮合持久化操作,是一个个排队消费处理的。

    撮合持久化的第一次优化是将队列中的持久化改为批量处理,如货币资金变更、资金日志、交易记录等等。

    压测过后发现消息堆积仍然比较严重,然后尝试将撮合持久化改为多线程处理,发现效果不是很明显,并且偶有死锁产生,这就说明通过开启多线程提高撮合持久化处理能力是行不通的。那么还有没有其他的办法呢?

    我们知道消息推送分为两类:推(push)模式和拉(pull)模式。rabbitmq默认的消息推送模式是push模式。

    推模式是长连接模式,能做到实时处理,提高响应速度。推模式缺点也比较明显,一次只能处理一个请求。

    而拉模式和推模式刚好相反,不能做到消息实时处理,可以一次拉取多个消息。我们的持久化操作对实时性要求不是那么高,可以通过一次拉取并处理多个消息来提高系统的并发量,进而在一定程度上减少消息堆积的量。

    我们在撮合持久化消费者端开启一个线程服务,用来消费撮合持久化队列。线程的消息推送模式改为拉模式,每次拉取20个消息,处理完毕休眠一段时间。休眠时间的长短根据队列中消息有无来进行调整,当队列中没有消息时,让线程休眠时间长一点,比如5s;当队列中有消息堆积时,让线程休眠时间短一点或者不休眠;

     

     

    简单总结一下撮合持久化的优化点:

    数据持久化单改批,但是批量操作的量不要设置的太大;

    消息推送模式推改拉,提高并发处理能力;

     

     

     

    性能优化总结:

    分布式缓存,通过添加缓存来提高应用层的响应效率;

    消息异步化:线程、队列等等;

    集群服务;

     

    代码优化:事务粒度调整、算法优化等;

     

     

    • 大小: 49.1 kb
    分享到:
    评论

    相关推荐

      携程h5性能优化实战-魏晓军

      《linux 性能优化实战》案例

      具体内容包括:基于用户体验的性能优化要素、前端性能优化实战、网站性能分析、服务端性能优化、tcp优化、dns优化、cdn优化、大型网站性能监控体系、大型网站容量评估、高性能系统架构模式、大促保障体系、数据分析...

      该文档来自mdcc 2015中国移动开发者大会。 徐凯(鬼道) - 手机淘宝 hybrid app 性能优化实战的主题演讲,欢迎下载!

      性能优化手册是一套java性能学习研究小技巧,包含内容:java性能优化、jvm性能优化、服务器性能优化、数据库性能优化、前端性能优化等。 内容包括但不限于: string 性能优化的 3 个小技巧 hashmap 7 种遍历方式...

      java 性能优化实战 21 讲,java 性能优化实战 21 讲,java 性能优化实战 21 讲,java 性能优化实战 21 讲

      java 大型网站性能优化实战从前端网络 cdn 到后端大促的全链路性能优化。 大型网站性能优化实战从前端网络cdn到后端大促的全链路性能优化 性能优化 网站 java 前端 服务器

      │ 开篇词 java 性能优化,是进阶高级架构师的炼金石.mp4 │ 02 理论分析:性能优化有章可循,谈谈常用的切入点.mp4 │ 03 深入剖析:哪些资源,容易成为瓶颈?.mp4 │ 04 工具实践:如何获取代码性能数据?....

      大型网站性能优化实战从前端网络cdn到后端大促的全链路性能优化

      java秒杀系统方案优化-高性能高并发实战 java秒杀系统方案优化-高性能高并发实战

      完整版,非常难得。

      大牛-高级教程mysql性能优化实战。

      flink原理、实战与性能优化.pdf

      目录 架构改进之路 1 文档处理的改进之路 1实战项目-性能优化实战架构改进之路服务的拆分,把离线文档的生成拆了出来,变成一个单独的rpc服务。实现rpc服务

      ‍《android性能优化-大厂实战全解析》

      深入剖析ios性能优化.pdf

      1、性能优化一定要建立在对业务的深入分析上,比如我们在性能优化的切入点,在缓存数据结构的选择就建立在对业务的深入理解上 2、性能优化要善于利用语言的高并发特性,

      阿里巴巴java性能调优实战

      对 java 工程师而言,性能优化能力决定了你能否进入大厂或成为一名高级工程师。但性能优化的能力却极难提升,如果你缺乏正确的方法论和实战演练,则很容易事倍功半。 视频大小:1.2g

      weex 架构简介和性能优化实战.pdf

    global site tag (gtag.js) - google analytics
    网站地图