sql >> データベース >  >> NoSQL >> Redis

StackExchange.Redisとの並列実行?

    現在、コードは同期API(StringSet)を使用しています )、10スレッドで同時にロードされています。これは、SE.Redisに感知できるほどの課題を提示することはありません-ここでは問題なく機能します。 疑う これは、サーバーが一部のデータを処理するのに必要な時間よりも長くかかったタイムアウトであり、サーバーのアロケータにも関連している可能性があります。したがって、1つのオプションは、単にタイムアウトを少し増やすことです。 。それほど多くはありません...デフォルトの1秒の代わりに5秒を試してください。おそらく、ほとんどの操作はとにかく非常に高速に動作しています。

    スピードアップに関して:ここでの1つのオプションは、待たないことです。 -つまり、データのパイプライン化を維持します。すべてのメッセージのエラー状態をチェックしないことに満足している場合、これを行う簡単な方法の1つは、, flags: CommandFlags.FireAndForget StringSetの最後まで 電話。私のローカルテストでは、これにより1Mの例が25%高速化されました(残りの時間の多くは実際には文字列のシリアル化に費やされていると思います)。

    10Mの例で私が抱えていた最大の問題は、10Mの例での作業のオーバーヘッドでした。 -特に、これは両方のredis-serverに大量のメモリを必要とするためです。 (セットアップをエミュレートするための)アプリケーションは同じマシン上にあります。これにより、マネージコードにGCの一時停止などが発生し、競合するメモリプレッシャーが発生します。しかし、おそらくもっと重要なのは、何かを始めるのに永遠にかかる 。その結果、並列のyield returnを使用するようにコードをリファクタリングしました。 単一のリストではなくジェネレーター。例:

        static IEnumerable<Person> InventPeople(int seed, int count)
        {
            for(int i = 0; i < count; i++)
            {
                int f = 1 + seed + i;
                var item = new Person
                {
                    Id = f,
                    Name = Path.GetRandomFileName().Replace(".", "").Substring(0, appRandom.Value.Next(3, 6)) + " " + Path.GetRandomFileName().Replace(".", "").Substring(0, new Random(Guid.NewGuid().GetHashCode()).Next(3, 6)),
                    Age = f % 90,
                    Friends = ParallelEnumerable.Range(0, 100).Select(n => appRandom.Value.Next(1, f)).ToArray()
                };
                yield return item;
            }
        }
    
        static IEnumerable<T> Batchify<T>(this IEnumerable<T> source, int count)
        {
            var list = new List<T>(count);
            foreach(var item in source)
            {
                list.Add(item);
                if(list.Count == count)
                {
                    foreach (var x in list) yield return x;
                    list.Clear();
                }
            }
            foreach (var item in list) yield return item;
        }
    

    と:

    foreach (var element in InventPeople(PER_THREAD * counter1, PER_THREAD).Batchify(1000))
    

    ここで、Batchifyの目的 各操作の間にかなりの時間をかけてサーバーを支援しすぎないようにすることです。データは1000のバッチで作成され、各バッチは非常に迅速に利用可能になります。

    JSONのパフォーマンスも心配だったので、JILに切り替えました:

        public static string ToJSON<T>(this T obj)
        {
            return Jil.JSON.Serialize<T>(obj);
        }
    

    そして、楽しみのために、JSON作業をバッチ処理に移動しました(実際の処理がループするように:

     foreach (var element in InventPeople(PER_THREAD * counter1, PER_THREAD)
         .Select(x => new { x.Id, Json = x.ToJSON() }).Batchify(1000))
    

    これにより時間が少し短縮されたので、3分57秒で10Mをロードでき、42,194ropsの速度になります。この時間のほとんどは、実際にはアプリケーション内のローカル処理です。各スレッドが同じをロードするように変更した場合 アイテムITEMS / THREADS 数回すると、これは1分48秒に変わります-92,592ropsの速度です。

    本当に何かに答えたかどうかはわかりませんが、短いバージョンは単に「タイムアウトを長くしてみてください。ファイアアンドフォーゲットの使用を検討してください」




    1. TCP接続で発生するすべてのバイトをどのように読み取りますか?

    2. redisキャッシュが機能しているかどうかをテストするにはどうすればよいですか?

    3. MongoDBのマシンプールとクラウドプロファイル

    4. 大規模なETAを使用したセロリタスクのスケジューリング