MongoDB表とスライス選択の一次実践

5435 ワード

背景:
最近、会社はアプリケーションを開発して、アプリケーションのデータが敏感なため、クライアントが安全だと仮定する前提の下で、データベースにアクセスする権限のあるいかなる人やネットワークの伝送過程の秘密漏洩を避けるために、ユーザーの各業務タイプのデータはすべてjsonに転換してそれからフロントエンドからバックエンドに秘密に保存して、バックエンドがフロントエンドに戻るデータもすべて暗号化データで、フロントエンドは、システムに保存されていないユーザカスタム鍵によって復号化される.
設計案:
  • バックエンドのデータストレージはMongoDB、Spring Dataを使用してデータアクセスを行います.
  • このコンテンツのテーブルデザインは多分_id、ビジネスタイプ、暗号文、変更日などのフィールド.
  • フロントエンドは、要求ごとに1つのトラフィックタイプのみを対象としているため、Apiごとにトラフィックタイプの着信がある.
  • 一括CUDの場合には、応答において具体的に各ペンに記録された操作結果をマークすることができるため、プライマリキー_idはフロントエンドによって生成される.
  • 各ビジネスタイプデータは1枚の表に保存されており、各ビジネスタイプデータはバックエンドにとって同じであり、同じREST Apiを使用しており、フロントエンドがデータを復号してから異なる処理を行うと同時に、この設計案は柔軟にビジネスタイプを増やすことができ、タイプを増やす際にはタイプの列挙クラスに要素を追加するだけでよい.
  • 以降は、[ビジネスタイプ、id]を組み合わせてスライスすることが考えられる.

  • 質問:
    開発が完了すると、フロントエンドはそのビジネス・ルールに基づいて、異なるビジネス・タイプで同じidを使用します.これにより、元の設計スキームは使用できません.また、ボスは、各ビジネス・タイプが異なるCollectionを使用してデータを保存することに偏っています.
    理由は主に以下の通りである.
  • スライスルーティングのために使用されるインデックス自体が大きな空間を占めている(スライスキーを左プレフィックスとするインデックスを増やす必要がある).
  • 各業務タイプデータは業務の観点から独立しており、揉むべきではない.

  • コードを見ると、Repositoryレイヤのデータベース操作は、MongoOperationsのようにfindOne(id)のようなMongoRepositoryから継承されます.findOne(query,Class,collectionName)は自分でCollectionを指定できるので、サブテーブルに変更するには大きな変更がかかり、計画通りにすぐに交差しなければならないので、いろいろな方法を探します.
    構想を改造する.
  • 考え方1:元のすべてのApiをそのままにして、フロントエンドに設定されたidを1つの業務idフィールド(biz_id)とし、バックエンドはObjectId()を真実idとして使用し、フロントエンドに戻るときに、業務idでidフィールドを埋め込むことを指定します.この考え方の欠点はかなり明らかで、見ただけで得られるものではなく、最初のプロジェクトに対してこのようにして、後のメンテナンスに難易度を増加させることができます.

  • 次の2つは表分けの考え方です.
  • 構想2:公式ドキュメントを表示すると、次の文字が
  • あります.
    Rich mapping support is provided by the MongoMappingConverter. MongoMappingConverter has a rich metadata model that provides a full feature set of functionality to map domain objects to MongoDB documents.
    MongoMappingConverterを上書きすることで、同じエンティティに対するCRUDをカスタムルーティングルールに従って指定Collectionに実装できるように見えますが、Referenceを見てもアプリケーションシーンの紹介は見つかりません.map domain objects to MongoDB documentsについて説明し、Collumnへのマッピングのみがあると判断します.
  • 構想3:ちょうど他のプロジェクトの同僚が同じDomainを保存する時に実際にどのCollectionに保存するかを決定し、SPELを使用しているので、参考にして、具体的には以下の通りです.
  • 1、Domainは注記@Document(collection="#{@collectionNameProvider.getCollectionName()}")を使用し、CRUD操作を行うとSpring Dataの下部からcollectionNameProviderが呼び出されます.getCollectionName()を使用してCollectionを取得します.
  • 2.Repository層の上、例えばサービス層でcollectionName Providerを呼び出す.setType()メソッドは、タイプ値をコンテキストに設定します.
  • 3、テーブル名決定器
  • の作成
    @Component("collectionNameProvider")
    public class CollectionNameProvider {
    
        public static final String DEFAULT_COLLECTION_NAME = "default_collection";
        private static ThreadLocal typeThreadLocal = new ThreadLocal<>();
    
        public static void setType(String type) {
            typeThreadLocal.set(type);
        }
    
        public String getCollectionName() {
            String type = typeThreadLocal.get();
            if (StringUtils.isNotBlank(type)) {
                String collectionName = doMapper(type);
                return collectionName;
            } else {
                return DEFAULT_COLLECTION_NAME;
            }
        }
    
        private String doMapper(String type) {
            //TODO        Type   Mapper   
            return null;
        }
    }

    以上のことから,この考え方は侵入性があり,Repository層の論理がServiceに侵入しているが,この考え方は比較的成熟しており,同時に業務タイプを柔軟に増加させることができるため,この考え方を用いて改造されていることがわかる.
    注意:ここで注意したいのは、Spring Data MongoDBがサービス開始時にすべての@Documentをスキャンし、collectionName Providerを呼び出すことによる依存性の問題です.getCollectionName()ですが、このときのc o l l e ctionNameProviderがApplicationContextにインスタンス化されていないと、起動に失敗する可能性があります.そのため、MongoMappingContextにApplicationContextのBeanを手動で注入することで、c o l l e ctionNameProviderがインスタンス化されてから@Documentをスキャンすることができます.
    まとめ:
  • 今回の設計については、以降は自分の考えを経て、個人的には分割テーブル(分割テーブルは特にここの考え方3の方式を指す、以下同)ではなく、分割テーブルはコード侵入性を有するが、現在は従来の関係型データライブラリに対するDAL(Data Access Layer)や他のP(CAPにおけるP)特性を有するNoSqlにかかわらず、設計哲学から,データストレージ層の上位層(永続層を含む)コードへの侵入を減らすことが考えられ,データストレージは上位層に対してできるだけ透明にするため,分表方式を用いるのは少し古い感じがする.
  • MongoDB unique indexがsharing keyの場合、一意のインデックスは失効するため、スライススキームはここで実行可能であり、異なるビジネスタイプで同じidを使用することができる.分表案の2つの理由については、次のように説明します.
  • スライスルーティングに使用されるインデックス自体は大きなスペースを占めており、本来はクエリー効率のために[トラフィックタイプ,id]のインデックスを増やす必要があるが、スライスは確かに追加のルーティングテーブルスペースを増やす必要があるが、このスペースはあまり大きくなく、許容できる範囲内である.
  • 各業務タイプデータは業務の観点から独立しており、揉むべきではない.この原因は比較的主観的であり、別の観点から見ると、実際には一緒に置くことができる.

  • 分表方式では、1つの業務タイプのデータがある程度増加すると、同様に分片が必要となり、同時に1つの業務タイプが増加するたびに、いずれも1つのテーブルを追加する必要があります(プログラムは自動的に作成できます).しかし、実際には各テーブルの構造は同じで、異なるのはテーブル名だけです.他のビジネスシーンに置くと、多くのテーブルは管理に不利になります.