2012-11-09 37 views
0

我正在用ASP.NET C#和MySQL构建自己的分片解决方案。对于每一行的Id我使用下面的:从代码中提取长号码中的三个数字

  • 碎片ID - 诠释(1-65535)
  • 表类型ID - 小整数(1-65535)
  • 增量编号(1 - 4294967295)

因此,例如,一个ID应该在URL这样的:

http://mywebsite.com/folders/65535655354294967297 

我想知道的是如何将数字组合成一个大N近似所以我可以稍后提取数据。因此,例如,我不会使用1作为分片ID,我可能需要给您00001,因为稍后通过对整数进行除法可以更容易地提取该数字。

那么我该怎么做,建立一个具有三个独立数值的长数然后能够将它们提取回代码的最佳方法是什么?

我寻找最有效的方式做它在C#中

感谢。

+0

是否有任何理由不让每个人都放在URL的单独部分,例如http://mywebsite.com/folders/65535/65535/4294967297 –

+0

是的,对于massy,脸谱,pinterest和所有的大牌球员使用很长的数字,而不是在像文件夹,所以我只是跟随趋势,它看起来更好在我看来 –

回答

1

可以使用的六角represantations数字

ushort ShardId=1; 
ushort TableTypeId = 100; 
uint IncrementalNumber = 1000; 

string url = ShardId.ToString("X4") + TableTypeId.ToString("X4") 
            + IncrementalNumber.ToString("X8"); 

var i1 = Convert.ToUInt16(url.Substring(0, 4), 16); 
var i2 = Convert.ToUInt16(url.Substring(4, 4), 16); 
var i3 = Convert.ToUInt32(url.Substring(8, 8), 16); 

OR

string url = (((ulong)ShardId << 48) | ((ulong)TableTypeId << 32) | IncrementalNumber) 
      .ToString("X16"); 

var u = Convert.ToUInt64(url,16); 
var i1 = (ushort)(u >> 48); 
var i2 = (ushort)((u >> 32) & 0xffff); 
var i3 = (uint)(u & 0xffffffff); 
+0

有趣,让我检查一下。它在性能方面是有效的? –

+0

我需要一个函数来获取这样的字符串:“00001000020000000015”,并分别返回[1,2,15]的数组(例如:1是分片ID,2是表类型ID,15是增量)。在上面的例子中,你可以看到这些数字以小数形式嵌入到字符串中) –

2

你几乎在你的问题中描述了答案。为每个数字定义一个固定的宽度。

int iShardId = 12; // Fixed width of 5 
int iTableTypeId = 840; // Fixed width of 5 
long lIncremental = 967295; // Fixed width of 10 

string sMyId = String.Concat(iShardId.ToString("00000"), iTableTypeId.ToString("00000"), lIncremental.ToString("0000000000")); 

然后,您可以稍后解析字符串(通过IHttpModule的或其他)使用正则表达式:

RegEx rMyText = new RegEx(@"/(?<shard>[0-9]{5})(?<table>[0-9]{5})(?<inc>[0-9]{10})/?$"); 
Match mMyValues = rMyText.Match(Request.Url.AbsolutePath); 

if (mMyValues.Success) { 
    int iShardId = Convert.ToInt32(mMyValues["shard"].Value); 
    int iTableTypeId = Convert.ToInt32(mMyValues["table"].Value); 
    long lIncremental = Convert.ToInt64(mMyValues["inc"].Value); 
} 
else { 
    //The input didn't match 
} 

正则表达式的目的是作为一个样本来分析的数字,但很明显,这取决于你如何规划为了实现,你应该调整它,以确保输入被限制为你期望的值,通过使用开始/结束斜线或字符串结尾($)。

+0

我看到了使用左移动位的解决方案。所以我只是想知道,这是做这件事的最好方式,我是否会遇到某种问题,我不知道。 –

+0

这是最聪明的做法。任何通过二元分解获得的效率都只会让你的应用程序难以置信地变得复杂,因为接下来的任何人都可以使用它。 –

+0

我在这里要小心 - 将输入作为'int' /'long'可以让某个人传递太长的值,并且如果有超过20位的数字,那么'regex'不会失败结果字符串,所以你会得到不同的值。 – Rawling

0

几个选项,大致从最长(最可读的?)至最短(最小可读)

  • 垫每个数字用零到最长也可能是(00001000010000000001
  • 独立的带有连字符的号码,甚至斜杠(1-1-11/1/1
  • 结合你的两个ushort S和uintulong并在URL把
  • 合并八个字节到一个数组,Base64编码,并把在URL

我会用第二个去 - 这可能将是最短的大部分时间,是最有人情味可读。

1

解决方案可能是使用二进制数字并将它们附加在一起形成一个数字。

  • 碎片ID - 诠释(1-65535)
  • 表类型ID - 小整数(1-65535)
  • 增量编号(1 - 4294967295)

的Shard Id和Table Id都需要16位,而增量数需要16位。这意味着您可以用64位来表示数据。

实施例:

碎片ID

12月:7

滨:0000 0000 0000 0111

表类型ID

12月:2435

滨:0000 1001 1000 0011

增量数

12月:23456457

滨:0001 0110 0101 1110 1010 1100 1001

最终数目

的毗连的二进制值如

碎片ID +表型的id +增量数

滨:0000 0000 0000 0111 0000 1001 1000 0011 0000 0001 0110 0101 1110 1010 1100 1001

12月:1980783105796809

+0

这个解决方案是不必要的复杂的,我很确定反序列化这个值很容易弥补序列化过程中获得的性能。 –

+0

我记得Pinterest用他们的解决方案进行了位移,所以我认为位移是性能上最快的 –

+0

如果这是10年前,或者您的网站的流量真的像Pinterest一样多,那么我会说它会值得考虑。 –