高并发分布式系统中生成全局唯一(订单号)Id js返回上一页并刷新、返回上一页、自动刷新页面 父页面操作嵌套iframe子页面的HTML标签元素 .net判断System.Data.DataRow中是否包含某列 .Net使用system.Security.Cryptography.RNGCryptoServiceProvider类与System.Random类生成随机数

时间:2021-11-11 22:11:26

高并发分布式系统中生成全局唯一(订单号)Id

1、GUID数据因毫无规律可言造成索引效率低下,影响了系统的性能,那么通过组合的方式,保留GUID的10个字节,用另6个字节表示GUID生成的时间(DateTime),这样我们将时间信息与GUID组合起来,在保留GUID的唯一性的同时增加了有序性,以此来提高索引效率,在NHibernate中,COMB型主键的生成代码如下所示:

高并发分布式系统中生成全局唯一(订单号)Id  js返回上一页并刷新、返回上一页、自动刷新页面  父页面操作嵌套iframe子页面的HTML标签元素  .net判断System.Data.DataRow中是否包含某列  .Net使用system.Security.Cryptography.RNGCryptoServiceProvider类与System.Random类生成随机数
        /// <summary>
        /// 保留GUID的10个字节,用另6个字节表示GUID生成的时间(DateTime)组合方式
        /// </summary>
        /// <returns></returns>
        public static Guid GenerateComb()
        {
            byte[] guidArray = Guid.NewGuid().ToByteArray();

            DateTime baseDate = new DateTime(1900, 1, 1);
            DateTime now = DateTime.Now;

            // Get the days and milliseconds which will be used to build
            //the byte string
            TimeSpan days = new TimeSpan(now.Ticks - baseDate.Ticks);
            TimeSpan msecs = now.TimeOfDay;

            // Convert to a byte array
            // Note that SQL Server is accurate to 1/300th of a
            // millisecond so we divide by 3.333333
            byte[] daysArray = BitConverter.GetBytes(days.Days);
            byte[] msecsArray = BitConverter.GetBytes((long)
                (msecs.TotalMilliseconds / 3.333333));

            // Reverse the bytes to match SQL Servers ordering
            Array.Reverse(daysArray);
            Array.Reverse(msecsArray);

            // Copy the bytes into the guid
            Array.Copy(daysArray, daysArray.Length - 2, guidArray,
                guidArray.Length - 6, 2);
            Array.Copy(msecsArray, msecsArray.Length - 4, guidArray,
                guidArray.Length - 4, 4);

            return new Guid(guidArray);
        }
高并发分布式系统中生成全局唯一(订单号)Id  js返回上一页并刷新、返回上一页、自动刷新页面  父页面操作嵌套iframe子页面的HTML标签元素  .net判断System.Data.DataRow中是否包含某列  .Net使用system.Security.Cryptography.RNGCryptoServiceProvider类与System.Random类生成随机数

上述方法循环测试生成id如下图

高并发分布式系统中生成全局唯一(订单号)Id  js返回上一页并刷新、返回上一页、自动刷新页面  父页面操作嵌套iframe子页面的HTML标签元素  .net判断System.Data.DataRow中是否包含某列  .Net使用system.Security.Cryptography.RNGCryptoServiceProvider类与System.Random类生成随机数

结论:适合大型应用。即保留GUID的唯一性的同时增加了GUID有序性,提高了索引效率;解决了关联表业务问题;生成的Id不够友好;占据了32位。

2、将GUID转为了19位数字

高并发分布式系统中生成全局唯一(订单号)Id  js返回上一页并刷新、返回上一页、自动刷新页面  父页面操作嵌套iframe子页面的HTML标签元素  .net判断System.Data.DataRow中是否包含某列  .Net使用system.Security.Cryptography.RNGCryptoServiceProvider类与System.Random类生成随机数
        /// <summary>
        /// 根据GUID获取19位的唯一数字序列
        /// </summary>
        public static long GuidToLong()
        {
            byte[] buffer = Guid.NewGuid().ToByteArray();
            return BitConverter.ToInt64(buffer, 0);
        }
高并发分布式系统中生成全局唯一(订单号)Id  js返回上一页并刷新、返回上一页、自动刷新页面  父页面操作嵌套iframe子页面的HTML标签元素  .net判断System.Data.DataRow中是否包含某列  .Net使用system.Security.Cryptography.RNGCryptoServiceProvider类与System.Random类生成随机数

上述方法循环测试生成id如下图

