How to implement random number stream over high traffic asp.net application with multiple servers

This question comes from the knowledge that when new Random()

called very quickly, it gets a seed with the same value that I believe is based on DateTime.Now.Ticks

.

Suppose you had a high traffic web application in the latest ASP.NET, IIS, .NET, etc. that online casinos implement. I would think that simulated slot machines should extract random numbers from a single stream.

With a high volume situation, you might end up with two slot machines with the same random number generator, triggering too many big jackpots. I don't have a complete understanding of pseudo-random generators, but my intuition is that for a safe online casino implementation, you really need to pull from one generator that is seeded only once.

One solution I can think of is a single thread synchronized queue that pushes numbers, but I don't know how to keep it synchronized in a multi-site application.

Is there a good / standard solution for this scenario?

Update: The actual scenario I'm working on (which really doesn't stand a chance of getting enough scope to cause the problem)

My real situation is that I have a medium high traffic asp.net web forms site and a requirement to show one of two custom controls for every request. I did it with the following code:

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

      

If I unit test the above code by calling it in quick succession it fails and I figured out that the reason was because it new Random()

was being called on the same "tick".

However, I believe my current implementation is sufficient (feel free to correct me), but I was curious how it could be solved if I really wanted to be strict about it ...

+3


source to share


3 answers


Just protect the random number generator with a lock. If you don't make hundreds of thousands of calls per second, this will be fast enough.

public class MyRandomObject
{
    private readonly Random _rnd = new Random();

    public int Next()
    {
        lock (_rnd)
        {
            return _rnd.Next();
        }
    }
}

      

Before you say "locks are too slow", please note that I tested this on a 2.4GHz quad core. It took about 70 nanoseconds to get the random number when the lock was not resolved. Lock conflicts can cause performance degradation, but you will need a lot of queries.



In a web application, you want to initialize one of them in Application_Start

and make that singleton available to the rest of your application.

There are faster ways, but they are more difficult to implement. One way would be to generate millions of random numbers (call Random.NextBytes

) and store them in a buffer. Protect this with a read / write lock. When the number of remaining values ​​reaches some threshold, the thread acquires the write lock, preventing all others until it refills the buffer. This is probably how you want it if you use a different source of random numbers. For example, the method RNGCryptoServiceProvider.GetBytes

( http://msdn.microsoft.com/en-us/library/system.security.cryptography.rngcryptoserviceprovider.getbytes.aspx ).

+2


source


Create one static instance Random

. Evict him by creating 4 cryptographically secure random bytes. You can even make this instance Random

[ThreadLocal]

to remove all locks.



I don't know why the BCL does not contain such a thing and automatically uses it to seed new instances. It's that easy to do, provides perfect seeding, and scales well for any number of threads.

0


source


See Generating random numbers with C ++ TR1 for details and an example from the Tunf casino page . The same article also explains how to use the built-in generators to create generators for four common distributions not included in the library: Cauchy, Chi-square, Student t, and Snedecor F.

0


source







All Articles