VB.NET循环生成随机参考ID在Web服务器出现重复值如何解决?
问题诱因
你猜测的情况完全正确,问题根源如下:
- .NET 中
Random类的默认无参构造函数依赖系统时钟生成随机种子,而系统时钟的分辨率通常只有10~15毫秒。本地调试时因为有调试断点、运行开销,两次函数调用的间隔超过时钟分辨率,每次new的Random实例种子不同,所以生成的随机序列不同;但服务器上循环执行速度极快,多次调用GenerateRandomString的间隔小于时钟分辨率,导致连续创建的多个Random实例拿到了相同的种子,最终生成完全一致的随机字符串,出现批量重复的refID。 - 附加潜在问题:当前随机字符串生成函数的循环条件为
i As Integer = 0 To length Step 1,最终返回的字符串长度会比传入的length参数多1位;同时函数要求生成的字符串无重复字符,当传入的length超过字符集总长度(当前字符集共62个字符)时会进入死循环。
解决方案
下面给出3种可行方案,可根据业务需求选择:
方案1:修改Random实例为静态(成本最低)
将Random实例改为类的静态成员,避免每次调用函数都重新创建实例,同时加锁保证线程安全(Web环境多线程并发场景下Random非线程安全)。
修正后的代码示例:
' 帮助类中定义静态Random实例和锁对象 Private Shared ReadOnly objRandom As New Random() Private Shared ReadOnly randomLock As New Object() Public Shared Function GenerateRandomString(ByVal length As Integer) As String Dim chara As Char() = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".ToCharArray() Dim randomString As New StringBuilder(length) SyncLock randomLock ' 加锁保证线程安全 For i As Integer = 1 To length ' 修正循环边界,避免多生成1位 Dim x As Integer = objRandom.Next(0, chara.Length) ' 原代码从1开始会永远取不到第一个字符'0',此处做了修正 ' 若无特殊要求可删除字符去重逻辑,既提升性能也避免长字符串场景死循环 randomString.Append(chara(x)) Next End SyncLock Return randomString.ToString() End Function
方案2:直接使用GUID生成唯一ID(最稳妥)
如果不需要严格限制ID的字符规则,直接使用GUID生成参考ID是最简单且完全保证唯一性的方案,不需要自己处理随机逻辑:
For Each i In myListOfNames ' 生成32位无分隔符的唯一ID,也可通过调整ToString参数更换输出格式 refID = Guid.NewGuid().ToString("N") Dim x As New BasketItem x.RefID = refID myListOfItems.Add(x) Next
方案3:使用加密随机数生成器(安全性最高)
如果对ID的不可预测性有要求,使用.NET提供的加密级随机数生成器,完全避免种子重复问题,同时安全性远高于普通Random:
Public Shared Function GenerateRandomString(ByVal length As Integer) As String Dim chara As Char() = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".ToCharArray() Dim result As New StringBuilder(length) Dim rng As RandomNumberGenerator = RandomNumberGenerator.Create() Dim buffer(3) As Byte For i As Integer = 1 To length rng.GetBytes(buffer) Dim num As UInteger = BitConverter.ToUInt32(buffer, 0) Mod chara.Length result.Append(chara(CInt(num))) Next Return result.ToString() End Function
内容的提问来源于stack exchange,提问作者Jimmy
相关产品推荐
相关产品推荐

