如何在具有多个服务器的高流量asp.net应用程序中实现随机数流

这个问题来自于以下知识:当快速调用new Random()时,它会被赋予相同的值,我假设它基于DateTime.Now.Ticks

假设您在最新版本的ASP.NET,IIS,.NET等上有一个高流量Web应用程序..它实现了一个在线赌场。 我认为模拟的老虎机需要从单个随机数流中提取。

在大容量情况下,您可能会得到两台具有相同随机数发生器的老虎机,导致太多的大奖励。 我没有完全了解伪随机生成器,但我的直觉是,为了安全地实现在线赌场,你真的需要从一个只播种一次的单个生成器中提取。

我能想到的一个解决方案是一个带有单个线程的同步队列,它推送数字,但我不知道如何在多站点应用程序中同步它。

这种情况是否有良好/标准的解决方案?

更新:我正在处理的实际场景(实际上没有机会获得足够的音量来导致问题)

我的真实情况是我有一个适度高流量的asp.net Web表单站点,并且要求在每个请求上显示两个用户控件之一。 我使用以下代码执行此操作:

 // Randomly display one of (FreeCreditScore1, MyFreeScoreNow1) private void ShowCreditScoreAd() { FreeCreditScore1.Visible = (new Random().Next(2) == 1); MyFreeScoreNow1.Visible = !FreeCreditScore1.Visible; } 

如果我通过快速连续调用它来对上面的代码进行unit testing,那么它就失败了,我开始明白原因是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 )。

创建一个静态Random实例。 通过生成4个加密安全随机字节来播种它。 您甚至可以使Random实例[ThreadLocal]删除所有锁定。

我不知道为什么BCL不包含这样的东西并自动使用它来播种新实例。 这很容易做到,提供完美的播种,并完美地扩展到任意数量的线程。