ردًا على أسئلة الأداء التي غالبًا ما تنشأ أثناء الاستخدام، أقدم المجموعات الثلاث التالية من أفضل الممارسات:
❄ إذا كانت متطلبات إنشاء المعرف لا تتجاوز 5 وات/ثانية، فليست هناك حاجة لتعديل أي معلمات تكوين.
❄ إذا تجاوزت 5 وات/ث وأقل من 50 وات/ث، فمن المستحسن تعديل: SeqBitLength=10
❄ إذا تجاوز 50 واط بت/ثانية واقترب من 500 واط بت/ثانية، فمن المستحسن تعديل: SeqBitLength=12
باختصار، ستؤدي زيادة SeqBitLength إلى أداء أفضل، لكن المعرفات التي تم إنشاؤها ستكون أطول.
❄ هذه خوارزمية محسنة لندفة الثلج (انجراف ندفة الثلج)، والتي تولد معرفات أقصر وأسرع.
❄ يدعم التوسع التلقائي لبيئات الحاويات مثل k8s (التسجيل التلقائي لـ WorkerId)، ويمكن إنشاء معرف رقمي فريد في بيئة مستقلة أو موزعة.
❄ يدعم أصلاً لغة C#/Java/Go/C/Rust/Python/Node.js/PHP (امتداد C)/SQL/ واللغات الأخرى، ويوفر اتصال مكتبة ديناميكي آمن متعدد الخيوط (FFI).
❄ متوافق مع جميع خوارزميات ندفة الثلج (وضع شريحة الأرقام أو الوضع الكلاسيكي، الشركات المصنعة الكبيرة أو الصغيرة)، يمكنك إجراء أي ترقية أو تبديل في المستقبل.
❄ هذه هي أداة إنشاء معرف Snowflake الأكثر شمولاً في تاريخ الكمبيوتر. 【اعتبارًا من أغسطس 2022】
كمهندس معماري، تريد حل مشكلة المفاتيح الأساسية الفريدة في قاعدة البيانات، خاصة في النظام الموزع الذي يحتوي على قواعد بيانات متعددة.
هل تريد أن يستخدم المفتاح الأساسي لجدول البيانات أقل مساحة تخزين، والفهرسة بشكل أسرع، والتحديد والإدراج والتحديث بشكل أسرع.
يجب أن تأخذ في الاعتبار أنه عند تقسيم قواعد البيانات والجداول (دمج قواعد البيانات والجداول)، يمكن استخدام قيمة المفتاح الأساسي مباشرة ويمكن أن تعكس توقيت العمل.
إذا كانت قيمة المفتاح الأساسي طويلة جدًا وتتجاوز الحد الأقصى لقيمة نوع رقم js للواجهة الأمامية، فيجب تحويل النوع الطويل إلى نوع السلسلة، وستشعر بالإحباط قليلاً.
على الرغم من أن Guid يمكنه الزيادة تلقائيًا، إلا أنه يشغل مساحة كبيرة وتكون سرعة الفهرسة بطيئة.
قد يكون هناك أكثر من 50 حالة تطبيق، ويمكن أن يصل كل طلب متزامن إلى 10 وات/ثانية.
لنشر التطبيقات في بيئة الحاوية، ودعم النسخ المتماثل الأفقي والتوسيع التلقائي.
هل لا ترغب في الاعتماد على عملية التزايد التلقائي لـ redis للحصول على معرفات المفتاح الأساسي المستمرة، لأن المعرفات المستمرة تشكل مخاطر أمنية على بيانات الأعمال.
هل تريد أن يعمل النظام لأكثر من 100 عام؟
المعرف الذي تم إنشاؤه طويل جدًا.
مقدار التزامن الفوري ليس كافياً.
لا يمكن حل مشكلة إعادة الاتصال بالوقت.
لا يتم دعم الإنشاء اللاحق الإضافي لمعرف الطلب المسبق.
قد تعتمد على أنظمة التخزين الخارجية.
✔ أرقام صحيحة، تتزايد بشكل رتيب مع مرور الوقت (ليست بالضرورة مستمرة)، وأقصر في الطول، ولن تتجاوز القيمة القصوى لنوع رقم js خلال 50 عامًا. (التكوين الافتراضي)
✔ أسرع، 2-5 مرات أسرع من خوارزمية ندفة الثلج التقليدية، يمكن إنشاء 500000 في 0.1 ثانية (استنادًا إلى الجيل الثامن من الجهد المنخفض i7).
✔ دعم معالجة رد الاتصال بالوقت. على سبيل المثال، إذا تم إرجاع وقت الخادم بمقدار ثانية واحدة، فيمكن أن تتكيف هذه الخوارزمية تلقائيًا لإنشاء معرف فريد للوقت الحرج.
✔يدعم الإدراج اليدوي للمعرفات الجديدة. عندما تحتاج الشركة إلى إنشاء معرفات جديدة في وقت تاريخي، يمكن للبتات المحجوزة لهذه الخوارزمية إنشاء 5000 معرف في الثانية.
✔ لا يعتمد على أي ذاكرة تخزين مؤقت أو قاعدة بيانات خارجية. (تعتمد المكتبة الديناميكية التي تسجل WorkerId تلقائيًا في بيئة k8s على redis)
✔ وظائف أساسية، جاهزة للاستخدام بمجرد إخراجها من الصندوق، ولا يلزم وجود ملفات تكوين أو اتصالات قاعدة بيانات أو ما إلى ذلك.
(المعلمات: تسلسل متزايد تلقائيًا 10 بت، 1000 قيمة قصوى للانجراف)
الطلبات المستمرة | 5K | 5 واط | 50 واط |
---|---|---|---|
خوارزمية ندفة الثلج التقليدية | 0.0045 ثانية | 0.053 ثانية | 0.556 ثانية |
خوارزمية الانجراف الثلوج | 0.0015 ثانية | 0.012 ثانية | 0.113 ثانية |
الأداء النهائي: 500 واط/ثانية ~ 3000 واط/ثانية. (يتم حساب جميع بيانات الاختبار على أساس الجيل الثامن من الجهد المنخفض i7)
عند حدوث معاودة الاتصال بوقت النظام، تستخدم الخوارزمية الرقم التسلسلي المحجوز للسلسلة الزمنية السابقة لإنشاء معرف جديد.
يتم وضع رقم المعرف الذي تم إنشاؤه بواسطة رد الاتصال أولاً بشكل افتراضي، ويمكن أيضًا تعديله ليكون لاحقًا.
السماح بإعادة الوقت إلى القاعدة المحددة مسبقًا لهذه الخوارزمية (المعلمات قابلة للتعديل).
المعرف الذي تم إنشاؤه بواسطة هذه الخوارزمية هو عدد صحيح (يشغل ما يصل إلى 8 بايت من المساحة). وفيما يلي المعرف الذي تم إنشاؤه بناءً على التكوين الافتراضي:
129053495681099 (运行1年,长度:15)
387750301904971 (运行3年,长度:15)
646093214093387 (运行5年,长度:15)
1292658282840139 (运行10年,长度:16)
9007199254740992 (运行70年,达到 js Number 最大值,长度:16)
165399880288699493 (运行1000年,等同普通雪花算法运行1年,长度:18)
قيمة المعرف التي تم إنشاؤها بواسطة هذه الخوارزمية هي 1٪ -10٪ من القيمة القصوى لرقم js، وهو جزء من الألف من قيمة خوارزمية ندفة الثلج العادية، ولكن سرعة التوليد أسرع من خوارزمية ندفة الثلج العادية.
الحد الأقصى لقيمة نوع رقم js: 9007199254740992. يمكن أن تستغرق هذه الخوارزمية 70 عامًا للوصول إلى القيمة القصوى لرقم js مع الحفاظ على أداء التزامن (5W+/0.01s) والحد الأقصى 64 معرف عامل (6 بت).
? 每增加 1位 WorkerIdBitLength 或 SeqBitLength,生成的ID数字值将会乘以2(基础长度可参考前一节“ID示例”),反之则除以2。
يشير شرح المدة التي يمكن استخدامها إلى الوقت الذي يمكن أن ينمو فيه رقم المعرف الذي تم إنشاؤه ليتجاوز الحد الأقصى لقيمة الطول (موقعة 64 بت، 8 بايت).
• في التكوين الافتراضي، يتوفر 71000 معرفًا فريدًا.
عند دعم 1024 عقدة عاملة، تتوفر المعرفات لمدة 4480 عامًا دون تكرار.
عند دعم 4096 عقدة عاملة، تتوفر المعرفات لمدة 1120 عامًا دون تكرار.
❄ WorkerIdBitLength ، طول بت كود الجهاز، يحدد الحد الأقصى لقيمة WorkerId، والقيمة الافتراضية هي 6 ، ونطاق القيمة هو [1، 19]. في الواقع، تستخدم بعض اللغات نوع ushort (uint16) غير الموقع للاستقبال هذه المعلمة، وبالتالي فإن الحد الأقصى للقيمة هو 16. إذا تم استخدام التوقيع القصير (int16)، فإن الحد الأقصى للقيمة هو 15.
❄ يجب أن يكون WorkerId ، رمز الجهاز، المعلمة الأكثر أهمية ، لا توجد قيمة افتراضية، فريدة عالميًا (أو فريدة داخل نفس DataCenterId)، ويجب تعيينها برمجيًا ، والشرط الافتراضي (يأخذ WorkerIdBitLength القيمة الافتراضية)، والحد الأقصى للقيمة هو 63، الحد الأقصى للقيمة النظرية هو 2^WorkerIdBitLength -1 (قد تقتصر لغات التنفيذ المختلفة على 65535 أو 32767، والمبدأ هو نفس قاعدة WorkerIdBitLength). ولا يمكن أن تكون هي نفسها على أجهزة مختلفة أو مثيلات تطبيق مختلفة. يمكنك تكوين هذه القيمة من خلال التطبيق أو الحصول على القيمة عن طريق الاتصال بخدمة خارجية. استجابة للحاجة إلى التسجيل التلقائي لـ WorkerId، توفر هذه الخوارزمية تطبيقًا افتراضيًا: التسجيل التلقائي للمكتبة الديناميكية لـ WorkerId من خلال redis، راجع "ToolsAutoRegisterWorkerId" للحصول على التفاصيل.
ملاحظة خاصة : إذا قام الخادم بنشر خدمات مستقلة متعددة، فستحتاج إلى تحديد WorkerId مختلفًا لكل خدمة.
❄ SeqBitLength ، طول بت التسلسل، القيمة الافتراضية 6 ، نطاق القيمة [3، 21] (يوصى به على الأقل 4)، يحدد عدد المعرفات التي تم إنشاؤها لكل مللي ثانية. إذا كان عدد الطلبات في الثانية لا يتجاوز 5 واط، فما عليك سوى الاحتفاظ بالقيمة الافتراضية 6؛ وإذا تجاوز 5 واط ولم يتجاوز 50 واط، فمن المستحسن تعيين قيمة 10 أو أكثر، وهكذا. متطلبات القاعدة: WorkerIdBitLength + SeqBitLength لا يتجاوز 22.
❄ MinSeqNumber ، الحد الأدنى لرقم التسلسل، القيمة الافتراضية 5، نطاق القيمة [5، MaxSeqNumber]، أول 5 أرقام تسلسلية لكل مللي ثانية تتوافق مع الأرقام 0-4 هي بتات محجوزة، منها 1-4 بتات محجوزة تتوافق مع الاتصال الهاتفي الزمني، 0 هو بت محجوز للقيم الجديدة اليدوية.
❄ MaxSeqNumber ، الحد الأقصى لرقم التسلسل، نطاق الإعداد هو [MinSeqNumber, 2^SeqBitLength-1]، القيمة الافتراضية هي 0، الحد الأقصى لرقم التسلسل الحقيقي هو القيمة القصوى (2^SeqBitLength-1)، إذا لم يكن 0 ، إنه الحد الأقصى الحقيقي لرقم التسلسل، ولا يلزم تعيينه بشكل عام، ما لم تشترك أجهزة متعددة في معرف العامل لإنشاء معرفات في المقاطع (في هذه الحالة، يجب تعيين الحد الأدنى لرقم التسلسل بشكل صحيح).
❄ BaseTime ، الوقت الأساسي (المعروف أيضًا باسم: وقت النقطة الأساسية، وقت الأصل، وقت العصر)، له قيمة افتراضية (2020)، وهو طابع زمني بالميلي ثانية (عدد صحيح، .NET هو نوع DatetTime)، وظيفته هي: الاستخدام عند إنشاء المعرف، يتم استخدام الفرق (بالملي ثانية) بين وقت النظام والوقت الأساسي كطابع زمني لإنشاء المعرف. ليست هناك حاجة بشكل عام لتعيين الوقت الأساسي. إذا كنت تشعر أن القيمة الافتراضية قديمة جدًا، فيمكنك إعادة تعيينها، ومع ذلك، يرجى ملاحظة أنه من الأفضل عدم تغيير هذه القيمة في المستقبل.
يخطط الإصدار الثاني لإضافة المعلمات:
❄ معرف مركز البيانات ، معرف مركز البيانات (معرف غرفة الكمبيوتر، الافتراضي 0)، يرجى التأكد من أنه فريد عالميًا.
❄ DataCenterIdBitLength ، طول معرف مركز البيانات (الافتراضي 0).
❄ نوع الطابع الزمني ، نوع الطابع الزمني (0 مللي ثانية، 1 ثانية)، الافتراضي 0.
1️⃣ الاتصال في الوضع الفردي. تستخدم هذه الخوارزمية مؤشر ترابط واحد لإنشاء معرفات، وستكون المكالمات الواردة من أطراف متعددة حصرية بشكل متبادل. في نفس مثيل التطبيق، يستخدم المتصل خيوط متعددة (أو متوازية) لاستدعاء هذه الخوارزمية، الأمر الذي لن يزيد من سرعة إخراج المعرف.
2️⃣ حدد معرف عامل فريدًا. يجب أن يضمن النظام الخارجي التفرد العالمي لـ WorkerId وتعيينه لمعلمة الإدخال لهذه الخوارزمية.
3️⃣ استخدم معرفات عاملة مختلفة عند نشر مثيلات متعددة على جهاز واحد. لا تدعم كافة التطبيقات التفرد المتزامن عبر العمليات. لكي تكون في الجانب الآمن، عند نشر مثيلات تطبيق متعددة على نفس المضيف، يرجى التأكد من أن كل WorkerId فريد.
4️⃣ التعامل مع الاستثناءات. ستطرح الخوارزمية جميع الاستثناءات، ويجب على النظام الخارجي التقاط الاستثناءات والتعامل معها جيدًا لتجنب التسبب في تعطل النظام بشكل أكبر.
5️⃣ فهم تعريف IdGeneratorOptions بعناية، والذي سيكون مفيدًا لدمج هذه الخوارزمية واستخدامها.
6️⃣ استخدم خوارزمية الانجراف على الثلوج. على الرغم من أن الكود يحتوي على تعريف خوارزمية ندفة الثلج التقليدية، ويمكنك تحديد (الطريقة = 2) عند نقطة الإدخال لتمكين الخوارزمية التقليدية، إلا أنه لا يزال يوصى باستخدام خوارزمية انجراف ندفة الثلج (الطريقة = 1، الافتراضية) بعد كل شيء، فهي تتمتع بقدرة أفضل على التمدد وأداء أعلى.
7️⃣ لا تقم بتعديل الخوارزمية الأساسية. تحتوي هذه الخوارزمية على العديد من المعلمات الداخلية والمنطق المعقد. عندما لا تتقن المنطق الأساسي، يرجى عدم تعديل الكود الأساسي واستخدامه في بيئة الإنتاج إلا إذا تم التحقق منه من خلال عدد كبير من الاختبارات الدقيقة والعلمية.
8️⃣ سياسات التكوين داخل مجال التطبيق هي نفسها. عندما يتم تشغيل النظام لفترة من الوقت ويحتاج المشروع إلى التبديل من تحديد WorkerId برمجيًا إلى تسجيل WorkerId تلقائيًا، يرجى التأكد من أن جميع المثيلات المستخدمة في نفس مجال التطبيق تتبنى إستراتيجية تكوين متسقة. وهذا ليس فقط لـ WorkerId ، ولكنه يتضمن أيضًا معلمات تكوين أخرى.
9️⃣ إدارة وقت الخادم بشكل جيد. تعتمد خوارزمية Snowflake على وقت النظام ولا تقم بضبط وقت نظام التشغيل يدويًا بمقدار كبير. إذا كان يجب عليك التعديل، فتذكر التأكد من أن وقت النظام عند بدء تشغيل الخدمة مرة أخرى أكبر من الوقت الذي تم فيه إيقاف تشغيلها آخر مرة. (ملاحظة: التغييرات الصغيرة في وقت النظام الناتجة عن مزامنة الوقت أو رد الاتصال على مستوى عالمي أو على مستوى الشبكة ليس لها أي تأثير على هذه الخوارزمية)
تشير تغييرات التكوين إلى ضبط معلمات التشغيل (خصائص كائن IdGeneratorOptions) بعد تشغيل النظام لفترة من الوقت.
1. المبدأ الأول هو: يمكن أن يكون BaseTime أقدم فقط (أبعد من الحاضر)، بحيث تكون قيمة المعرف الذي تم إنشاؤه أكبر من القيمة القصوى التاريخية، مما يضمن عدم وجود تداخل زمني وعدم إنشاء معرفات مكررة. [ لا ينصح بضبط BaseTime بعد تشغيل النظام]
2. يُسمح بزيادة WorkerIdBitLength أو SeqBitLength في أي وقت، ولكن يجب استخدام عملية "التخفيض" بحذر، لأن هذا قد يتسبب في أن يكون المعرف الذي تم إنشاؤه في المستقبل هو نفس التكوين القديم. [السماح بزيادة أي قيمة xxxBitLength بعد تشغيل النظام]
3. إذا كان من الضروري تقليل أحد WorkerIdBitLength أو SeqBitLength، فيجب استيفاء الشرط: يجب أن يكون مجموع القيمتين الجديدتين xxxBitLength أكبر من مجموع القيمتين القديمتين. [ لا يوصى بتضييق أي قيمة BitLength بعد التشغيل]
4. لا يتم التحكم منطقيًا في القواعد الثلاث المذكورة أعلاه في هذه الخوارزمية. يجب على المستخدمين إجراء تغييرات على التكوين بعد التأكد من أن التكوين الجديد يلبي المتطلبات.
يعتمد منشئ المعرف الفريد على WorkerId عندما تتطلب خدمات الأعمال النسخ المتماثل الأفقي والعشوائي (التوسيع التلقائي)، فإن هذا يتطلب القدرة على تسجيل WorkerId الفريد عالميًا قبل إنشاء معرف فريد.
توفر هذه الخوارزمية مكتبة ديناميكية مفتوحة المصدر (يتم تنفيذها بلغة Go)، والتي يمكنها تسجيل WorkerId تلقائيًا من خلال redis في بيئات الحاوية مثل k8s.
تسجيل WorkerId من خلال redis ليس هو الطريقة الوحيدة. يمكنك أيضًا تطوير خدمة تكوين مركزية عند بدء تشغيل كل خدمة لنقطة النهاية، يتم الحصول على معرف العامل الفريد من خلال الخدمة المركزية.
بالطبع، إذا لم تكن خدمتك بحاجة إلى التوسع تلقائيًا، فلن تحتاج إلى تسجيل WorkerId تلقائيًا، ولكن قم بتعيين قيم فريدة عالميًا لها.
هناك العديد من الطرق، مثل تطوير خدمة إنشاء معرف مركزية تقوم بإنشاء معرفات قابلة للاستخدام لكل خدمة نقطة نهاية (فردية أو دفعة).
رابط الصورة: https://github.com/yitter/IdGenerator/blob/master/Tools/AutoRegisterWorkerId/regprocess.jpg
مسار كود المصدر:/Go/source/regworkerid/reghelper.go
رابط التحميل: https://github.com/yitter/IdGenerator/releases/download/v1.3.3/workeridgo_lib_v1.3.3.zip
// 注册一个 WorkerId,会先注销所有本机已注册的记录
// address: Redis连接地址,单机模式示例:127.0.0.1:6379,哨兵/集群模式示例:127.0.0.1:26380,127.0.0.1:26381,127.0.0.1:26382
// password: Redis连接密码
// db: Redis指定存储库,示例:1
// sentinelMasterName: Redis 哨兵模式下的服务名称,示例:mymaster,非哨兵模式传入空字符串即可
// minWorkerId: WorkerId 最小值,示例:30
// maxWorkerId: WorkerId 最大值,示例:63
// lifeTimeSeconds: WorkerId缓存时长(秒,3的倍数),推荐值15
extern GoInt32 RegisterOne(char* server, char* password, GoInt32 db, char* sentinelMasterName, GoInt32 minWorkerId, GoInt32 maxWorkerId, GoInt32 lifeTimeSeconds);
// 注销本机已注册的 WorkerId
extern void UnRegister();
لغة | جيثب |
---|---|
؟ج# | عرض المثال |
جافا | عرض المثال |
؟ يذهب | عرض المثال |
الصدأ | عرض المثال |
?بايثون | عرض المثال |
؟ج | عرض المثال |
ج (امتداد PHP)؟ | عرض المثال |
دلفي (باسكال) | عرض المثال |
جافا سكريبت | عرض المثال |
؟ تايبسكريبت | عرض المثال |
?V | عرض المثال |
؟د | عرض المثال |
عنوان مفتوح المصدر: https://github.com/yitter/IdGenerator
مجموعة QQ: 646049993