Client programming c#

์ด๋ฒˆ์—๋Š” redis์˜ sentinel์„ client์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

redis standalone ์‚ฌ์šฉํ•˜๊ธฐ

cd standalone
docker-compose up -d

๋‚ด ์ปดํ“จํ„ฐ์— 6379 ํฌํŠธ๋กœ redis๊ฐ€ ์‹คํ–‰๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

์ด์ œ c# ์ฝ”๋“œ๋ฅผ ๋งŒ๋“ค์–ด ๋ณด์ž.

https://redis.io/docs/connect/clients/dotnet/ ์ฐธ๊ณ ํ•œ๋‹ค.

dotnet add package NRedisStack
using Microsoft.AspNetCore.Mvc;
using NRedisStack;
using NRedisStack.RedisStackCommands;
using StackExchange.Redis;

namespace ThreadTest.Controllers;

[ApiController]
[Route("values")]
public class ValuesController : ControllerBase
{
    private readonly ILogger<ValuesController> _logger;

    public ValuesController(ILogger<ValuesController> logger)
    {
        _logger = logger;
    }

    [HttpGet]
    public OkResult Get()
    {
        ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost");
        IDatabase db = redis.GetDatabase();

        System.Console.WriteLine(db.Database.ToString());

        db.StringSet("foo", "bar");
        Console.WriteLine(db.StringGet("foo")); // prints bar


        return Ok();
    }
}
...

curl http://localhost:5007/value

![alt text](images/sentinel-client/image.png)

bar๋ฅผ ์ฐ๋Š”๊ฑธ ๋ณผ์ˆ˜์žˆ๋‹ค ๋กœ์ปฌ์— ์žˆ๋Š” ๋ ˆ๋””์Šค์— ์ €์žฅ์ด ๋˜๊ณ  ๊ทธ ๊ฐ’์„ ๊ฐ€์ ธ์˜จ๊ฒƒ์ด๋‹ค.

cli๋กœ ํ™•์ธํ•ด๋ณด์ž.

