高并发帐户查询怎么做?

简介: 高并发帐户查询怎么做?

一、项目场景


  高并发帐户查询的应用场景有很多,例如:手机银行查流水、电商系统查购物订单、手游帐户查充值记录等等。这些场景一般会涉及众多帐户,数据总量非常大,需要外存。每个帐户的数据量通常不大(几条到几千条),而且就是简单查询,几乎没有什么运算。不过,众多的帐户自然也会有大量、高频率的查询,并发访问量会很大,要达到秒级甚至更高的响应速度也是一个不小的挑战。


       在SQL数据库或数据仓库中,用索引查找单个帐户数据的速度很快,几乎感觉不到耗时,但并发很多时就会有明显延迟了。这是因为,基于无序集合理解的关系数据库不能保证数据在存储时的次序,也就无法保证同一帐户数据在物理上连续存放,查找一个帐户数据时,可能要到硬盘的很多位置读取才能全部取出。而硬盘有最小读取单位,在读取不连续数据时,会取出很多无关内容,查询就会变慢。虽然每个帐户数据量很少,单个帐户查询的时候只是慢一点,但是高并发访问的每个查询都慢一点,总体性能就会很差了。


       因为关系数据库的表现不如人意,所以搜索引擎Elastic Search经常会被用来应对这种场景,即把数据导出到ES里,利用搜索技术实现高性能并发查询。使用ES后,通常确实可以达到期望的性能要求,但遗憾的是ES对JOIN支持非常差,如果查询过程中还涉及关联计算,就会造成巨大的麻烦。比如帐户交易明细表,要和用户表、商品表、网点表等等关联,使用ES时通常只能将这些数据全都整合到交易表中形成大宽表。准备这个大宽表的过程费时费力,还会丧失很多灵活性;而且ES的数据导入非常慢,会进一步加剧这个问题。使用大宽表后无法在关联数据发生变动时简单追加写入,只能重新准备新的宽表再重新导入,耗时很长,这期间只能暂停查询服务。用ES解决高并发帐户查询只能说是一个权宜之计。


二、解决方案


开源数据计算引擎SPL支持有序存储,可以保证数据按照帐户物理有序存放。高并发查找时,SPL的索引可以迅速、精确定位到指定帐号的外存存储位置;有序存储技术则保证同一帐号的数据在物理上连续存储在一片区域中,不需要跳动读取。两者配合,可以让高并发帐户查询达到极致性能。


       另外,高并发场景要选择行式存储,而不是很多数据仓库鼓吹的列存方案。这是因为,行存时一条记录的各个字段数据在物理上是连续存放的,才能保证同一帐户的所有数据存在一处。而列存时,则是各列数据连续存放,一个帐户的字段分散在不同的列中,还是会造成硬盘读取不连续数据的情况。特别是有并发任务时,列存造成的硬盘不连续访问程度要比行存严重的多。


       实际上,行存更适合查找,列存则更适合遍历。SPL两者都支持,程序员可以根据计算的需要来自由选择。有些数据仓库做成了透明机制,不允许用户自由选择行存和列存,就很难达到最佳效果了。        


三、示例代码


SPL有序行存加索引的代码也很简单,比如,从数据库导出数据,生成有序行存的帐户交易表和索引的代码大致是这样:


