# Client programming c\#

이번에는 redis의 sentinel을 client에서 사용하는 방법을 알아보겠습니다.

## redis standalone 사용하기

```sh
cd standalone
docker-compose up -d
```

내 컴퓨터에 6379 포트로 redis가 실행되었습니다.

이제 c# 코드를 만들어 보자.

<https://redis.io/docs/connect/clients/dotnet/> 참고한다.

```sh
dotnet add package NRedisStack
```

````csharp
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
````

![alt text](https://3379277180-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MaoWGMVdC3ztoOAzHPq%2Fuploads%2Fgit-blob-88fb203ac2c2d494469de58ed24477581d4ccd5a%2Fimage-1.png?alt=media)

결과가 잘 나온다.

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

이 코드를 추가해서 실행해보자.

![alt text](https://3379277180-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MaoWGMVdC3ztoOAzHPq%2Fuploads%2Fgit-blob-ebd6cf8921ffd4517ab9e1fbdfe26e1178a285eb%2Fimage-2.png?alt=media)

```
Unspecified/localhost:6379
```

이라는 결과가 나온다.

## redis replica(main-secondary) 사용하기

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

![alt text](https://3379277180-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MaoWGMVdC3ztoOAzHPq%2Fuploads%2Fgit-blob-2ddd11741fa56af50620a17cf6e3271f65e60ecc%2Fimage-3.png?alt=media)

| name        | port |
| ----------- | ---- |
| main        | 6379 |
| secondary-1 | 6380 |
| secondary-2 | 6381 |

모든 노드를 ,로 구분해서 넣어주면 된다.

```cs
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에서 읽어온다.

![alt text](https://3379277180-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MaoWGMVdC3ztoOAzHPq%2Fuploads%2Fgit-blob-63a92d8616ec1177325c26ef52bff7018f4e25f5%2Fimage-4.png?alt=media)

database는 0번이고 값은 bar이고 endpoint는 localhost:6379이다.

replica에서 확인해보자.

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

![alt text](https://3379277180-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MaoWGMVdC3ztoOAzHPq%2Fuploads%2Fgit-blob-fbf61c047e9f26c7a6e159e99878989d9aac1491%2Fimage-5.png?alt=media)

replica에서도 값이 잘 입력되있다.

### db를 선택하지

* 레디스 서버는 여러개의 데이터베이스를 가질 수 있다.
* 기본 값은 16이다.
* DB 번호 0부터 15까지 16개의 데이터베이스를 갖는다.
* 확인하는법

```sh
CONFIG GET databases
INFO keyspace
```

![alt text](https://3379277180-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MaoWGMVdC3ztoOAzHPq%2Fuploads%2Fgit-blob-61825fcbd6ea498cd73098d71ef977c6acc725f5%2Fimage-6.png?alt=media)

데이터베이스를 선택하는 방법

```sh
SELECT 1
```

### code에서 db를 선택하는 방법

```cs
IDatabase db = redis.GetDatabase(); // 0번을 리턴

// 1번을 사용하려면
IDatabase db = redis.GetDatabase(1); //database 1 을 사용한다.
```

## redis sentinel 사용하기

```sh
cd sentinel
docker-compose up -d
```

sentinel은 service name이라는 것이 있다 확인해보자.

```sh
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
```

![alt text](https://3379277180-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MaoWGMVdC3ztoOAzHPq%2Fuploads%2Fgit-blob-bba8a1616b366afa0edc1edc5e3e231c9e5f9db2%2Fimage-7.png?alt=media)

mymaster가 이름이다.

connection string에 서비스 이름을 지정하면 sentinel 모드가 실행

```cs
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();
```

![alt text](https://3379277180-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MaoWGMVdC3ztoOAzHPq%2Fuploads%2Fgit-blob-8cdb00b17f3c14b262fd72eabd83552a87db1770%2Fimage-8.png?alt=media)

동작한다.

## redis cluster 사용하기

```cs
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>
