開発ブログ

株式会社Nextatのスタッフがお送りする技術コラムメインのブログ。

電話でのお問合わせ 075-744-6842 ([月]-[金] 10:00〜17:00)

  1. top >
  2. 開発ブログ >
  3. データベース >
  4. DBaaS >
  5. UpstashのRedisに日本リージョンからアクセスした場合のレイテンシ

UpstashのRedisに日本リージョンからアクセスした場合のレイテンシ

upstash-00-site.png

こんにちは、ナカエです。

本日は Upstash に関する記事です。 UpstashはサーバレスRedis、サーバレスKafka、そしてQstashというメッセージングサービスを提供しています。

接続元を問わないマネージドRDBのサービス(DBaaS)は最近色々と出てきていますが、Redisは珍しいです。

個人的には、

  • コンテナ系のフルマネージドサービスやエッジ環境からもVPCを気にせずアクセスできる点
  • Auto Scaleが設定できるので実際のRedisインスタンスをあまり意識しなくても良い点
  • 実行したコマンド数に対する課金のプランを選べる点


などが魅力的だと感じています。

例えばテスト環境や個人の趣味開発の環境でサービスへのアクセス数が少ない場合にRedisにかかる料金が節約できます。

さて、今回はUpstashのRedisにアクセスした際のレイテンシが気になったので調査を行います。

Upstashのブログにて、Latency Comparison Among Serverless Databases: DynamoDB vs FaunaDB vs Upstash | Upstash Blog という記事が公開されており、DynamoDBやFaunaDBとの比較が掲載されています。

upstash-blog-latency.png

低レイテンシにかなりの自信があるようですが、実際に日本のリージョンから使った場合のデータがほしいですね。

Redisデータベースの新規作成

Upstashに新規登録すると管理コンソールにログインできます。 Redis、Kafka、QStashが上部メニューに並んでいますが、今回はRedisのみ見ていきます。

upstash-01-console.png

Create databaseボタンを押すと、新規作成用のモーダルが表示されます。

TypeはRegionalとGlobalの2種類が選べます。

Regionalは1つのリージョンにRedisを配置するタイプです。 AWSのap-northeast-1が利用可能ですが、GCPはus-central-1のみとなっています(2022/03/22現在)。

upstash-02-region-single.png

 

GlobalのWriteはプライマリリージョンのみですが、Read用のレプリカをマルチリージョンに配置できます。 Globalではap-southeast-1が日本からの最寄りになります。

upstash-03-region-global.png

今回はRegionalでap-northeast-1を選び、TLSを有効にします。

upstash-04-create-database.png

作成したRedisのデータベースを確認

upstash-05-2-redis-detail.png

新規作成が完了すると、Redisデータベースの詳細画面を表示できます。

Detailsタブの上部にリージョン、エンドポイント、パスワード、ポートなどの接続情報が記載されているので接続する際にはこちらを利用します。 Connect to your databaseのエリアにそれぞれのCLIツールや言語における接続例が、REST APIのエリアにはREST APIの利用例が掲載されており、非常に親切ですね。

ConfigurationのエリアにはAuto ScaleやSecurity Addonsなどの設定が並びます。 EnterpriseプランであればIPアドレスのホワイトリストやVPC Peeringなどよりセキュアな方法も選択できるようです。

upstash-05-redis-detail.png

Subscriptionのエリアにはプランごとの制限と価格についての情報が記載されています。 Pay as you go のプランでは1000コマンド/秒、同時接続100が上限であり、10万コマンドにつき0.2ドルかかるとのこと。

upstash-07-redis-subscription.png

他にもタブがいくつかありますが、とても使いやすい管理画面だなと思います。

  • Usage: 利用状況のメトリクス
  • CLI: Redisコマンドを実行できるコンソール
  • Data Browser: Redisの中身のデータの確認
  • Backups: Daily Backupなどバックアップの設定
  • Quckstarts: Lambda、Vercel、Cloudflare workersなどのサービス向けのスタートガイド


Usage

upstash-08-usage.png
 

CLI

upstash-09-cli.png

Data Browser

upstash-10-data-browser.png

Backups

upstash-11-backups.png
 

計測の準備

今回選択したRegionはAWSのものであるため、AWSからの接続と他のクラウドプロバイダからの接続で差が出るか気になるところです。

AWS App Runner(ap-northeast-1)とGCPのCloud Run(asia-northeast1)からの接続を試します。

環境

  • PHP 8.2.3
  • phpredis 拡張 5.3.7
  • pack CLI 0.28.0

コンテナイメージ作成の設定

コンテナイメージはHerokuのBuildpackで作成します。

Procfile

web: heroku-php-nginx -C nginx.conf public

