【问题标题】:Can't check key distribution with FNV-1 algorithm无法使用 FNV-1 算法检查密钥分配
【发布时间】:2021-03-01 21:59:55
【问题描述】:

根据很多地方的建议,我正在使用 FNV-1 方法为具有 5 个分区的 Service Fabric 群集生成分区键,如下所示:

[
  {
    "lowKey": -5534023222112865000,
    "highKey": -1844674407370955300,
    "id": "92b4c32e-cb3c-432f-aea0-4579fc72850c",
    "kind": 2
  },
  {
    "lowKey": 5534023222112865000,
    "highKey": 9223372036854776000,
    "id": "dd9b084d-88fa-4773-94d9-f634d22a2c03",
    "kind": 2
  },
  {
    "lowKey": -9223372036854776000,
    "highKey": -5534023222112865000,
    "id": "d7322e52-cf1e-47c2-b713-e983f443b533",
    "kind": 2
  },
  {
    "lowKey": -1844674407370955300,
    "highKey": 1844674407370955300,
    "id": "dfe2f994-bdc7-4b32-b54f-78a0245e4c4c",
    "kind": 2
  },
  {
    "lowKey": 1844674407370955300,
    "highKey": 5534023222112865000,
    "id": "6ad81ffb-5f3c-48ba-91d9-e65b23c528a4",
    "kind": 2
  }
]

我想检查我的数据分布情况。

但是,我不知道该怎么做,因为数字太大了。

我假设我必须为此使用 LowKey="-9223372036854775808" HighKey="9223372036854775807"?

如果是这样,这些数字太大/太小,我无法在 SQL 或 C# 中处理(C# 因为常量太大)。

有没有办法解决这个问题?如果我尝试将这些值保存在我的数据库中,我会遇到溢出问题。

我使用的是 SQL Server 2017。

DECLARE @tbl TABLE(LowKey BIGINT, HighKey BIGINT, TotalITems INT)

INSERT INTO @tbl(LowKey, HighKey, TotalITems) VALUES (5534023222112865000, 9223372036854776000, 0)
INSERT INTO @tbl(LowKey, HighKey, TotalITems) VALUES (-9223372036854776000, -5534023222112865000, 0)

INSERT INTO @tbl(LowKey, HighKey, TotalITems) VALUES (-5534023222112865000, -1844674407370955300, 0)
INSERT INTO @tbl(LowKey, HighKey, TotalITems) VALUES (-1844674407370955300, 1844674407370955300, 0)
INSERT INTO @tbl(LowKey, HighKey, TotalITems) VALUES (1844674407370955300, 5534023222112865000, 0)

前两行因错误而失败

Msg 8115, Level 16, State 2, Line 168
Arithmetic overflow error converting expression to data type bigint.

这是我用来查看分区的逻辑:

[ActionName("GetPartitions")]
public async Task<ActionResult> GetPartitionsAsync()
{
   var result = new List<ServicePartitionInformation>();
   ServicePartitionList partitions = await FabricClient.QueryManager.GetPartitionListAsync(FullServiceName).ConfigureAwait(false);

   foreach (var partition in partitions)
   {
       result.Add(partition.PartitionInformation);
   }

   return new JsonResult(result);
}

保罗

【问题讨论】:

    标签: c# azure hash azure-service-fabric service-fabric-stateful


    【解决方案1】:

    Service Fabric 可以使用 UniformInt64Partition。这意味着最低低 -9223372036854775808 和最高高 9223372036854775807。

    你可以检查使用

    Console.WriteLine(long.MinValue);
    Console.WriteLine(long.MaxValue);
    

    所以你的 json 不正确。例如,-9223372036854776000 不是有效的 long/Int64 值。

    我假设我必须为此使用 LowKey="-9223372036854775808" HighKey="9223372036854775807"?

    如果是这样,这些数字对我来说太大/太小了,我无法在 SQL 或 C# 中处理(C# 因为常量太大)

    不可能,这些是基于 Int64 的有状态服务的默认设置。

    <Service Name="Stateful1" ServicePackageActivationMode="ExclusiveProcess">
      <StatefulService ServiceTypeName="Stateful1Type" TargetReplicaSetSize="[Stateful1_TargetReplicaSetSize]" MinReplicaSetSize="[Stateful1_MinReplicaSetSize]">
        <UniformInt64Partition PartitionCount="[Stateful1_PartitionCount]" LowKey="-9223372036854775808" HighKey="9223372036854775807" />
      </StatefulService>
    </Service>
    

    当我针对新的默认有状态服务运行您的代码时,我得到了

    [
        {
            "LowKey": 5534023222112865485,
            "HighKey": 9223372036854775807,
            "Id": "ef982303-dd13-49f0-ad3c-5de7428eccad",
            "Kind": 2
        },
        {
            "LowKey": -1844674407370955161,
            "HighKey": 1844674407370955161,
            "Id": "e2e5f51b-d3f5-4381-b7ff-6267124d0adb",
            "Kind": 2
        },
        {
            "LowKey": -5534023222112865484,
            "HighKey": -1844674407370955162,
            "Id": "4715db41-124a-4eee-b5b9-2587256ed6e1",
            "Kind": 2
        },
        {
            "LowKey": -9223372036854775808,
            "HighKey": -5534023222112865485,
            "Id": "10e9d445-53e0-4f27-9434-0ea5621ac188",
            "Kind": 2
        },
        {
            "LowKey": 1844674407370955162,
            "HighKey": 5534023222112865484,
            "Id": "687c1c4d-9fc1-4574-a916-66ac5ebfed25",
            "Kind": 2
        }
    ]
    

    如您所见,您的 highkey 9223372036854776000 和 lowkey -9223372036854776000 无效,不在我生成的 json 中。不知道那是从哪里来的。

    我要重现的代码:

        protected override async Task RunAsync(CancellationToken cancellationToken)
        {
            var result = new List<ServicePartitionInformation>();
            ServicePartitionList partitions = await new FabricClient().QueryManager.GetPartitionListAsync(Context.ServiceName).ConfigureAwait(false);
    
            foreach (var partition in partitions)
            {
                result.Add(partition.PartitionInformation);
            }
    
            var info = JsonConvert.SerializeObject(result);
            Console.WriteLine(info);
        }
    

    【讨论】:

    • 是的,除了我没有 ServicePackageActivationMode="ExclusiveProcess" 位之外,它与您所拥有的相匹配 - 我可以补充一点,我不确定是否需要它
    • hiNo,这不是必须的。让我试着重现这个。
    • @Paul 我无法重现此内容,请参阅更新答案。您可以尝试添加一个新的有状态服务并针对该服务运行代码吗?
    • 我同意,如果我在我的服务中使用你的代码,我会得到这些分区。但我不能使用这个原理。我有一个网关服务,它负责计算分区然后进行调用。所以不知道现在该去哪里?
    • 好的,我删除了所有内容并再次执行此操作,现在我确实找到了匹配项:) 我想我会将其标记为答案 - 我可以通过使用 FLOAT 而不是 BIGINT 来解决数据库方面的问题。我知道 float 存在精度问题,但这些数字不是小数,所以应该可以吗?
    猜你喜欢
    • 2015-08-30
    • 1970-01-01
    • 2015-06-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-11
    相关资源
    最近更新 更多