تخزين الذاكرة

*This content is translated using AI (Beta) and may contain errors. To view this page in English, click here.

MemoryStoreService هي خدمة بيانات ذات تدفق عالي وزمن استجابة منخفض، توفر تخزين بيانات سريع في الذاكرة يمكن الوصول إليه من جميع الخوادم في جلسة حية. تخزين الذاكرة مناسب للبيانات المتكررة والعابرة التي تتغير بسرعة ولا تحتاج إلى أن تكون دائمة، لأنها أسرع في الوصول وتختفي عند الوصول إلى الحد الأقصى لعمرها. للبيانات التي تحتاج إلى الاستمرار عبر الجلسات، استخدم مخازن البيانات.

هياكل البيانات

بدلاً من الوصول المباشر إلى البيانات الخام، تمتلك تخزين الذاكرة ثلاث هياكل بيانات أولية مشتركة بين الخوادم لمعالجة سريعة: خريطة مرتبة، قائمة انتظار، و خريطة تجزئة. كل هيكل بيانات مناسب لحالات استخدام معينة:

  • المطابقة المعتمدة على المهارة - إحفظ معلومات المستخدم، مثل مستوى المهارة، في قائمة انتظار مشتركة بين الخوادم، واستخدم خوادم اللوبي لتنفيذ المطابقة بشكل دوري.
  • التجارة والمزادات عبر الخوادم - إتاحة التجارة العامة بين الخوادم المختلفة، حيث يمكن للمستخدمين المزايدة على العناصر مع أسعار تتغير في الوقت الفعلي، مع خريطة مرتبة من أزواج المفتاح-القيمة.
  • لوحات القيادة العالمية - تخزين وتحديث تصنيفات المستخدمين على لوحة قيادة مشتركة داخل خريطة مرتبة.
  • المخازن المشتركة - إحفظ عناصر المخزون والإحصائيات في خريطة تجزئة مشتركة، حيث يمكن للمستخدمين استخدام عناصر المخزون مع بعضهم بشكل متزامن.
  • ذاكرة تخزين للبيانات الدائمة - مزامنة ونسخ بياناتك المستمرة في مخزن بيانات إلى خريطة تجزئة في ذاكرة التخزين تعمل كذاكرة مؤقتة وتحسن من أداء لعبتك.

بشكل عام، إذا كنت بحاجة إلى الوصول إلى البيانات بناءً على مفتاح معين، استخدم خريطة التجزئة. إذا كنت بحاجة إلى أن تكون هذه البيانات مرتبة، استخدم خريطة مرتبة. إذا كنت بحاجة إلى معالجة بياناتك بترتيب معين، استخدم قائمة الانتظار.

الحدود والكوطة

للإبقاء على قابلية التوسع وأداء النظام، تمتلك تخزين الذاكرة حدود استخدام البيانات الخاصة بحجم الذاكرة، طلبات API، وحجم هيكل البيانات.

تمتلك تخزين الذاكرة سياسة طرد تعتمد على وقت انتهاء الصلاحية، والمعروفة أيضًا باسم "الوقت للحياة" (TTL). يتم طرد العناصر بعد انتهاء صلاحيتها، ويتم تحرير حصة الذاكرة لإدخالات جديدة. عندما تصل إلى حد الذاكرة، تفشل جميع طلبات الكتابة اللاحقة حتى تنتهي صلاحية العناصر أو تقوم بحذفها يدويًا.

حصة حجم الذاكرة

تحدد حصة الذاكرة إجمالي كمية الذاكرة التي يمكن أن تستهلكها اللعبة. ليست قيمة ثابتة؛ بل تتغير بمرور الوقت حسب عدد المستخدمين في اللعبة وفقًا للصيغة 64KB + 1.2KB * [عدد المستخدمين]. تنطبق الحصة على مستوى اللعبة بدلاً من مستوى الخادم.