高并发分布式系统中生成全局唯一(订单号)Id  js返回上一页并刷新、返回上一页、自动刷新页面  父页面操作嵌套iframe子页面的HTML标签元素  .net判断System.Data.DataRow中是否包含某列  .Net使用system.Security.Cryptography.RNGCryptoServiceProvider类与System.Random类生成随机数

结论:适合大型应用,从业务上来说,有一个规则的编码能体现产品的专业成度。

js返回上一页并刷新、返回上一页、自动刷新页面

一、返回上一页并刷新

<a href="javascript:" onclick="self.location=document.referrer;">返回上一页并刷新</a>
<a href="javascript:history.go(-1)">返回上一页</a>
<a href="javascript:location.reload()">刷新当前页面</a>
<a href="javascript:" onclick="history.go(-2); ">返回前两页</a>
<a href="javascript:" onclick="history.back(); ">返回上一页</a> 

二、自动刷新页面

<!-- 10指每隔5秒刷新一次页面  -->
<meta http-equiv="refresh" content="5">

三、页面自动跳转

<!-- 5指隔5秒后跳转到http://www.baidu.com页面 -->
<meta http-equiv="refresh" content="5;url=http://www.baidu.com"> 

四、页面跳转

<a href="javascript:" onclick="window.location.href='test.html'" >js跳转</a> 

五、父子窗口之间的刷新

高并发分布式系统中生成全局唯一(订单号)Id  js返回上一页并刷新、返回上一页、自动刷新页面  父页面操作嵌套iframe子页面的HTML标签元素  .net判断System.Data.DataRow中是否包含某列  .Net使用system.Security.Cryptography.RNGCryptoServiceProvider类与System.Random类生成随机数
//刷新包含该框架的页面用
<script language=JavaScript>
        parent.location.reload();
</script> 

//子窗口刷新父窗口
<script language=JavaScript>
self.opener.location.reload();
</script>
( 或者 <a href="javascript:opener.location.reload()">刷新</a> ) 

//刷新iframe另一个框架的页面用
<script language=JavaScript>
parent.另一FrameID.location.reload();
</script> 
高并发分布式系统中生成全局唯一(订单号)Id  js返回上一页并刷新、返回上一页、自动刷新页面  父页面操作嵌套iframe子页面的HTML标签元素  .net判断System.Data.DataRow中是否包含某列  .Net使用system.Security.Cryptography.RNGCryptoServiceProvider类与System.Random类生成随机数

父页面操作嵌套iframe子页面的HTML标签元素

一个页面A.html使用iframe嵌套一个页面B.html,在A页面写js操作B页面HTML元素,首先要获取到B页面document对象,才能对嵌套页面进行操作

请看一个实例,在A页面写js操作B页面div的内容:

A.html代码:

高并发分布式系统中生成全局唯一(订单号)Id  js返回上一页并刷新、返回上一页、自动刷新页面  父页面操作嵌套iframe子页面的HTML标签元素  .net判断System.Data.DataRow中是否包含某列  .Net使用system.Security.Cryptography.RNGCryptoServiceProvider类与System.Random类生成随机数
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <script type="text/javascript" src="js/jquery-1.9.1.min.js" ></script>
    </head>
    <body >
        <iframe name="iframe1" src="B.html"></iframe>
    </body>
</html>

<script>

        window.onload=()=>{

                $(window.frames["iframe1"].document).on("click","#btn",function(){  //window.frames["iframe1"].document获的iframe标签嵌套页面document对象

                    $(this).html("1123");
                })
        }

</script>
高并发分布式系统中生成全局唯一(订单号)Id  js返回上一页并刷新、返回上一页、自动刷新页面  父页面操作嵌套iframe子页面的HTML标签元素  .net判断System.Data.DataRow中是否包含某列  .Net使用system.Security.Cryptography.RNGCryptoServiceProvider类与System.Random类生成随机数

B页面代码:

高并发分布式系统中生成全局唯一(订单号)Id  js返回上一页并刷新、返回上一页、自动刷新页面  父页面操作嵌套iframe子页面的HTML标签元素  .net判断System.Data.DataRow中是否包含某列  .Net使用system.Security.Cryptography.RNGCryptoServiceProvider类与System.Random类生成随机数
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>

        <script type="text/javascript" src="js/jquery-1.9.1.min.js" ></script>

    </head>
    <body id="body">
        <div id="btn" >测试操作</div>
    </body>
</html>
高并发分布式系统中生成全局唯一(订单号)Id  js返回上一页并刷新、返回上一页、自动刷新页面  父页面操作嵌套iframe子页面的HTML标签元素  .net判断System.Data.DataRow中是否包含某列  .Net使用system.Security.Cryptography.RNGCryptoServiceProvider类与System.Random类生成随机数