connect("db").cursor@d("select * from detail order by id")
file("detail.ctx").create@r(#id,ddate,amt,…)
A3.append@i(A2)
A3.index(index_id;id)
>A3.close()

A1连数据库准备取数。A2创建交易明细表,@r代表行存。B2向明细表追加数据,A3给明细表创建索引。


然后,就可以使用生成的明细表和索引进行高速查询:

file("detail.ctx").open().index@3(index_id)
A4.icursor (id,ddate,amt;id==1101004 && …,index_id).fetch()

A4加载明细表的索引,A5利用有序行存表和索引完成查询。

在此基础上,SPL实现JOIN运算也很轻松,多外键关联、多层关联都很容易做到。比如,查询交易明细表时,要关联网点表store,在查询结果中要包含网点名称。代码是下面这样:


file("detail.ctx").open().index@3(index_id)
A4.icursor (id,ddate,amt,sid;id==1101004 && …,index_id).fetch()
file("store.btx").import@b(id,name,...).keys(id)
A5.switch(sid,A6)
A7.new(id,sid.name:sname,amt,ddate)

A6、A7、A8加载网点表,完成内存关联,生成查询结果(包含网点名称)。


由于每个帐户的数据量都不大,所以A7和A8是内存计算,几乎不占用什么时间。


SPL还支持新增数据的快速追加,详情请参考SQL 提速:高并发帐户查询


经过实际测试,在总数据量2亿条,500用户并发查询的场景中,SPL有序行存索引的查询性能可以超过ES。可以看到,SPL性能与ES相当甚至稍快。而SPL对JOIN的支持要好得多,也不存在加载复杂的问题,相比之下,比ES更适合高并发帐户查询场景。


还要注意的是,高并发帐户查询属于查找计算,但有时候系统还要兼顾遍历计算的性能,比如说2月份的帐户交易数据,要按产品分组统计交易总金额、总笔数等。SPL提供了<strong>带值索引</strong>机制,可以同时支持高性能遍历和查找计算。有兴趣的读者可以参考SQL 提速:高并发帐户查询


四、参阅SPL资料


SQL 提速:高并发帐户查询

SPL源代码

目录
相关文章
|
存储 SQL 运维
高并发扛不住、复杂查询慢、数据存不下…别慌,痛点“全扫王” PolarDB-X来了!
2020年6月9日,“全速重构”2020阿里云·线上峰会即将隆重召开。
1231 0
高并发扛不住、复杂查询慢、数据存不下…别慌,痛点“全扫王” PolarDB-X来了!
|
存储 缓存 NoSQL
|
缓存 Memcache
应对Memcached缓存失效,导致高并发查询DB的几种思路
原文地址: http://blog.csdn.net/hengyunabc/article/details/20735701 当Memcached缓存失效时,容易出现高并发的查询DB,导致DB压力骤然上升。
724 0
|
缓存 存储
应对Memcached缓存失效,导致高并发查询DB的四种思路(l转)
当Memcached缓存失效时,容易出现高并发的查询DB,导致DB压力骤然上升。 这篇blog主要是探讨如何在缓存将要失效时,及时地更新缓存,而不是如何在缓存失效之后,如何防止高并发的DB查询。 解决这个问题有四种思路: 比如一个key是aaa,失效时间是30s。
796 0
|
缓存 应用服务中间件 nginx
应对Memcached缓存失效,导致高并发查询DB的几种思路
最近看到nginx的合并回源,这个和下面的思路有点像。不过nginx的思路还是在控制缓存失效时的并发请求,而不是当缓存快要失效时,及时地更新缓存。
725 0
|
6月前
|
消息中间件 Java Linux
2024年最全BATJ真题突击:Java基础+JVM+分布式高并发+网络编程+Linux(1),2024年最新意外的惊喜
2024年最全BATJ真题突击:Java基础+JVM+分布式高并发+网络编程+Linux(1),2024年最新意外的惊喜
|
5月前
|
缓存 NoSQL Java
Java高并发实战:利用线程池和Redis实现高效数据入库
Java高并发实战:利用线程池和Redis实现高效数据入库
474 0
|
3月前
|
监控 算法 Java
企业应用面临高并发等挑战,优化Java后台系统性能至关重要
随着互联网技术的发展,企业应用面临高并发等挑战,优化Java后台系统性能至关重要。本文提供三大技巧:1)优化JVM,如选用合适版本(如OpenJDK 11)、调整参数(如使用G1垃圾收集器)及监控性能;2)优化代码与算法,减少对象创建、合理使用集合及采用高效算法(如快速排序);3)数据库优化,包括索引、查询及分页策略改进,全面提升系统效能。
45 0
|
5月前
|
存储 NoSQL Java
探索Java分布式锁:在高并发环境下的同步访问实现与优化
【6月更文挑战第30天】Java分布式锁在高并发下确保数据一致性,通过Redis的SETNX、ZooKeeper的临时节点、数据库操作等方式实现。优化策略包括锁超时重试、续期、公平性及性能提升,关键在于平衡同步与效率,适应大规模分布式系统的需求。
155 1
|
4月前
|
算法 Java 调度
高并发架构设计三大利器:缓存、限流和降级问题之使用Java代码实现令牌桶算法问题如何解决
高并发架构设计三大利器:缓存、限流和降级问题之使用Java代码实现令牌桶算法问题如何解决