عندما ينضم المستخدمون إلى اللعبة، تتوفر حصة الذاكرة الإضافية على الفور. عندما يغادر المستخدمون اللعبة، لا تتقليص الحصة على الفور. هناك فترة زمنية للخلف تمتد لثمانية أيام قبل أن يتم إعادة تقييم الحصة إلى قيمة أقل.

بعد أن تصل لعبتك إلى حصة حجم الذاكرة، تفشل أي طلبات API تزيد من حجم الذاكرة دائمًا. الطلبات التي تقلل أو لا تغير من حجم الذاكرة لا تزال تنجح.

مع لوحة الرصد، يمكنك مشاهدة حصة حجم الذاكرة للعبتك في الوقت الحقيقي باستخدام مخطط استخدام الذاكرة.

حدود طلبات API

تنطبق حصة وحدات الطلب على جميع استدعاءات MemoryStoreService API. هذه الحصة هي 1000 + 120 * [عدد المستخدمين المتزامنين] من وحدات الطلب في الدقيقة.

معظم استدعاءات API تستهلك وحدة طلب واحدة فقط، مع بعض الاستثناءات:

  • MemoryStoreSortedMap:GetRangeAsync()

    تستهلك وحدات بناءً على عدد العناصر المعادة. على سبيل المثال، إذا أعادت هذه الطريقة 10 عناصر، فإن الاستدعاء يعد كـ 10 وحدات طلب. إذا أعادت استجابة فارغة، فسيحسب كـ وحدة طلب واحدة.

  • MemoryStoreQueue:ReadAsync()

    تستهلك وحدات بناءً على عدد العناصر المعادة، تمامًا مثل MemoryStoreSortedMap:GetRangeAsync()، لكن تستهلك وحدة إضافية كل ثانيتين أثناء القراءة. حدد الحد الأقصى لوقت القراءة باستخدام معلمة waitTimeout.

  • MemoryStoreHashMap:UpdateAsync()

    تستهلك حد أدنى من وحدتين.

  • MemoryStoreHashMap:ListItemsAsync()

    تستهلك [عدد الأقسام الممسوحة] + [العناصر المعادة] وحدات.

يتم تطبيق حصة الطلبات أيضًا على مستوى اللعبة بدلاً من مستوى الخادم. يوفر ذلك مرونة لتوزيع الطلبات بين الخوادم طالما أن المعدل الإجمالي للطلبات لا يتجاوز الحصة. إذا تجاوزت الحصة، ستحصل على رد خطأ عندما تقوم الخدمة بخنق طلباتك.

مع ميزة الرصد المتاحة، يمكنك عرض حصة وحدة الطلبات للعبتك في الوقت الحقيقي.

حدود حجم هيكل البيانات

بالنسبة لخريطة مرتبة واحدة أو قائمة انتظار، تنطبق الحدود التالية على الحجم وعدد العناصر:

  • الحد الأقصى لعدد العناصر: 1,000,000
  • الحد الأقصى للإجمالي الحجم (بما في ذلك المفاتيح لخريطة مرتبة): 100 ميجابايت

حدود لكل قسم

راجع الحدود لكل قسم.

أفضل الممارسات

