6

I am developing some web apis in .NET Core 2.2

The requirements brought us to the point where data is stored/cached/centralized within multiple redis storages (for the sake of easiness lets assume 2 redis servers).

That would be (as example)

  1. server 1 for the data protection
  2. server 2 for some other data

So far the data protection seems to work and it was configured using the connection multiplexer (which was added as singleton for reuse before hand) as suggested in the basic usage guide.

The relevant parts of StartUp.ConfigureServices

  ConnectionMultiplexer cm = ConnectionMultiplexer.Connect("server1:6729");
  services.AddSingleton<IConnectionMultiplexer>(cm);

  services.AddDataProtection()
    .SetApplicationName("myapp")
    .PersitKeysToStackExchangeRedis(cm, "DataProtection-Keys");

The keys are stored as expected in the redis storage on server 1.


Now I need to integrate the second storage.

Can a ConnectionMultiplexer used to connect to two servers?

ConnectionMultiplexer cm = ConnectionMultiplexer.Connect("server1:6729;server2:6729"); //?

How to get the correct database pointing to the correct (either 1st or 2nd) server?

2
  • 1
    Are the two different servers used for two different purposes, or are they used for redundancy? Commented Feb 19, 2019 at 13:49
  • They are used for different purposes (in the meaning different storages for different types of data like one for data protection key and one for other data) Commented Feb 19, 2019 at 14:02

2 Answers 2

6

Or just have a Singleton of a ConnectionMultiplexer factory:

public class ConnectionFactory
{
    private Lazy<ConnectionMultiplexer> _cnn1 { get; set; }
    private Lazy<ConnectionMultiplexer> _cnn2 { get; set;}
    public ConnectionFactory(string cnn1, string cnn2)
    {
        _cnn1 = new Lazy<UserQuery.ConnectionMultiplexer>(() => ConnectionMultiplexer.Connect(cnn1));
        _cnn2 = new Lazy<UserQuery.ConnectionMultiplexer>(() => ConnectionMultiplexer.Connect(cnn2));
    }
    public ConnectionMultiplexer GetConnection1()
    {
        return _cnn1.Value;
    }
    public ConnectionMultiplexer GetConnection2()
    {
        return _cnn2.Value;
    }
}

And register like:

var factory = new ConnectionFactory("server1:6379", "server2:6379");
services.AddSingleton(factory);

var cm1 = factory.GetConnection1();
var cm2 = factory.GetConnection2();

....
Sign up to request clarification or add additional context in comments.

Comments

4

The ConnectionMultiplexer can connect to a cluster of servers, but that is only intended for failover / load balancing / replication of the same dataset.

If you just want a logical separation of your keys, Redis has 8 databases internally. You own other storage code can just call _muxer.GetDatabase(3) for example and you can use the same server.

If you have another reason for wanting separate servers I would create a different wrapper class / interface. The wrapper class can new up a ConnectionMultiplexer and be injected in Singleton scope. You end up having 2 instances of the multiplexer, but that is not a big issue, the main thing to avoid is newing up lots of them, for example per call.

public Interface IOtherStorage
{
    void StoreItem(string key, string value);
}

public class OtherStorage : IOtherStorage
{
    private IConnectionMultiplexer _muxer;

    public OtherStorage(string connection)
    {
        _muxer = ConnectionMultiplexer.Connection(connection)
    }

    public void StoreItem(string key, string value)
    {
        _muxer.GetDatabase().StringSet(key, value);
    }
}

And in the startup

services.AddSingleton<IOtherStorage>(c => new OtherStorage("server2:6279");

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.