当点击 “测试操作” 时就这个文字就被修改成“1123”

.net判断System.Data.DataRow中是否包含某列

大家对将DataRow转成实体对象并不陌生,转成实体的时候一般都会加上这个判断  if (row["字段名"] != null && row["字段名"].ToString() != "") ,这个写法会存在一个问题,当row不存在这个字段时就会抛出异常,导致程序崩溃,这种情况在数据库频繁地修改出现的频率高,因为修改数据库时,代码里面转成实体的方法就不适用了,基于业务的不同可能存在多个转成实体的方法,这样修改数据库时,并修改代码的同时很容易遗漏修改,导致程序崩溃,特别是需求经常变动的项目(改数据库)。所以个人建议在判断里面加多一个逻辑条件:

 if (row.Table.Columns.Contains("字段名") && row["字段名"] != null && row["字段名"].ToString() != "")   //row.Table.Columns.Contains("字段名") 是判断row中是否存在该字段,存在返回true,否则返回 false

这个逻辑条件可以避免当row不存在该字段是出现的错误。

代码例子

实体类:

高并发分布式系统中生成全局唯一(订单号)Id  js返回上一页并刷新、返回上一页、自动刷新页面  父页面操作嵌套iframe子页面的HTML标签元素  .net判断System.Data.DataRow中是否包含某列  .Net使用system.Security.Cryptography.RNGCryptoServiceProvider类与System.Random类生成随机数
1     public class User
2     {
3         public int UserId { get; set; }
4         public string UserName { get; set; }
5         public int Age { set; get; }
6     }
高并发分布式系统中生成全局唯一(订单号)Id  js返回上一页并刷新、返回上一页、自动刷新页面  父页面操作嵌套iframe子页面的HTML标签元素  .net判断System.Data.DataRow中是否包含某列  .Net使用system.Security.Cryptography.RNGCryptoServiceProvider类与System.Random类生成随机数

转成实体类方法:

高并发分布式系统中生成全局唯一(订单号)Id  js返回上一页并刷新、返回上一页、自动刷新页面  父页面操作嵌套iframe子页面的HTML标签元素  .net判断System.Data.DataRow中是否包含某列  .Net使用system.Security.Cryptography.RNGCryptoServiceProvider类与System.Random类生成随机数
 1             User userModel=new User();
 2             if (row.Table.Columns.Contains("UserId") && row["UserId"] !=null && row["UserId"].ToString() !="")
 3             {
 4                 userModel.UserId = Convert.ToInt32(row["UserId"]);
 5             }
 6             if (row.Table.Columns.Contains("UserName") && row["UserName"] != null && row["UserName"].ToString() != "")
 7             {
 8                 userModel.UserId = Convert.ToInt32(row["UserName"]);
 9             }
10             if (row.Table.Columns.Contains("Age") && row["Age"] != null && row["Age"].ToString() != "")
11             {
12                 userModel.UserId = Convert.ToInt32(row["Age"]);
13             }
14             return userModel;
15         }
高并发分布式系统中生成全局唯一(订单号)Id  js返回上一页并刷新、返回上一页、自动刷新页面  父页面操作嵌套iframe子页面的HTML标签元素  .net判断System.Data.DataRow中是否包含某列  .Net使用system.Security.Cryptography.RNGCryptoServiceProvider类与System.Random类生成随机数

.Net使用system.Security.Cryptography.RNGCryptoServiceProvider类与System.Random类生成随机数

.Net中我们通常使用Random类生成随机数,在一些场景下,我却发现Random生成的随机数并不可靠,在下面的例子中我们通过循环随机生成10个随机数:

            for (int i = 0; i < 10; i++)
            {
                Random random1 = new Random();
                Console.WriteLine(random1.Next());
            }

测试生成随时基本都是相同的结果:

高并发分布式系统中生成全局唯一(订单号)Id  js返回上一页并刷新、返回上一页、自动刷新页面  父页面操作嵌套iframe子页面的HTML标签元素  .net判断System.Data.DataRow中是否包含某列  .Net使用system.Security.Cryptography.RNGCryptoServiceProvider类与System.Random类生成随机数

很显然上面的结果是不靠谱的,为什么会这样呢,因为微软的Random类,发现在C#中生成随机数使用的算法是线性同余法,这种算法生成的不是绝对随机,而是一种伪随机数,线性同余法算法的的公式是