للحفاظ على نمط استخدام الذاكرة الأمثل وتجنب الوصول إلى الحدود، اتبع هذه الممارسات الجيدة:

  • قم بإزالة العناصر المعالجة. يعمل تنظيف العناصر المقروءة بانتظام باستخدام MemoryStoreQueue:RemoveAsync() لقوائم الانتظار و MemoryStoreSortedMap:RemoveAsync() لخرايط مرتبة على تحرير الذاكرة وإبقاء هيكل البيانات محدثًا.

  • حدد وقت انتهاء الصلاحية لأقصر فترة زمنية ممكنة عند إضافة البيانات. على الرغم من أن وقت انتهاء الصلاحية الافتراضي هو 45 يومًا لكل من MemoryStoreQueue:AddAsync() و MemoryStoreSortedMap:SetAsync()، فإن تحديد أقصر وقت ممكن يمكن أن يؤدي تلقائيًا إلى تنظيف البيانات القديمة لمنعها من ملء حصة استخدام الذاكرة الخاصة بك.

    • لا تخزن كمية كبيرة من البيانات مع انتهاء صلاحية طويلة، لأنها تعرض خطتك لتجاوز الحصة الخاصة بك وتسبب مشكلات يمكن أن تعطل لعبتك بالكامل.
    • دائمًا قم إما بحذف العناصر غير الضرورية صراحة أو تعيين انتهاء صلاحية قصير للعناصر.
    • بشكل عام، يجب عليك استخدام الحذف الصريح لإطلاق الذاكرة وانتهاء صلاحية العنصر كآلية أمان لمنع العناصر غير المستخدمة من شغل الذاكرة لفترة طويلة.
  • احتفظ فقط بالقيم الضرورية في الذاكرة.

    على سبيل المثال، بالنسبة للعبة مزاد، تحتاج فقط للحفاظ على أعلى مزايدة. يمكنك استخدام MemoryStoreSortedMap:UpdateAsync() على مفتاح واحد للحفاظ على أعلى مزايدة بدلاً من الاحتفاظ بجميع المزايدات في هيكل البيانات الخاص بك.

  • استخدم التراجع الأسي للمساعدة في البقاء تحت حدود طلبات API.

    على سبيل المثال، إذا تلقيت DataUpdateConflict، يمكنك إعادة المحاولة بعد ثانيتين، ثم أربع، ثماني، إلخ. بدلًا من إرسال الطلبات بشكل متواصل إلى MemoryStoreService للحصول على الاستجابة الصحيحة.

  • قم بتقسيم هياكل البيانات الضخمة إلى هياكل أصغر متعددة عن طريق تجزئتها.

    من الأسهل غالبًا إدارة البيانات في هياكل أصغر بدلًا من تخزين كل شيء في هيكل بيانات كبير واحد. يمكن أن يساعد هذا النهج أيضًا في تجنب حدود الاستخدام والمعدل. على سبيل المثال، إذا كان لديك خريطة مرتبة تستخدم بادئات لمفاتيحها، فكر في فصل كل بادئة إلى خريطتها المرتبة الخاصة. بالنسبة للعبة شعبية بشكل خاص، قد تفصل حتى المستخدمين إلى خرائط متعددة بناءً على الأرقام الأخيرة من معرفات المستخدمين الخاصة بهم.

  • قم بتجزئة المفاتيح التي يتم الوصول إليها بشكل متكرر في خرائط التجزئة مع نسخ متعددة من المفتاح لتوزيع الحمل.

  • قم بضغط القيم المخزنة.

    على سبيل المثال، فكر في استخدام خوارزمية LZW لتقليل حجم القيمة المخزنة.

  • انضم إلى خدمات موسعة.

    يمكنك زيادة حدود التخزين وحدود الطلبات الخاصة بك من خلال الانخراط في الخدمات الموسعة.

الرصد

توفر لوحة الرصد رؤى وتحليلات لمراقبة وحل مشكلات استخدام تخزين الذاكرة الخاص بك. مع المخططات التي يتم تحديثها في الوقت الحقيقي حول جوانب مختلفة من استخدام الذاكرة وطلبات API، يمكنك تتبع نمط استخدام الذاكرة للعبتك، عرض الحصص المخصصة الحالية، مراقبة حالة API، وتحديد المشكلات المحتملة لتحسين الأداء.

تسرد الجدول التالي وتصف جميع رموز الحالة لاستجابات API المتاحة على مخططات عدد الطلبات حسب الحالة و طلبات حسب API x الحالة في لوحة الرصد. لمزيد من المعلومات حول كيفية حل هذه الأخطاء، راجع استكشاف الأخطاء وإصلاحها. للحد أو الحصة المحددان الذي يتعلق به خطأ، راجع الحدود والكوطة.

