0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ApsaraDB for MongoDBを使ってみる【事前準備編】

Last updated at Posted at 2024-07-18

overview

Alibaba CloudとMongoDBを触る機会ができたので、試しにいろいろいじってみる。

まずは事前準備としてローカルでMongoDBを触る。

Mongo DBとは

MongoDBはRDBMSではなく、いわゆるNoSQLと呼ばれるデータベースに分類されるものである。RDBMSのようにレコードをテーブルに格納するのではなく、「ドキュメント」と呼ばれる構造的データをJSONライクな形式で表現し、そのドキュメントの集合を「コレクション」として管理する(このデータの物理的な格納はBSONと呼ばれるJSONのバイナリ版といえる形式で行われる)。

引用:Wikipedia

データ構造は以下。

https://storage.googleapis.com/zenn-user-upload/592d71f0a368-20240314.png

引用:公式

MongoDB のストレージ構造は、従来のリレーショナル データベースとは異なります。 MongoDB のデータは次のレベルで編成されます。
ドキュメント: ドキュメントは、MongoDB のデータの基本単位です。ドキュメントは BSON キーと値のペアで構成され、リレーショナル データベースの行に相当します。
コレクション: コレクションには複数のドキュメントが含まれます。リレーショナル データベースのテーブルに相当します。
データベース: データベースには複数のコレクションが含まれます。リレーショナル データベースに相当します。 ApsaraDB for MongoDB インスタンスに複数のデータベースを作成できます。

引用:MongoDBのストレージ構造

  • 多くのプログラミング言語のネイティブデータ型に対応
  • RDBのような多重JOINに陥りにくい
  • 動的スキーマにより振る舞いを変えやすい
    などの利点がある

スケールアウトしやすく、ログ蓄積や軽い読み取りを大量に捌くケースに使う。
ちなみにRedisよりも使われてるらしい。意外。

Redis vs Mongoに関してはAWSが示してくれているので参考になる。
https://aws.amazon.com/jp/compare/the-difference-between-redis-and-mongodb/

水平スケーリングにより、MongoDB は大量のデータを効率的に処理できます。シャーディングを使用して、複数のリージョンとノードにデータを分散します。クロスシャーディング操作では、複数のシャードにわたってクエリと更新を行うことができます。
Redis は MongoDB ほどのスケーラビリティを提供していません。Redis は、プライマリオペレーションにデフォルトでシャードを 1 つだけ使用します。シャーディングはハッシュベースで手動で管理する必要があるため、管理が複雑になります。Redis にはクロスシャード機能もありません。

MongoDB と Redis はどちらも、レプリケーションによる可用性をサポートしています。ただし、MongoDB はレプリカセットを使用することでより高い水準の可用性をサポートします。自動フェイルオーバーメカニズムをサポートしています。
これとは対照的に、Redis はデフォルトでは自動フェイルオーバーを提供しません。特にレプリカが別のデータセンターにある場合は、管理者ユーザーが手動フェイルオーバーを開始します。自動フェイルオーバーが必要な場合は、Redis Sentinel という別のコンポーネントをセットアップして構成する必要があります。

MongoDB は、マルチドキュメントの、原子性、一貫性、独立性、耐久性のある (ACID) トランザクションをサポートしています。そのため、複数の操作でデータの一貫性を保つことができます。MongoDB は、セッション内ですべての変更をコミットまたはロールバックします。これにより、ACID への準拠が確保されます。
逆に、Redis には ACID サポートが組み込まれていません。ただし、MULTI コマンドを使用すると、複数のコマンドを 1 つのアトミック操作にグループ化できます。しかし、これだけでは解決策にはなりません。また、Redis はトランザクション内でロールバック機能をネイティブにサポートしていないため、アプリケーションコード内にロールバック機能を実装する必要があります

MongoDB は、複雑な空間計算やデータ分析機能を実行する場合でも、高い柔軟性でクエリを実行できます。MongoDB は JSON に似た構文をサポートする MongoDB クエリー言語 (MQL) を使用しており、高度なクエリを簡略化します。
これとは対照的に、Redis は複雑なクエリや検索機能ではなく、key-value の高速アクセス操作に最適化されています。

どうやら同じNoSQLでもより可用性があって、データ保持もある程度担保しつつ、リッチな操作ができるのがMongo
アプリ側でデータ抽出を頑張れる&データが揮発性高いのであればRedis
というイメージ。

ただ、AlibabaCloudのApsaraDB for Redisでは以下の点が違うみたい。

