这个问题来自这样的知识,即当 new Random()
被非常快速地调用时,它会被植入相同的值,我假设它是基于 DateTime.Now.Ticks
.
假设您在最新版本的 ASP.NET、IIS、.NET 等上有一个高流量的 Web 应用程序,它实现了一个在线赌场。我认为模拟老虎机需要从单个随机数流中提取。
在高交易量的情况下,您可能会得到两台具有相同随机数生成器的老虎机,从而导致累积奖金过多。我对伪随机生成器没有完全的了解,但我的直觉是,要安全地实现在线赌场,您确实需要从只播种一次的单个生成器中提取数据。
我能想到的一个解决方案是使用单个线程的同步队列来推送数字,但我不知道如何在多站点应用程序中同步它。
对于这种情况是否有好的/标准的解决方案?
更新:我正在处理的实际场景(实际上没有机会获得足够的音量来引起问题)
我的真实情况是,我有一个流量适中的 asp.net 网站,并且要求在每个请求上显示两个用户控件之一。我使用以下代码这样做:
// Randomly display one of (FreeCreditScore1, MyFreeScoreNow1)
private void ShowCreditScoreAd()
{
FreeCreditScore1.Visible = (new Random().Next(2) == 1);
MyFreeScoreNow1.Visible = !FreeCreditScore1.Visible;
}
如果我通过快速连续调用上面的代码来对它进行单元测试,它会失败,我开始明白原因是 new Random()
在同一个“tick”中被调用。
就是说,我确实相信我当前的实现已经足够(随时纠正我)但我很好奇如果我真的想对其严格控制,如何解决它......
最佳答案
只是用一把锁来保护随机数生成器。除非您每秒对它进行数十万次调用,否则它已经足够快了。
public class MyRandomObject
{
private readonly Random _rnd = new Random();
public int Next()
{
lock (_rnd)
{
return _rnd.Next();
}
}
}
在您说“锁太慢”之前,请注意我是在一个旧的 2.4 GHz 四核上测试它的。当锁未被竞争时,大约需要 70 纳秒才能获得一个随机数。锁争用会降低性能,但您需要大量请求。
在 Web 应用程序中,您希望在 Application_Start
中初始化其中一个,并使该单例可用于应用程序的其余部分。
有更快的方法,但更难实现。一种方法是预先生成数百万个随机数(调用 Random.NextBytes
)并将它们存储在缓冲区中。用读/写锁保护它。当剩余值的数量达到某个阈值时,线程会获取写入器锁,阻止所有其他访问,直到它重新填充缓冲区。如果您使用其他一些随机数来源,这可能是您想要的方式。例如 RNGCryptoServiceProvider.GetBytes
方法 ( http://msdn.microsoft.com/en-us/library/system.security.cryptography.rngcryptoserviceprovider.getbytes.aspx )。
关于c# - 如何在具有多个服务器的高流量 asp.net 应用程序中实现随机数流,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14971846/