رمز الحالةالوصف
نجاحنجاح.
DataStructureMemoryOverLimitيتجاوز حد حجم الذاكرة لمستوى هيكل البيانات (100 ميجابايت).
DataUpdateConflictتعارض بسبب التحديث المتزامن.
AccessDeniedغير مصرح بالوصول إلى بيانات اللعبة. هذا الطلب لا يستهلك وحدات الطلب أو يستخدم الحصة.
InternalErrorخطأ داخلي.
InvalidRequestالطلب ليس لديه المعلومات المطلوبة أو يحتوي على معلومات مشوهة.
DataStructureItemsOverLimitيتجاوز حد عدد العناصر لمستوى هيكل البيانات (1M).
NoItemFoundلم يتم العثور على عنصر في MemoryStoreQueue:ReadAsync() أو MemoryStoreSortedMap:UpdateAsync(). ReadAsync() يستعلم كل ثانيتين ويعيد هذا رمز الحالة حتى يجد عناصر في قائمة الانتظار.
DataStructureRequestsOverLimitيتجاوز حد وحدات الطلب لمستوى هيكل البيانات (100,000 وحدة طلب في الدقيقة).
PartitionRequestsOverLimitيتجاوز حد وحدات الطلب الخاصة بالقسم.
TotalRequestsOverLimitيتجاوز حد وحدات الطلب على مستوى الكون.
TotalMemoryOverLimitيتجاوز حد الذاكرة على مستوى الكون.
ItemValueSizeTooLargeحجم القيمة يتجاوز الحد (32KB).

تسرد الجدول التالي رموز الحالة من جانب العميل، والتي غير متاحة حاليًا على لوحة الرصد.

رمز الحالةالوصف
InternalErrorخطأ داخلي.
UnpublishedPlaceيجب عليك نشر هذا المكان لاستخدام MemoryStoreService.
InvalidClientAccessيجب استدعاء MemoryStoreService من الخادم.
InvalidExpirationTimeيجب أن يكون حقل 'expiration' بين 0 و 3,888,000.
InvalidRequestغير قادر على تحويل القيمة إلى JSON.
InvalidRequestغير قادر على تحويل sortKey إلى رقم أو سلسلة صالحين.
TransformCallbackFailedفشل في استدعاء دالة الرجوع للتحول.
RequestThrottledطلبات MemoryStores الأخيرة تصطدم بواحد أو أكثر من الحدود.
UpdateConflictتجاوز الحد الأقصى لعدد المحاولات.

استكشاف الأخطاء وإصلاحها

تسرد الجدول التالية وتصف الحلول الموصى بها لكل رمز حالة رد:

خطأخيارات استكشاف الأخطاء وإصلاحها
DataStructureRequestsOverLimit / PartitionRequestsOverLimit
  • أضف ذاكرة مؤقتة محلية عن طريق حفظ المعلومات في متغير آخر وإعادة التحقق بعد فترة زمنية معينة، مثل 30 ثانية.
  • استخدم مخطط عدد الطلبات حسب الحالة للتحقق من أنك تتلقى استجابات نجاح أكثر من عدم وجود عناصر. حد من عدد المرات التي تصطدم بها MemoryStoreService بطلب فاشل.
  • قم بتنفيذ تأخير قصير بين الطلبات.
  • اتبع الممارسات الجيدة، بما في ذلك:
    • تجزئة هياكل بياناتك إذا كنت تتلقى عددًا كبيرًا من استجابات DataStructureRequestsOverLimit/PartitionRequestsOverLimit.
    • تجزئة مفاتيح خريطة التجزئة الخاصة بك إذا كنت تتلقى عددًا كبيرًا من استجابات PartitionRequestsOverLimit في استدعاءات خريطة التجزئة.
    • تقليل أو تجميع الاتصالات بهياكل بيانات معينة أو مفاتيح خريطة التجزئة إذا كنت ترى استجابات PartitionRequestsOverLimit.
    • تنفيذ تراجع أسي لإيجاد معدل معقول من الطلبات للإرسال.