Redis は、プライマリオペレーションにデフォルトでシャードを 1 つだけ使用します。シャーディングはハッシュベースで手動で管理する必要があるため、管理が複雑になります。Redis にはクロスシャード機能もありません。

クラスターバージョンでは、自動的にハッシュベースのシャーディングが行われ、各キーはハッシュスロットに割り当てられる。なので、ユーザーは手動でシャーディングを管理する手間を省ける。

Redis はデフォルトでは自動フェイルオーバーを提供しません。特にレプリカが別のデータセンターにある場合は、管理者ユーザーが手動フェイルオーバーを開始します。

master-replicaの構成になり、masterが障害発生する場合は、自動フェールオーバーする。

だから大きな懸念点はなさそう!

やってみる

まずはローカルでPythonからMongo DBに接続するAPIをつくる。

アプリケーション

使用技術スタック

  • Docker
  • Python
  • FastAPI
  • MongoDB
  • pip

ファイル構成

https://storage.googleapis.com/zenn-user-upload/8c7c8932c120-20240317.png

DockerでFastAPIを利用。
公式サンプルをベースに用意。

FROM python:3.10.13

WORKDIR /code

COPY ./app/requirements.txt /code/requirements.txt

RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt

COPY ./app /code/app

docker-composeを利用し、webコンテナとMongoDBコンテナを立てる

services:
  web:
    build: .
    ports:
      - '8000:8000'
    volumes:
      - ./app:/code/app
    command: uvicorn main:app --host 0.0.0.0 --reload
    working_dir: /code/app
  mongo:
    image: mongo
    container_name: mongo
    restart: always
    ports:
      - 27017:27017

requirements.txtを用意

fastapi>=0.68.0,<0.69.0
pydantic>=1.8.0,<2.0.0
uvicorn>=0.15.0,<0.16.0
pymongo

main.pyを用意

from fastapi import FastAPI, Body
from mongo import MongoManager

app = FastAPI()
mongo_manager = MongoManager()

@app.get("/")
def get_all():
    all = mongo_manager.get_all()
    return all

@app.get("/name/{name}")
def get_item(name: str):
    return mongo_manager.get_by_name(name)

@app.post("/name")
def post_name(name: str = Body(...)):
    mongo_manager.add_one(name)
    return "ok"

@app.delete("/")
def delete_all():
    mongo_manager.delete_all()
    return "ok"

mongo.pyを用意

from pymongo import MongoClient

class MongoManager(object):

    def __init__(self):
        self.client = MongoClient('mongodb://mongo')
        self.db = self.client['test']

    def get_all(self):
        """全データ取得"""
        return list(self.db.test.find({}, {'_id': 0}))

    def get_by_name(self, name: str):
        """データ取得"""
        return list(self.db.test.find({"dir": {
            "name": name
        }}, {'_id': 0}))

    def add_one(self, name: str):
        """データ挿入"""
        d = {"name": name}
        data = {
            'title': 'names',
            'dir': d
        }
        return self.db.test.insert_one(data)

    def delete_all(self):
        """全データ削除"""
        self.db.test.delete_many({})

ローカルで起動する

docker-compose upでコンテナを立ちあげると下記ログが出る。

[+] Running 2/0
 ✔ Container python-mongo-web-1    Created                                                           0.0s
 ✔ Container python-mongo-mongo-1  Recreated                                                         0.0s
