一种基于B+树的ETC收费系统用户卡状态名单存取方法与流程

文档序号:32654984发布日期:2022-12-23 21:14阅读:28来源:国知局
一种基于B+树的ETC收费系统用户卡状态名单存取方法与流程
一种基于b+树的etc收费系统用户卡状态名单存取方法
技术领域
1.本发明涉及一种数据写入和检索方法,尤其涉及一种基于b+树的高速公路用户卡状态名单存取方法,属于智能交通领域。


背景技术:

2.自2015年9月28日,全国高速公路电子不停车收费实现全国联网,用户实现一卡畅行全国,全国31个(省)(直辖市)(自治区),全部实现了高速公路etc联网收费,实现全国高速公路etc联网通行,用户在任意省份办理etc通行卡,即可通行全国。
3.随着etc卡发行量的增加,因用户注销、卡遗失、欠费停用等原因被添加用户状态的用户卡信息也随之增加。截至2022年5月,全国etc用户卡状态名单数量已达4450万。
4.用户卡状态名单包含以下主要属性:
5.1)用户卡号:40字节长度的字符串,用于用户卡的唯一标识;
6.2)状态名单创建时间:时间类型,用于标识该状态名单的发布时间;
7.3)状态名单生效时间:时间类型,用于标识该状态名单的生效时间;
8.4)操作类型:整数类型,用于标识该状态名单的操作类型,如卡注销、余额不足等;
9.5)操作状态:整数类型,用标识该状态名单的处理状态,如进入黑名单、解除黑名单;
10.6)发行方:12字节长度的字符串,用于标识该用户卡所属发行单位。
11.在用户卡状态名单的设计中允许同一张卡存在多个状态,最终的用户状态由多个状态合并。在etc收费系统中,为了保证车辆的快速通行,系统处理各环节的处理时效性要求极高。
12.目前,为了确保etc收费系统的处理效率,用户卡状态名单采用内存加载结合hash查找的方式实现。单个用户卡状态名单存储需要使用92字节——用户卡号40字节+状态名单创建时间8字节+状态名单生效时间8字节+操作类型4字节+操作状态4字节+发行方12字节+对象描述符8字节+8字节的hash码。因此,加载4450万名单共需要3.8g内存空间。使用hash表查询算法需要计算用户卡号的hash值,对于4450万用户卡状态名单,计算hash值并加载到内存需要耗时20分钟左右。
13.因此,在etc收费系统中使用内存加载结合hash查找实现用户状态存取方法存在以下弊端:
14.1)内存占用较大
15.etc收费系统除用户卡状态名单外还存在其他需要加载到内存的运行数据,增加内存的使用会提升etc收费系统的建设成本;同时较大的内存占用不利于软件常态化运作的管理,在运维场景下高内存的占用降低了系统的健壮性和鲁棒性。
16.2)hash算法存在hash碰撞,造成不同的用户卡号被计算为相同的hash值,hash碰撞的存在需要重新设计hash跳表来确保相同hash值下不同用户卡号的映射关系,提升了软件代码的复杂度,降低了系统的健壮性。
17.3)加载耗时需要20分钟以上的现状也对etc收费系统快速运作、高效运转的要求带来较大的挑战。
18.综上所述,在用户卡状态名单存取场景下,使用内存加载结合hash表的方法很难达到满意的效果。


技术实现要素:

19.本发明要解决的技术问题是:在etc收费系统中使用内存加载结合hash查找实现用户状态存取方法存在内存占用较大、软件代码复杂度高以及加载耗时的缺陷。
20.为了解决上述技术问题,本发明的技术方案是提供了一种基于b+树的etc收费系统用户卡状态名单存取方法,其特征在于,包括以下步骤:
21.第一步、将用户卡状态名单转化为单链数据结构dictionary实例,其中,链数据结构dictionary包括用于记录用户卡号的key字段、用于记录用户卡状态信息的value字段以及用于存储指向其它单链数据结构dictionary实例的指针的next字段;
22.第二步、在写入用户卡状态名单时,对于当前单链数据结构dictionary实例的处理包括以下步骤:
23.步骤1、获得当前单链数据结构dictionary实例的key字段的值key,查找与当前用户卡槽对应的b+树实例中各叶子节点的key数组每个key元素值:
24.若在当前key数组中存在等于值key的key元素值,则将等于值key的key元素值定义为当前key元素值,进入步骤6;
25.若在当前b+树实例中未查找到等于值key的key元素值,但在当前key数组中存在小于值key的key元素值,则将与当前key数组对应的叶子节点作为当前叶子节点,进入步骤3;
26.若在当前b+树实例中未查找到小于等于值key的key元素值,则进入步骤2;
27.步骤2、新建叶子节点,将新建的叶子节点作为当前叶子节点,进入步骤3;
28.步骤3、判断当前叶子节点是否已满:若当前叶子节点已满,则分裂当前叶子节点,将分裂得到的叶子节点作为新的当前叶子节点,进入步骤4;若当前叶子节点未满,则直接进入步骤4;
29.步骤4、将值key作为一个key元素值存入当前叶子节点的key数组中,并对key数组中所有key元素值重组排序,获得重组排序后值key在当前key数组中的排序序号k,进入步骤5;
30.步骤5、新建第k个value数组,依据当前单链数据结构dictionary实例的next字段,在第k个value数组的对应位置存入当前单链数据结构dictionary实例;
31.步骤6、获取当前key元素值所对应的value数组及其中存储的第一个单链数据结构dictionary实例,将该单链数据结构dictionary实例定义为上一个单链数据结构dictionary实例,进入步骤7;
32.步骤7、若上一个单链数据结构dictionary实例的next字段为空,则将上一个单链数据结构dictionary实例的next字段指向当前单链数据结构dictionary实例,在当前单链数据结构dictionary实例存入当前value数组中,且当前单链数据结构dictionary实例在当前value数组中的位置位于上一个单链数据结构dictionary实例之后;若上一个单链数
据结构dictionary实例的next字段非空,则进一步获得单链数据结构dictionary实例的next字段指向的下一个单链数据结构dictionary实例,将所获得的下一个单链数据结构dictionary实例定义为新的上一个单链数据结构dictionary实例后,返回步骤7循环执行;
33.在查询查询用户卡状态名单时,在b+树实例中进行查询。
34.优选地,第一步中,进行用户卡状态名单转化时,将用户卡号的前n个字符截取作为用户卡槽,同一用户卡槽对应一个b+树实例,则用户卡号前四位相同的数据聚合在一个b+树中;
35.第二步中,在查询查询用户卡状态名单时,先将用户卡号前n个字符截取,命中与其对应的用户卡槽的b+树实例,然后在该b+树实例中进行查询。
36.优选地,用户卡号为长度20的数字字符串,则取用户卡号的前4个字符作为卡槽标记,用户卡号的后16字符为用户卡标记,将用户卡标记转为long类型,将卡槽标记及转为long类型的用户卡标记存储在所述key字段中。
37.优选地,所述value字段仅用于记录用户卡状态信息中的状态生效时间、操作类型和操作状态,且使用计算状态生效时间+操作状态*10+操作类型得到长度所得到的15位的long值类型数据存储在所述value字段中。
38.相较于内存加载结合hash表的存取方法,本发明提供的一种基于b+树的用户卡状态名单存取方式取消了hash计算操作,解决因hash碰撞造成的数据冲突。本发明引入用户卡槽的聚合模型,对相同槽下的b+树可以实现并发写入,极大地提升数据写入性能,加载完成4450万用户卡状态名单耗时仅需110秒。结合b+树的存取特性,将用户卡状态名单单条记录压缩到28字节,全量加载完仅需1.16g内存空间,有效的降低了etc收费系统的建设成本,提升了系统的健壮性和鲁棒性。在查询效率方面,采用本发明提供的技术方案后,单记录命中耗时不到1ms,相较于hash查找算法耗时略有增加,但依然能够满足etc收费系统的高效运作。
附图说明
39.图1示意了b+树在用户卡状态名单场景下的应用;
40.图2示意了数据写入流程;
41.图3示意了b+树在用户卡状态名单存取方法。
具体实施方式
42.下面结合具体实施例,进一步阐述本发明。应理解,这些实施例仅用于说明本发明而不用于限制本发明的范围。此外应理解,在阅读了本发明讲授的内容之后,本领域技术人员可以对本发明作各种改动或修改,这些等价形式同样落于本技术所附权利要求书所限定的范围。
43.本发明提供的一种基于b+树的etc收费系统用户卡状态名单存取方法包括用户卡状态名单转化以及用户卡状态名单的存取。
44.一)用户卡状态名单转化
45.用户卡状态名单本质上是描述用户卡状态信息的,本发明设计了一个单链数据结构dictionary用于存储用户卡状态信息。每个用户卡状态名单都被转化为一个单链数据结
构dictionary实例。
46.本发明中,链数据结构dictionary有三个属性字段,分别为key字段、value字段以及next字段,其中:
47.key字段用于记录用户卡号,用户卡号为长度20的数字字符串,utf-8编码时一个字符占用2字节共计40字节,取字符串前4个字符作为卡槽标记,在存储时相同卡槽标记的用户卡号会聚合在一个b+树中,无需存储卡槽信息;后16长度字符串为用户卡标记,在64位操作系统中long值取值范围为-9223372036854774808~9223372036854774807,将用户卡标识转为long类型存储,长度为8个字节;
48.value字段用于记录用户卡状态信息,用户卡状态信息中状态生效时间、操作类型和操作状态三个属性是主要属性;发行方信息是包含在用户卡号中,无需存储;名单创建时间主要用于校验延迟,无需存储;因此仅存储这三个属性。状态生效时时间是一个时间戳,长度13位的long值,操作类型是长度1位的int值,操作状态是长度1位的int值,使用计算状态生效时间+操作状态*10+操作类型得到长度15位的long值,占用8字节;
49.next字段,是一个指向其它单链数据结构dictionary实例的指针,长度为4字节。
50.基于上文定义,链数据结构dictionary可以表示为:
[0051][0052]
因此,在本发明中,一个单链数据结构dictionary实例占用空间为28个字节——key字段8字节、value字段8字节、next字段4字节、对象描述符8字节。
[0053]
为每个用户卡状态名单构建一个单链数据结构dictionary实例,构建时,将用户卡号的前4个字符截取作为用户卡槽,同一用户卡槽对应一个b+树实例,则用户卡号前四位相同的数据聚合在一个b+树中,以此降低单个b+树过大引发性能瓶颈。
[0054]
二)用户卡状态名单的存取
[0055]
在写入用户卡状态名单时,对于当前单链数据结构dictionary实例的处理包括以下步骤:
[0056]
步骤1、获得当前单链数据结构dictionary实例的key字段的值key,查找与当前用户卡槽对应的b+树实例中各叶子节点的key数组每个key元素值:
[0057]
若在当前key数组中存在等于值key的key元素值,则说明当前用户卡号存在多个用户卡状态名单,将等于值key的key元素值定义为当前key元素值,进入步骤6;
[0058]
若在当前b+树实例中未查找到等于值key的key元素值,但在当前key数组中存在小于值key的key元素值,则将与当前key数组对应的叶子节点作为当前叶子节点,进入步骤3;
[0059]
若在当前b+树实例中未查找到小于等于值key的key元素值,则进入步骤2;
[0060]
步骤2、新建叶子节点,将新建的叶子节点作为当前叶子节点,进入步骤3;
[0061]
步骤3、判断当前叶子节点是否已满:若当前叶子节点已满,则分裂当前叶子节点,
将分裂得到的叶子节点作为新的当前叶子节点,进入步骤4;若当前叶子节点未满,则直接进入步骤4;
[0062]
步骤4、将值key作为一个key元素值存入当前叶子节点的key数组中,并对key数组中所有key元素值重组排序,获得重组排序后值key在当前key数组中的排序序号k,进入步骤5;
[0063]
步骤5、新建第k个value数组,依据当前单链数据结构dictionary实例的next字段,在第k个value数组的对应位置存入当前单链数据结构dictionary实例;
[0064]
步骤6、获取当前key元素值所对应的value数组及其中存储的第一个单链数据结构dictionary实例,将该单链数据结构dictionary实例定义为上一个单链数据结构dictionary实例,进入步骤7;
[0065]
步骤7、若上一个单链数据结构dictionary实例的next字段为空,则将上一个单链数据结构dictionary实例的next字段指向当前单链数据结构dictionary实例,在当前单链数据结构dictionary实例存入当前value数组中,且当前单链数据结构dictionary实例在当前value数组中的位置位于上一个单链数据结构dictionary实例之后;若上一个单链数据结构dictionary实例的next字段非空,则进一步获得单链数据结构dictionary实例的next字段指向的下一个单链数据结构dictionary实例,将所获得的下一个单链数据结构dictionary实例定义为新的上一个单链数据结构dictionary实例后,返回步骤7循环执行。
[0066]
在查询查询用户卡状态名单时,先将用户卡号前4个字符截取,命中与其对应的用户卡槽的b+树实例,然后在该b+树实例中进行查询。
当前第1页1 2 
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1