TotalRequestsOverLimit
DataStructureItemsOverLimit
DataStructureMemoryOverLimit
TotalMemoryOverLimit
DataUpdateConflict
  • قم بتنفيذ تأخير قصير بين الطلبات لتجنب تحديث نفس المفتاح في نفس الوقت.
  • بالنسبة للخرايط المرتبة، استخدم وظيفة الرجوع في دالة MemoryStoreSortedMap:UpdateAsync() لإلغاء طلب بعد عدد معين من المحاولات، كما يظهر في مثال الشيفرة التالي:
  • مثال على إلغاء الطلب

    local MemoryStoreService = game:GetService("MemoryStoreService")
    local map = MemoryStoreService:GetSortedMap("AuctionItems")
    function placeBid(itemKey, bidAmount)
    map:UpdateAsync(itemKey, function(item)
    item = item أو { highestBid = 0 }
    if item.highestBid < bidAmount then
    item.highestBid = bidAmount
    return item
    end
    print("العنصر هو "..item.highestBid)
    return nil
    end, 1000)
    end
    placeBid("MyItem", 50)
    placeBid("MyItem", 40)
    print("تم")
  • تحقق مما إذا كنت تستدعي MemoryStoreService بكفاءة لتجنب التعارضات. مثاليًا، ينبغي عليك عدم إرسال الطلبات بشكل مفرط.
  • قم بإزالة العناصر باستمرار بمجرد قراءتها باستخدام دالة MemoryStoreQueue:RemoveAsync() لقوائم الانتظار و MemoryStoreSortedMap:RemoveAsync() للخرايط المرتبة.
خطأ داخلي
طلب غير صالح
  • تأكد من أنك تتضمن المعلمات الصحيحة والصحيحة في طلبك. تشمل أمثلة المعلمات غير الصالحة:
    • سلسلة فارغة
    • سلسلة تتجاوز حد الطول
حجم قيمة العنصر كبير جدًا
  • قم بتجزئة أو توزيع قيمة العنصر إلى مفاتيح متعددة.
    • لترتيب المفاتيح المجمعة، قم بفرزها أبجديًا عن طريق إضافة prefix إلى المفتاح.
  • تشفير أو ضغط القيم المخزنة.

اختبار وتصحيح في الاستوديو

البيانات في MemoryStoreService معزولة بين الاستوديو والإنتاج، لذا فإن تغيير البيانات في الاستوديو لا يؤثر على سلوك الإنتاج. هذا يعني أن استدعاءات API الخاصة بك من الاستوديو لا تصل إلى بيانات الإنتاج، مما يسمح لك باختبار تخزين الذاكرة والميزات الجديدة بأمان قبل الانتقال إلى الإنتاج.

يخبر الاستوديو بنفس الحدود والكوطة مثل الإنتاج. بالنسبة للحصص المحسوبة استنادًا إلى عدد المستخدمين، يمكن أن تكون الحصة الناتجة صغيرة جدًا نظرًا لأنك المستخدم الوحيد خلال اختبار الاستوديو. عند الاختبار من الاستوديو، قد تلاحظ أيضًا زمن استجابة أعلى قليلاً ومعدلات خطأ مرتفعة مقارنة بالاستخدام في الإنتاج بسبب بعض الفحوصات الإضافية التي يتم إجراؤها للتحقق من الوصول والإذن.

لمزيد من المعلومات حول كيفية تصحيح تخزين الذاكرة في الألعاب الحية أو عند الاختبار في الاستوديو، استخدم وحدة التحكم للمطورين.

©2026 شركة Roblox Corporation. تُعد منصّة Roblox، وشعار Roblox وشعار "توسيع حدود المخيلة"، من ضمن علاماتنا التجارية المسجّلة وغير المسجّلة في الولايات المتحدة وبلدان أخرى.