Attaching to mongo, python-mongo-web-1
mongo               | {"t":{"$date":"2024-03-17T07:53:14.978+00:00"},"s":"I",  "c":"CONTROL",  "id":23285,   "ctx":"main","msg":"Automatically disabling TLS 1.0, to force-enable TLS 1.0 specify --sslDisabledProtocols 'none'"}
mongo               | {"t":{"$date":"2024-03-17T07:53:14.978+00:00"},"s":"I",  "c":"NETWORK",  "id":4915701, "ctx":"main","msg":"Initialized wire specification","attr":{"spec":{"incomingExternalClient":{"minWireVersion":0,"maxWireVersion":21},"incomingInternalClient":{"minWireVersion":0,"maxWireVersion":21},"outgoing":{"minWireVersion":6,"maxWireVersion":21},"isInternalClient":true}}}
mongo               | {"t":{"$date":"2024-03-17T07:53:14.979+00:00"},"s":"I",  "c":"NETWORK",  "id":4648601, "ctx":"main","msg":"Implicit TCP FastOpen unavailable. If TCP FastOpen is required, set tcpFastOpenServer, tcpFastOpenClient, and tcpFastOpenQueueSize."}
mongo               | {"t":{"$date":"2024-03-17T07:53:14.981+00:00"},"s":"I",  "c":"REPL",     "id":5123008, "ctx":"main","msg":"Successfully registered PrimaryOnlyService","attr":{"service":"TenantMigrationDonorService","namespace":"config.tenantMigrationDonors"}}
mongo               | {"t":{"$date":"2024-03-17T07:53:14.981+00:00"},"s":"I",  "c":"REPL",     "id":5123008, "ctx":"main","msg":"Successfully registered PrimaryOnlyService","attr":{"service":"TenantMigrationRecipientService","namespace":"config.tenantMigrationRecipients"}}
mongo               | {"t":{"$date":"2024-03-17T07:53:14.981+00:00"},"s":"I",  "c":"CONTROL",  "id":5945603, "ctx":"main","msg":"Multi threading initialized"}
mongo               | {"t":{"$date":"2024-03-17T07:53:14.981+00:00"},"s":"I",  "c":"TENANT_M", "id":7091600, "ctx":"main","msg":"Starting TenantMigrationAccessBlockerRegistry"}
mongo               | {"t":{"$date":"2024-03-17T07:53:14.982+00:00"},"s":"I",  "c":"CONTROL",  "id":4615611, "ctx":"initandlisten","msg":"MongoDB starting","attr":{"pid":1,"port":27017,"dbPath":"/data/db","architecture":"64-bit","host":"9e7f96999d20"}}
mongo               | {"t":{"$date":"2024-03-17T07:53:14.982+00:00"},"s":"I",  "c":"CONTROL",  "id":23403,   "ctx":"initandlisten","msg":"Build Info","attr":{"buildInfo":{"version":"7.0.6","gitVersion":"66cdc1f28172cb33ff68263050d73d4ade73b9a4","openSSLVersion":"OpenSSL 3.0.2 15 Mar 2022","modules":[],"allocator":"tcmalloc","environment":{"distmod":"ubuntu2204","distarch":"aarch64","target_arch":"aarch64"}}}}
mongo               | {"t":{"$date":"2024-03-17T07:53:14.982+00:00"},"s":"I",  "c":"CONTROL",  "id":51765,   "ctx":"initandlisten","msg":"Operating System","attr":{"os":{"name":"Ubuntu","version":"22.04"}}}
mongo               | {"t":{"$date":"2024-03-17T07:53:14.982+00:00"},"s":"I",  "c":"CONTROL",  "id":21951,   "ctx":"initandlisten","msg":"Options set by command line","attr":{"options":{"net":{"bindIp":"*"}}}}
mongo               | {"t":{"$date":"2024-03-17T07:53:14.985+00:00"},"s":"I",  "c":"STORAGE",  "id":22270,   "ctx":"initandlisten","msg":"Storage engine to use detected by data files","attr":{"dbpath":"/data/db","storageEngine":"wiredTiger"}}
mongo               | {"t":{"$date":"2024-03-17T07:53:14.985+00:00"},"s":"I",  "c":"STORAGE",  "id":22297,   "ctx":"initandlisten","msg":"Using the XFS filesystem is strongly recommended with the WiredTiger storage engine. See <http://dochub.mongodb.org/core/prodnotes-filesystem","tags":["startupWarnings>"]}
mongo               | {"t":{"$date":"2024-03-17T07:53:14.985+00:00"},"s":"I",  "c":"STORAGE",  "id":22315,   "ctx":"initandlisten","msg":"Opening WiredTiger","attr":{"config":"create,cache_size=3413M,session_max=33000,eviction=(threads_min=4,threads_max=4),config_base=false,statistics=(fast),log=(enabled=true,remove=true,path=journal,compressor=snappy),builtin_extension_config=(zstd=(compression_level=6)),file_manager=(close_idle_time=600,close_scan_interval=10,close_handle_minimum=2000),statistics_log=(wait=0),json_output=(error,message),verbose=[recovery_progress:1,checkpoint_progress:1,compact_progress:1,backup:0,checkpoint:0,compact:0,evict:0,history_store:0,recovery:0,rts:0,salvage:0,tiered:0,timestamp:0,transaction:0,verify:0,log:0],"}}
python-mongo-web-1  | INFO:     Will watch for changes in these directories: ['/code/app']
python-mongo-web-1  | INFO:     Uvicorn running on <http://0.0.0.0:8000> (Press CTRL+C to quit)
python-mongo-web-1  | INFO:     Started reloader process [1] using statreload
python-mongo-web-1  | INFO:     Started server process [8]
python-mongo-web-1  | INFO:     Waiting for application startup.
python-mongo-web-1  | INFO:     Application startup complete.
mongo               | {"t":{"$date":"2024-03-17T07:53:15.936+00:00"},"s":"I",  "c":"STORAGE",  "id":4795906, "ctx":"initandlisten","msg":"WiredTiger opened","attr":{"durationMillis":951}}
mongo               | {"t":{"$date":"2024-03-17T07:53:15.936+00:00"},"s":"I",  "c":"RECOVERY", "id":23987,   "ctx":"initandlisten","msg":"WiredTiger recoveryTimestamp","attr":{"recoveryTimestamp":{"$timestamp":{"t":0,"i":0}}}}
mongo               | {"t":{"$date":"2024-03-17T07:53:15.942+00:00"},"s":"W",  "c":"CONTROL",  "id":22120,   "ctx":"initandlisten","msg":"Access control is not enabled for the database. Read and write access to data and configuration is unrestricted","tags":["startupWarnings"]}
mongo               | {"t":{"$date":"2024-03-17T07:53:15.943+00:00"},"s":"W",  "c":"CONTROL",  "id":5123300, "ctx":"initandlisten","msg":"vm.max_map_count is too low","attr":{"currentValue":262144,"recommendedMinimum":1677720,"maxConns":838860},"tags":["startupWarnings"]}
mongo               | {"t":{"$date":"2024-03-17T07:53:15.945+00:00"},"s":"I",  "c":"NETWORK",  "id":4915702, "ctx":"initandlisten","msg":"Updated wire specification","attr":{"oldSpec":{"incomingExternalClient":{"minWireVersion":0,"maxWireVersion":21},"incomingInternalClient":{"minWireVersion":0,"maxWireVersion":21},"outgoing":{"minWireVersion":6,"maxWireVersion":21},"isInternalClient":true},"newSpec":{"incomingExternalClient":{"minWireVersion":0,"maxWireVersion":21},"incomingInternalClient":{"minWireVersion":21,"maxWireVersion":21},"outgoing":{"minWireVersion":21,"maxWireVersion":21},"isInternalClient":true}}}
mongo               | {"t":{"$date":"2024-03-17T07:53:15.945+00:00"},"s":"I",  "c":"REPL",     "id":5853300, "ctx":"initandlisten","msg":"current featureCompatibilityVersion value","attr":{"featureCompatibilityVersion":"7.0","context":"startup"}}
mongo               | {"t":{"$date":"2024-03-17T07:53:15.945+00:00"},"s":"I",  "c":"STORAGE",  "id":5071100, "ctx":"initandlisten","msg":"Clearing temp directory"}
mongo               | {"t":{"$date":"2024-03-17T07:53:15.946+00:00"},"s":"I",  "c":"CONTROL",  "id":6608200, "ctx":"initandlisten","msg":"Initializing cluster server parameters from disk"}
mongo               | {"t":{"$date":"2024-03-17T07:53:15.946+00:00"},"s":"I",  "c":"CONTROL",  "id":20536,   "ctx":"initandlisten","msg":"Flow Control is enabled on this deployment"}
mongo               | {"t":{"$date":"2024-03-17T07:53:15.947+00:00"},"s":"I",  "c":"FTDC",     "id":20625,   "ctx":"initandlisten","msg":"Initializing full-time diagnostic data capture","attr":{"dataDirectory":"/data/db/diagnostic.data"}}
mongo               | {"t":{"$date":"2024-03-17T07:53:15.949+00:00"},"s":"I",  "c":"REPL",     "id":6015317, "ctx":"initandlisten","msg":"Setting new configuration state","attr":{"newState":"ConfigReplicationDisabled","oldState":"ConfigPreStart"}}
mongo               | {"t":{"$date":"2024-03-17T07:53:15.949+00:00"},"s":"I",  "c":"STORAGE",  "id":22262,   "ctx":"initandlisten","msg":"Timestamp monitor starting"}
mongo               | {"t":{"$date":"2024-03-17T07:53:15.951+00:00"},"s":"I",  "c":"NETWORK",  "id":23015,   "ctx":"listener","msg":"Listening on","attr":{"address":"/tmp/mongodb-27017.sock"}}
mongo               | {"t":{"$date":"2024-03-17T07:53:15.951+00:00"},"s":"I",  "c":"NETWORK",  "id":23015,   "ctx":"listener","msg":"Listening on","attr":{"address":"0.0.0.0"}}
mongo               | {"t":{"$date":"2024-03-17T07:53:15.951+00:00"},"s":"I",  "c":"NETWORK",  "id":23016,   "ctx":"listener","msg":"Waiting for connections","attr":{"port":27017,"ssl":"off"}}
mongo               | {"t":{"$date":"2024-03-17T07:53:15.951+00:00"},"s":"I",  "c":"CONTROL",  "id":8423403, "ctx":"initandlisten","msg":"mongod startup complete","attr":{"Summary of time elapsed":{"Startup from clean shutdown?":true,"Statistics":{"Transport layer setup":"0 ms","Run initial syncer crash recovery":"0 ms","Create storage engine lock file in the data directory":"0 ms","Get metadata describing storage engine":"0 ms","Validate options in metadata against current startup options":"0 ms","Create storage engine":"951 ms","Write current PID to file":"0 ms","Initialize FCV before rebuilding indexes":"2 ms","Drop abandoned idents and get back indexes that need to be rebuilt or builds that need to be restarted":"0 ms","Rebuild indexes for collections":"0 ms","Load cluster parameters from disk for a standalone":"0 ms","Build user and roles graph":"0 ms","Set up the background thread pool responsible for waiting for opTimes to be majority committed":"0 ms","Initialize information needed to make a mongod instance shard aware":"0 ms","Start up the replication coordinator":"1 ms","Start transport layer":"0 ms","_initAndListen total elapsed time":"969 ms"}}}}
mongo               | {"t":{"$date":"2024-03-17T07:53:25.248+00:00"},"s":"I",  "c":"NETWORK",  "id":22943,   "ctx":"listener","msg":"Connection accepted","attr":{"remote":"172.18.0.3:43728","uuid":{"uuid":{"$uuid":"d9da7bf8-5fd7-4663-9834-4e7e51ea0fce"}},"connectionId":1,"connectionCount":1}}
mongo               | {"t":{"$date":"2024-03-17T07:53:25.251+00:00"},"s":"I",  "c":"NETWORK",  "id":51800,   "ctx":"conn1","msg":"client metadata","attr":{"remote":"172.18.0.3:43728","client":"conn1","negotiatedCompressors":[],"doc":{"driver":{"name":"PyMongo","version":"4.6.2"},"os":{"type":"Linux","name":"Linux","architecture":"aarch64","version":"5.15.49-linuxkit-pr"},"platform":"CPython 3.9.18.final.0"}}}
mongo               | {"t":{"$date":"2024-03-17T07:53:25.264+00:00"},"s":"I",  "c":"NETWORK",  "id":22943,   "ctx":"listener","msg":"Connection accepted","attr":{"remote":"172.18.0.3:43742","uuid":{"uuid":{"$uuid":"812c9429-30d5-4e56-9c7c-cee9790633eb"}},"connectionId":2,"connectionCount":2}}
mongo               | {"t":{"$date":"2024-03-17T07:53:25.265+00:00"},"s":"I",  "c":"NETWORK",  "id":51800,   "ctx":"conn2","msg":"client metadata","attr":{"remote":"172.18.0.3:43742","client":"conn2","negotiatedCompressors":[],"doc":{"driver":{"name":"PyMongo","version":"4.6.2"},"os":{"type":"Linux","name":"Linux","architecture":"aarch64","version":"5.15.49-linuxkit-pr"},"platform":"CPython 3.9.18.final.0"}}}