:第n+1个数 = ( 第N个数 * a + b) % m ,公式中a、b和m分别为常数,是生成随机数的因子,如果之前从未通过同一个Random对象生成过随机数(也就是调用过Next方法),那么第N个随机数为将被指定为一个默认的常数,这个常数在创建一个Random类时被默认值指定,Random也提供一个构造函数允许开发者使用自己的随机数因子.

有人说要将 Random random1 = new Random(); 要放到循环的外面:

            Random random2 = new Random();
            for (int i = 0; i < 20; i++)
            {
                Console.WriteLine(random2.Next());
            }

测试上面的代码执行的结果是这样的:

高并发分布式系统中生成全局唯一(订单号)Id  js返回上一页并刷新、返回上一页、自动刷新页面  父页面操作嵌套iframe子页面的HTML标签元素  .net判断System.Data.DataRow中是否包含某列  .Net使用system.Security.Cryptography.RNGCryptoServiceProvider类与System.Random类生成随机数

得到结果还是不靠谱的

有人说使用GUID产生填充因子:

高并发分布式系统中生成全局唯一(订单号)Id  js返回上一页并刷新、返回上一页、自动刷新页面  父页面操作嵌套iframe子页面的HTML标签元素  .net判断System.Data.DataRow中是否包含某列  .Net使用system.Security.Cryptography.RNGCryptoServiceProvider类与System.Random类生成随机数
            for (int i = 0; i < 20; i++)
            {
                byte[] buffer = Guid.NewGuid().ToByteArray();
                int iSeed = BitConverter.ToInt32(buffer, 0);
                Random random3 = new Random(iSeed);
                Console.WriteLine(random3.Next());
            }
高并发分布式系统中生成全局唯一(订单号)Id  js返回上一页并刷新、返回上一页、自动刷新页面  父页面操作嵌套iframe子页面的HTML标签元素  .net判断System.Data.DataRow中是否包含某列  .Net使用system.Security.Cryptography.RNGCryptoServiceProvider类与System.Random类生成随机数

测试上面的代码得到的结果:

高并发分布式系统中生成全局唯一(订单号)Id  js返回上一页并刷新、返回上一页、自动刷新页面  父页面操作嵌套iframe子页面的HTML标签元素  .net判断System.Data.DataRow中是否包含某列  .Net使用system.Security.Cryptography.RNGCryptoServiceProvider类与System.Random类生成随机数

得到的结果还是不靠谱的。

为了生成更加可靠的随机数,微软在System.Security.Cryptography命名空间下提供一个名为system.Security.Cryptography.RNGCryptoServiceProvider的类,它采用系统当前的硬件信息、进程信息、线程信息、系统启动时间和当前精确时间作为填充因子,通过更好的算法生成高质量的随机数,它的使用方法如下所示:

高并发分布式系统中生成全局唯一(订单号)Id  js返回上一页并刷新、返回上一页、自动刷新页面  父页面操作嵌套iframe子页面的HTML标签元素  .net判断System.Data.DataRow中是否包含某列  .Net使用system.Security.Cryptography.RNGCryptoServiceProvider类与System.Random类生成随机数
            for (int i = 0; i < 20; i++)
            {
                byte[] randomBytes = new byte[8];
                System.Security.Cryptography.RNGCryptoServiceProvider rngServiceProvider = new System.Security.Cryptography.RNGCryptoServiceProvider();
                rngServiceProvider.GetBytes(randomBytes);
                int result = BitConverter.ToInt32(randomBytes, 0);
                result = System.Math.Abs(result);  //求绝对值
                Console.WriteLine(result);
            }
高并发分布式系统中生成全局唯一(订单号)Id  js返回上一页并刷新、返回上一页、自动刷新页面  父页面操作嵌套iframe子页面的HTML标签元素  .net判断System.Data.DataRow中是否包含某列  .Net使用system.Security.Cryptography.RNGCryptoServiceProvider类与System.Random类生成随机数

测试结果未发现重复的:

高并发分布式系统中生成全局唯一(订单号)Id  js返回上一页并刷新、返回上一页、自动刷新页面  父页面操作嵌套iframe子页面的HTML标签元素  .net判断System.Data.DataRow中是否包含某列  .Net使用system.Security.Cryptography.RNGCryptoServiceProvider类与System.Random类生成随机数

总结:

Random算法简单,性能较高,适用于随机性要求不高的情况,由于RNGCryptoServiceProvider在生成期间需要查询上面提到的几种系统因子,所以性能稍弱于Random类,但随机数质量高,可靠性更好。使用哪一种方式视情况而定