NIFCLOUD-mbaas / UserCommunity

ニフクラ mobile backend ユーザーコミュニティ
https://mbaas.nifcloud.com/
81 stars 18 forks source link

同時にDBにアクセスした新規ユーザに対して、重複しないように、DBに新規IDを登録したい( query.FindAsync中のDBでの処理に関する質問) #1340

Open undgro03 opened 1 year ago

undgro03 commented 1 year ago

現在、Unityでランキング機能付きのゲームを開発しています。 ランキング機能の実装にあたって、ニフクラをサーバーとして用いています。

実装方法として、DBの中で"userId"というプレイヤーに固有の値を、新規プレイヤーに1から順に割りあてていく方式を考えています。 このuserIdが重複しないように新規ユーザIDを生成・管理したいと考えており、下記コードによる実装をしているのですが、この際、query.FindAsyncの処理に関して疑問があります。

2人の新規プレイヤーが、同時にFindAsyncを行った場合に、サーバー側の処理として、 ①1人のFindAsync の処理が終わったのち、もう1人のFindAsyncの処理が開始される ②2人で並列処理が行われる のどちら(またはそれ以外)なのでしょうか?もし、②の場合、重複しないように管理するためにはどのように設計すればよいのでしょうか?

下記コードでは、次のような意図で処理を行っています。 1.ニフクラ上にUserIdManagerというクラスを作り、ユーザーID数を管理するため"userId"というフィールドを持たせます。 2.query.FindAsync((List objList, NCMBException e) でDBにアクセスし、"userId"の最新の値を取得します 3.ローカル変数のuserIdにDB上の"userId"に1を足した値を代入し、この値でDB上の"userId"を上書きします。 4.セーブデータの領域の、自分のIDを管理する変数(この場合はtestId)にuserIdを格納します

今回の質問としては、2人が同時アクセスした場合に、同じuserIdの値が取得されてしまう可能性があるのかどうかを知りたいです。 よろしくお願いします。

ニフクラ

using NCMB;
using System.Collections.Generic;
using UnityEngine;

namespace NCMB
{
    public class UserIdManager
    {
        public void GetUserId()
        {
            int userId;
            NCMBQuery<NCMBObject> query = new NCMBQuery<NCMBObject>("UserIdManager");
            query.FindAsync((List<NCMBObject> objList, NCMBException e) => {
            if (e == null) {
                if( objList.Count == 0 ) //userIdが1つも登録されていない場合の処理
                {
                    NCMBObject obj = new NCMBObject("UserIdManager");
                    obj["userId"] = 1;
                    obj.SaveAsync();
                    userId = System.Convert.ToInt32(obj["userId"]);
                }
                else //userIdが登録されている場合の処理
                {
                    userId = System.Convert.ToInt32(objList[0]["userId"]) + 1;
                    objList[0]["userId"] = userId;
                    objList[0].SaveAsync();
                }
                PlayerPrefs.SetString("testId", userId.ToString("D8"));
            }
            });
        }
    }
}
goofmint commented 1 year ago

ネットワークで多人数が同時アクセスする前提なので、重複しない数字を割り当てる(いわばロックするような仕組み)のは無理かと思います。NCMB自体ではそういった動作の保証はしていませんので、同時に取得すれば重複した数値が割り当てられます。

undgro03 commented 1 year ago

ご回答どうもありがとうございます。 そうなんですね。となると、ユーザー重複しないようにするには、GUID値などを割り当てて、最初から重複の可能性を限りなく方法を採用したほうが良いのかもしれないですね。

goofmint commented 1 year ago

GUIDを割り当てるのであれば、objectIdを使ってもらう方が良いかなと。objectIdはユニークです。