無事立ち上げ成功!だけどMongoのログ長い。。。
実運用ではログレベル変更する設定を入れた方がよさそう。

https://www.mongodb.com/docs/manual/reference/log-messages/#configure-log-verbosity-levels

https://storage.googleapis.com/zenn-user-upload/8b7f878482b8-20240317.png

APIを叩く

postmanで各エンドポイントを叩いてみる。

  • データ投入

    https://storage.googleapis.com/zenn-user-upload/2fef3e876489-20240317.png

  • 全データ取得

    https://storage.googleapis.com/zenn-user-upload/f9a67fe76c07-20240317.png

  • name指定でデータ取得

    https://storage.googleapis.com/zenn-user-upload/6d72183302b1-20240317.png

  • 全データ消去のち全データ取得

![https://storage.googleapis.com/zenn-user-upload/68dccd979a97-20240317.png](https://storage.googleapis.com/zenn-user-upload/68dccd979a97-20240317.png)

![https://storage.googleapis.com/zenn-user-upload/f802b6f158da-20240317.png](https://storage.googleapis.com/zenn-user-upload/f802b6f158da-20240317.png)

できた〜
とりあえず手元で動かせたので、次はMongo DBをAlibabaのをつかってみる。

つづきはこちら! ApsaraDB for MongoDBを使ってみる【AlibabaCloud 接続編】

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?