Azure Cache for Redis  ASP.NETでの使用方法、注意点

今回はAzure Web Service(以下Web Server)からAzure Redis(以下Redis)にデータを読み書きします。
その際の注意点や、ベストプラクティスとして紹介されているアプローチを紹介したいと思います。

# 簡単にRedisの概要
・KeyとValueの組み合わせでデータを保存できるDB。
・読み書きがとても速い。
・データの保存期間を設定できるので時限式で消せる。
・Get,Set,Update,Sortなど単純な機能を持っている。
・永続させたいデータの保存には使用できない。(再起動で消える)
・ただのミドルウェア(自由にダウンロードできるので、ローカルにもRedisServerを立てれます)


# 利用を考えている方にまず知らせたいこと
・ほかのAzureサービスと比べて価格設定が高め。
キャッシュさせたいものにもよりますが、DBの性能にお金を出したほうが良い場合もあると思います。
(私はキャッシュしたいものが認証情報だけだったので、最終的にDBにお金を出しました。。)

キャッシュするデータ、量、Redisの機能で判断していただければと思います。

・すぐ始められる、使い方や設定がすごく簡単、機能が単純なのでハマるポイントが少ない（べた褒め）

・スケールアップに（途中でプランを上げる）再起動が必要
運用途中で性能を上げるためにはサービスのダウンタイムが発生してしまう。
（これはシャード構成にしておけば、解決できるものなのかもしれない）

# AzureポータルからRedisの作成
作成時の注意としてWeb ServerとRedisは同じリージョンに配置します。
公式より引用
>最大限のパフォーマンスと最短の待機時間を実現するには、キャッシュ クライアント アプリケーションと同じリージョンに Azure Cache for Redis を配置します。

選ぶプランの指標ですが、
基本的なことは価格表と説明を見てもらって、私が疑問に思った部分だけ補足します。

Redis価格表
https://azure.microsoft.com/ja-jp/pricing/details/cache/

・クライアント接続の数
今回のクライアントはWeb Serverになります。
なのでRedisに接続するクライアント数はWeb Serverのインスタンス数になります(実際にはそれより少しだけ多いです。)
Web Serverは最大10インスタンスなので最小の256で足りますね。

実際に私はWeb Server１台からRedisを使っていたのですが、接続数を確認したところ最大13コネクションがありました。
多分Azureの監視系のサーバーやコンソールのカウントだと思うのですが、確信がないです。

・ネットワーク帯域
認証情報を扱うぐらいなら「低」で問題なかったです。
１秒間に7KBでネックになることはなかったですが、大きいデータを扱う際には先に検証してみることをお勧めします。

# 実装前に環境設定をします。

### Redisの接続文字列を設定します。

ポータルからRedisを開きサブメニューを概要とアクセスキーから
urlとキーを確認します。

Web.configにRedisへの接続文字列を追加します。

```Web.config
<appSettings>
    <add key="CacheConnection" value="概要のURL.redis.cache.windows.net:6380,abortConnect=false,ssl=true,allowAdmin=true,password=アクセスキー"/>
</appSettings>
```
ソース上にキー情報を置きたくない場合は、Azureポータル上に置くこともできます。
置き場所は、ポータル＞App Service＞構成＞新しいアプリケーション設定を追加
キーと値に上記と同じ内容を入れて保存。
※保存した際にサーバーが再起動します。

どちらに配置してもコード上からの参照方法は変わりません。

### Redisを扱うためのパッケージをインストールします

「StackExchange.Redis」をNugetパッケージマネージャでインストールします。


### 以上の設定を使って実際の使い方を示します。

以下のコードだけでRedisの接続部分はできます。
これは公式で推奨された書き方で、すべてのRedis接続は同じインスタンスを介すようにします。

```C#
private static Lazy<ConnectionMultiplexer> lazyConnection = new Lazy<ConnectionMultiplexer>(() =>
{
    // Web.configに設定してもポータル上の場合でも、ConfigurationManagerで取得できます。
    string cacheConnection = ConfigurationManager.AppSettings["CacheConnection"];
    return ConnectionMultiplexer.Connect(cacheConnection);
});

public static ConnectionMultiplexer Connection
{
    get
    {
        return lazyConnection.Value;
    }
}
```

実際にRedisにGet,Setしてみます。

```C#
var cacheKey = "Redis_Key_Name";
// Redisにはシリアライズしたオブジェクトも入れることができます。
var cacheValue = "Allow_Content_SerializeObject";

// Connectionはどこから参照してもOKな、スレッドセーフになっています。
IDatabase cache = Connection.GetDatabase();

// Redisに値をセットします。(Key, Value, 保存期間、 Set動作の詳細)
cache.StringSet(cacheKey, cacheValue, TimeSpan.FromMinutes(5), When.Always);

// Redisの値をゲットします。非同期もできます。StringGetAsync,StringSetAsync
RedisValue value = cache.StringGet(cacheKey);
if (value.IsNullOrEmpty)
{
    return null;
}
// 保存期間の再セットです。
cache.KeyExpire(cacheKey, TimeSpan.FromMinutes(5));
```

あとはデプロイして試してみてください。
次に実際にRedisに値が入ったかを確認する方法を記します。

# Redisにコンソールからアクセス

Redisコンソールにアクセスして、Keyを操作してみましょう。
Azureポータルから入るパターンと、ローカルのcmdからアクセスするパターンがあります。

Azureポータルからは簡単には入れます、Redisの中にSSHのタブがあったとおもうので、そこからアクセスできると思います。（うろ覚えでごめんなさい）
色々とコマンドを試してください。

cmdから入る方法は公式をチェックでおねがいします。。。
https://docs.microsoft.com/ja-jp/azure/azure-cache-for-redis/cache-how-to-redis-cli-tool

### 

# 負荷試験をした際に躓いたこと。
負荷試験を行ったところRedisのタイムアウトが頻発しました。
Redisのプランを上げても解決しなかったので、しばらく原因がわからなかったのですが、
Web ServerのCPUが100%になってたので、Web Serverのプランを上げたところRedisのタイムアウトがなくなりました。
腑に落ちなかったので調べたところ、公式に記載がありました。

>Redis クライアントでのメモリ不足
https://docs.microsoft.com/ja-jp/azure/azure-cache-for-redis/cache-troubleshoot-client

クライアントの性能が足りないと、Redisが即時にレスポンスを返しても、受け取ることができずにRedisのタイムアウトが発生するとのことです。
Web Serverが悪いのにRedisのせいされててかわいそう。

# 最後に
Redis自体は本当に早いと思います。
プランのネットワーク帯域についてはもっと言及された記載があるとうれしいですね。