nginx.conf

location / {
    try_files $uri @rewriteapp;
}

location @rewriteapp {
    rewrite ^(.*)$ /index.php$1 last;
}

composer.json

{
    "name": "n1215/upstash-latency-test",
    "type": "project",
    "license": "MIT",
    "autoload": {
        "psr-4": {
            "N1215\\UpstashLatencyTest\\": "src/"
        }
    },
    "require": {
        "php": "8.2.3",
        "ext-redis": "5.3.7"
    }
}

project.toml

[project]
id = "upstash-latency"
name = "Upstash Latency Test"
version = "1.0.0"
[build]
exclude = [
    ".idea",
    "/README.md",
    ".git",
    "/vendor"
]
builder = "heroku/buildpacks:20"
[[build.buildpacks]]
uri = "heroku/php"
[[build.buildpacks]]
uri = "heroku/procfile"

計測用のソースコード

時間計測用のクラスを用意します。

src/Timer.php

<?php

declare(strict_types=1);

namespace N1215\UpstashLatencyTest;

class Timer
{
    private array $records = [];

    public function measure(string $key, callable $task): mixed
    {
        $start = hrtime(true);
        $result = $task();
        $end = hrtime(true);

        $milliSec = ($end - $start) / 1e+6;
        $this->records[$key] = $milliSec;

        return $result;
    }

    public function getRecords(): array
    {
        return $this->records;
    }
}

phpredis拡張を利用して、

  • Redisへの接続
  • SET10回
  • GET10回


を実行します。 おおよそどれくらいかを見たいだけなので、平均値や中央値などはあまり気にしないことにします。

なお、今回TLS接続を有効にしていますが、phpredisによるTLS接続はv1.2まで指定しないと上手く動かないようです。

<?php

declare(strict_types=1);

require_once __DIR__ . '/../vendor/autoload.php';

if ($_SERVER['REQUEST_URI'] !== '/latency') {
    echo "OK";
    exit();
}

$config = [
    'host' => getenv('REDIS_HOST') ?? "",
    'port' => (int)(getenv('REDIS_PORT') ?? 6379),
    'password' => getenv('REDIS_PASSWORD'),
    'tls' => true,
];

$timer = new N1215\UpstashLatencyTest\Timer();

$redis = new Redis();
$timer->measure('connect', function () use ($redis, $config) {
    $host = $config['tls']
        ? "tlsv1.2://{$config['host']}"
        : $config['host'];
    $context = $config['password'] !== false
        ? ['auth' => ['pass' => $config['password']]]
        : [];
    $result = $redis->connect(
        $host,
        $config['port'],
        3,
        null,
        0,
        10,
        $context,
    );

    if (!$result) {
        throw new RuntimeException('unable to connect Redis');
    }
});

// 値を生成
$values = [];
for ($i = 0; $i < 10; $i++) {
    $values[] = "bar-" . uniqid();
}

// set
for ($i = 0; $i < 10; $i++) {
    $timer->measure("set-$i", function () use ($redis, $i, $values) {
        $redis->set("foo$i", $values[$i]);
    });
}

// get
for ($i = 0; $i < 10; $i++) {
    $timer->measure("get-$i", function () use ($redis, $i) {
        $redis->get("foo$i");
    });
}

$redis->close();

header('Content-Type: application/json');
echo json_encode($timer->getRecords());
exit();

デプロイ

こちらをApp RunnerとCloud Runにそれぞれデプロイします。

App RunnerはCodeBuildで、Cloud RunはCloud Buildにてそれぞれpack CLIを利用してコンテナイメージの作成を行いました。 詳細は割愛しますが、以前にブログで紹介した方法とほぼ同じです。

参考

計測結果

何度かブラウザで GET /latency を叩いた結果が下記のとおりです。

※ コールドスタート時の値を除く

サービス Redisに接続 SET GET
App Runner 7〜20ms 2〜16ms 0.3〜2.5ms
Cloud Run 10〜28ms 3〜20ms 1.6〜7.4ms


AWS内に配置されているだけあってか、AWSのほうが有意にレイテンシが低くなりました。とはいえ、Cloud Runからのアクセスでもまずまず良好な値です。

まとめ

東京リージョンのApp RunnerとCloud Runから同じリージョンのUpstashのRedisをPHPで利用した場合のレイテンシを計測しました。AWSのほうがレイテンシは低くなりましたが、同じリージョンからであれば十分実用レベルであると感じました。高負荷なサービスでは接続数などの上限に引っかかる場合もありそうですが、今後積極的に活用していきたいところです。

なお、テストにかかったUpstashの料金は$0.01でした。お安いですね。

upstash-12-cost.png

TOPに戻る