```sh
docker run -it --rm bitnami/redis:7.2 redis-cli -h host.docker.internal -p 6379

get foo

๊ฒฐ๊ณผ๊ฐ€ ์ž˜ ๋‚˜์˜จ๋‹ค.

foreach (EndPoint endpoint in redis.GetEndPoints())
{
    Console.WriteLine(endpoint.ToString());
}

์ด ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ด์„œ ์‹คํ–‰ํ•ด๋ณด์ž.

Unspecified/localhost:6379

์ด๋ผ๋Š” ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์˜จ๋‹ค.

redis replica(main-secondary) ์‚ฌ์šฉํ•˜๊ธฐ

cd replica-multi-node
docker-compose up -d
docker ps

๋ชจ๋“  ๋…ธ๋“œ๋ฅผ ,๋กœ ๊ตฌ๋ถ„ํ•ด์„œ ๋„ฃ์–ด์ฃผ๋ฉด ๋œ๋‹ค.

ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost:6379,localhost:6380,localhost:6381");
if (redis == null) return Ok();
if (!redis.IsConnected) return Ok();

IDatabase db = redis.GetDatabase(); //database 0 ์„ ์‚ฌ์šฉํ•œ๋‹ค.

Console.WriteLine(db.Database.ToString());

db.StringSet("foo1", "bar1");

Console.WriteLine(db.StringGet("foo")); // prints bar

์ž๋™์œผ๋กœ master๋ฅผ ์•Œ์•„๋‚ด์„œ ๊ทธ๊ณณ์—๋‹ค ๋ฐ์ดํ„ฐ๋ฅผ ์ž…๋ ฅ์‹œ์ผœ์ค€๋‹ค. ์ฝ๊ธฐ๋Š” ์ž๋™์œผ๋กœ secondary์—์„œ ์ฝ์–ด์˜จ๋‹ค.

database๋Š” 0๋ฒˆ์ด๊ณ  ๊ฐ’์€ bar์ด๊ณ  endpoint๋Š” localhost:6379์ด๋‹ค.

replica์—์„œ ํ™•์ธํ•ด๋ณด์ž.

docker run -it --rm bitnami/redis:7.2 redis-cli -h host.docker.internal -p 6380

replica์—์„œ๋„ ๊ฐ’์ด ์ž˜ ์ž…๋ ฅ๋˜์žˆ๋‹ค.

db๋ฅผ ์„ ํƒํ•˜์ง€

  • ๋ ˆ๋””์Šค ์„œ๋ฒ„๋Š” ์—ฌ๋Ÿฌ๊ฐœ์˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋‹ค.

  • ๊ธฐ๋ณธ ๊ฐ’์€ 16์ด๋‹ค.

  • DB ๋ฒˆํ˜ธ 0๋ถ€ํ„ฐ 15๊นŒ์ง€ 16๊ฐœ์˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ๊ฐ–๋Š”๋‹ค.

  • ํ™•์ธํ•˜๋Š”๋ฒ•

CONFIG GET databases
INFO keyspace

๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์„ ํƒํ•˜๋Š” ๋ฐฉ๋ฒ•

SELECT 1

code์—์„œ db๋ฅผ ์„ ํƒํ•˜๋Š” ๋ฐฉ๋ฒ•

IDatabase db = redis.GetDatabase(); // 0๋ฒˆ์„ ๋ฆฌํ„ด

// 1๋ฒˆ์„ ์‚ฌ์šฉํ•˜๋ ค๋ฉด
IDatabase db = redis.GetDatabase(1); //database 1 ์„ ์‚ฌ์šฉํ•œ๋‹ค.

redis sentinel ์‚ฌ์šฉํ•˜๊ธฐ

cd sentinel
docker-compose up -d

sentinel์€ service name์ด๋ผ๋Š” ๊ฒƒ์ด ์žˆ๋‹ค ํ™•์ธํ•ด๋ณด์ž.

docker run -it --rm bitnami/redis-sentinel:7.2 redis-cli -h host.docker.internal -p 26379
info sentinel
> master0:name=mymaster,status=ok,address=172.30.0.2:6379,slaves=4,sentinels=3

mymaster๊ฐ€ ์ด๋ฆ„์ด๋‹ค.

connection string์— ์„œ๋น„์Šค ์ด๋ฆ„์„ ์ง€์ •ํ•˜๋ฉด sentinel ๋ชจ๋“œ๊ฐ€ ์‹คํ–‰

var sentinelConfig = new ConfigurationOptions
{
    AllowAdmin = false,
    AbortOnConnectFail = false,
    CommandMap = CommandMap.Sentinel,
    EndPoints =
        {
            "host.docker.internal:26379",
            "host.docker.internal:26380",
            "host.docker.internal:26381"
        },
};

var masterConfig = new ConfigurationOptions
{
    CommandMap = CommandMap.Default,
    ServiceName = "mymaster",
};

var redis = ConnectionMultiplexer.SentinelConnect(sentinelConfig, Console.Out);

var conn = redis.GetSentinelMasterConnection(masterConfig, Console.Out);
var db = conn.GetDatabase(0);

db.StringSet("foo2", "bar2");

Console.WriteLine(db.StringGet("foo")); // prints bar

redis.Close();

๋™์ž‘ํ•œ๋‹ค.

redis cluster ์‚ฌ์šฉํ•˜๊ธฐ

string connectString = "host.docker.internal:6371,host.docker.internal:6372,host.docker.internal:6373,host.docker.internal:6374,host.docker.internal:6375,host.docker.internal:6379";
var options = ConfigurationOptions.Parse(connectString);
var redisCluster = ConnectionMultiplexer.Connect(options);

IDatabase db = redisCluster.GetDatabase();
db.StringSet("foo3", "bar3");

Console.WriteLine(db.StringGet("foo3")); // prints bar3
redisCluster.Close();

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋™์ž‘ํ•œ๋‹ค.

todo

  • ์ผ๋ฐ˜์ ์œผ๋กœ ์ด๋ ‡๊ฒŒ ์ฝ”๋”ฉํ•˜๋Š”๋ฐ ์ด๋Ÿฌ๋ฉด connection์„ ๋งค๋ฒˆ ๋งบ๋Š”๋‹ค. ๋ฌธ์ œ๊ฐ€ ๋œ๋‹ค.

  • ๊ผญ Async๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ๋ฐ”๋ž€๋‹ค.

์ฐธ๊ณ 

connection string์— ์“ธ์ˆ˜ ์žˆ๋Š” ์ถ”๊ฐ€ ์˜ต์…˜๋“ค

https://stackexchange.github.io/StackExchange.Redis/Configuration#configuration-options

Last updated