资金网络场景下如何设计图谱

  • nebula 版本:3.4.0
  • 部署方式:分布式
  • 安装方式:RPM
  • 是否上生产环境:Y
    计划从hive导入数据生成资金网络图谱,两个账户节点间每个方向的边只能有一条,怎样能合理地表示多笔交易关系呢,有没有在这个场景下应用的大牛帮忙提提建议~~

可以参考 rank,用 rank 来标识每笔交易:INSERT EDGE - NebulaGraph Database 手册 参考边插入语法中的 rank 说明。

我也想提这个问题,资金场景下交易是动态增长的,无法确定单条交易与rank的对应关系,如果关系rank设计为跟节点vid一样可以使用string标识就可以解决;
我现在是通过增加一个交易节点来解决这个问题,交易节点的vid使用该条交易的唯一标识,比如发送方–接收方–交易时间–交易金额去创建string vid或者hash成vid;但是这种解决方案存在很大的弊端,就是直接将节点数与关系数直接翻倍,比如原来10个用户间有100条交易只需要创建10个节点以及100条关系即可,使用上述方案需要额外多创建100个中间节点以及100条边,严重影响查询效率!大概测试了下真实数据,使用这种方案节点数是原来的20倍关系数是原来的10+倍

1 个赞

你可以把交易时间做为 rank,rank 支持 64 位 int,可以把交易时间转成 timestamp 存进去

正常很少有这么合理的交易情况存在;
比如微信红包同一个交易单号会产生多条交易,交易时间、交易金额、付款方都是相同的,但是收款金额、收款方、收款时间是不同的;还有中情况是,有人给发了两个红包如有收款账号用了红包助手有极大概率会产生收款时间相同的情况,交易时间都是交易机构(微信、支付宝等)返回的精度基本都是秒很难规避精度不足造成的数据覆盖;
再比如牵扯商品订单的交易还存在退款以及部分退款的问题交易单号、交易双方、交易时间也是同一个交易金额可能不同;买了多个商品合并订单支付的情况下,交易双方交易时间基本都是强一致的,实际情况中很难通过单一字段解决rank值唯一的问题;

多笔交易的交易单号是一样的吗?这个比较好奇。我理解,不同的交易应该都有一个唯一标识 吧?不然如何区分是一笔还是多笔,不是系统出错呢

交易确实只有一个标识就是交易单号,但具有多个状态,创建、接收、退款等都是对同一个交易单号进行操作;对于发红包的来说有且只有一个单号他只支付了一笔钱一个交易时间,但是对于群红包的来说就有n个状态每个人抢红包的金额时间都不同,这n个状态同属于一笔交易。
有个比较直观的例子就是,同时从不同卖家买了几件不同的商品,然后一起付款就会看到只有一条订单编号但是钱肯定是去了不同的卖家手里

是否可以这么考虑:

  1. 群红包或者是一个订单到不同的卖家,起点和终点是不一样的;
  2. 同一笔订单的不同交易操作(创建/接收/退款)可以使用不同的edge type;

这样的话,就能保证起点、重点、 edge type、rank(交易单号)是唯一的

理论上是可行的,问题就在于交易单号并不一定是一个数字……有的是全数字的并且特别长,比如:1000050101190402031209000110126838106718;有的类似十六进制包含字母,比如:2017050159068ACEFADD08E0E10080002821020D001;
所以其实rank只要支持string类型就可以比较好的解决我遇到的相关问题

可以考虑下把那一串做 hash,然后 hash 的结果做 rank。
hash 冲突我觉得概率比较小,尤其是还要考虑起点+终点+类型+rank。这个冲突概率应该是非常非常低

我们已经做hash了,但是hash转10进制int类型rank超长了;

hash是个好方法但rank只能使用int没办法原生支持,如果hash转int类型rank对我们已有功能以及各数据库间数据统一都会造成相当程度的影响,毕竟资金数据很多都已经是比较久远的了

不是很理解,我们的 rank 值可以存 8 个字节。

rank虽然可以存8个字节(64位)但是数据类型是int,值范围为2^64在 -9,223,372,036,854,775,808 到9,223,372,036,854,775,807 ,如果存1000050101190402031209000110126838106718这种订单号很显然已经超出范围了,如果存2017050159068ACEFADD08E0E10080002821020D001这种订单号除了超出范围还需要额外增加转纯数字的逻辑,如果使用hash比较基础的md5也会产生32位16进制(128位)也超长了;
当然我们也可以使用比较简单的hash算法,但是这就需要我们在旧数据库(mysql、es)中增加这一字段,很显然这很困难且不安全,否则我就无法直接获取某条交易与rank值的对应关系;在查询过程中如果我仅使用LOOKUP就必须指定rank值,如果不在旧数据库中存储rank值,就需要在代码各处都使用这种逻辑才能推算出某一条交易的rank值,继而才能查到该边;

其实形而上一点说就是,两点之间本就该存在无数种关系,每种关系也应该存在无数种可能;但是rank的出现比较反逻辑,数据库设计可以有上限要求但不应该把这种限制直接暴露给用户操作,如果将关系rank设计为类似于主键允许用户自定义值类型,只要总数不超出上限更符合逻辑;
还有个问题就是既然允许悬挂边的存在,那就说明并不强制边的结构;如果不允许悬挂边才需要强制要求边结构;但是rank的存在既增加了用户使用难度以及理解难度,又允许悬挂边的存在,可能于我来说比较比较蹩脚。

嗯嗯,关于 rank 的设计在后续的版本已经调整了,类似于主键的设置,定义某个属性为 rank

另外,rank 的目的就是为了区分平行边的场景。不过现在3.x的 rank 值是完全有用户决定的,且有长度限制,用起来相对麻烦点。

此话题已在最后回复的 7 天后被自动关闭。不再允许新回复。