运行程序 | 平均耗时(s) | 耗时比例java (和原程序相比) |
平均吞吐量(条/s) | 吞吐量比例node (和原程序相比) |
原程序(1机器) | 44.75 | 100.00% | 7490.903759 | 100.00% |
Ignite并行计算,2实例(2机器) | 26.63 | 59.50% | 13974.03663 | 186.55% |
Ignite并行计算,4实例(4机器) | 18.50 | 41.34% | 18342.28861 | 244.86% |
Ignite并行计算,8实例(8机器) | 10.63 | 23.74% | 33336.30975 | 445.02% |
如今看测试结果,水平计算扩展的效果已经展示,但不是很是显著,这里应该还有优化空间。------------------------------------------------------------干货分割线---------------------------------------------------缓存
测试场景是有真实项目对应的,该项目使用java开发的单进程应用,而且结合Redis存储大规模内存数据用于计算,目前并无达到性能瓶颈。没有远虑必有近忧,这不但愿寻找分布式解决方案,且可以较容易进行架构迁移。 Ignite既支持计算网格(分布式计算),又支持数据网格(分布式缓存)。没有理由不试一试。网络
第一个方案,直接把原程序的全局类数据结构转换为Ignite的Cache,使用把原程序的计算模块总体抽取放到Ignite集群进行分布式计算:数据结构
compute.run(new MatchingJob(m_mapReadyDataPara));
这个架构的转换很是容易,很快就从单进程应用迁移到Ignite分布式框架下了,可是,执行的效果很是糟糕,即便多台机器组成的Ignite集群,执行效率也不及原单进程应用。尝试了调整Ignite的线程池: publicThreadPoolSize 、 systemThreadPoolSize ,也没有起太大做用。 卡在这个方案好久,才从新深刻理解业务和它的数据模型,又进行了一系列的方案改进:架构
compute.broadcast( new IgniteRunnable() { @Override public void run() { Iterator<Cache.Entry<String, Map<Long, List<baselink>>>> it = mapMatchingData.localEntries(CachePeekMode.ALL).iterator(); ... }} )
匹配计算完成后写计算结果耗时巨大,进行重构,经过计算和数据并置,让写结果的数据写本地,避免网络传输。 按车辆进行并置,一个car的数据做为1个job计算。 结果:较以前方案,效率提高显著, 但水平扩展效果不佳。缘由:job粒度过细。框架
先根据carID的并置关系,预先分类在同一Ignite实例上计算的car数据,再根据实例CPU核数启动job数。 结果:不论和原程序比较,仍是水平扩展,效果均达预期。分布式
UUID nodeID = ignite.affinity("MapMatchingData").mapKeyToNode(car_key).id();
总结: Ignite这样一个功能全面的内存框架,由java语言开发,部署很是简单,能够说开箱即用。尤为对于java开发人员,简直没有学习成本,借用官方的说法,Spark用于大数据处理,而Ignite则用于快数据处理。后面,还会写一写Ignite在支持SQL方面的表现,敬请关注。ide