python - كيفية استبدال المفتاح الأساسي Django مع عدد صحيح مختلف فريد لهذا الجدول




mysql hash (3)

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

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

  1. أرغب في الاحتفاظ بنوع حقل المفتاح الأساسي كـ عدد صحيح.
  2. كما أنني أفضل عدم الاضطرار إلى تجزئة / إلغاء هذه القيمة في كل مرة يتم قراءتها أو كتابتها أو مقارنتها بقاعدة البيانات. يبدو ذلك مضيعة للراحة سيكون من الجيد القيام بذلك مرة واحدة فقط: عندما يتم إدراج السجل في البداية في قاعدة البيانات
  3. لا يلزم أن تكون وظيفة التجزئة / التشفير قابلة للانعكاس لأنني لست بحاجة لاسترداد المفتاح المتسلسل الأصلي. قيمة التجزئة تحتاج فقط لتكون فريدة من نوعها.
  4. يجب أن تكون قيمة التجزئة فريدة لهذا الجدول فقط - وليست فريدة من نوعها على مستوى العالم.
  5. يجب أن تكون قيمة التجزئة قصيرة قدر الإمكان. أرغب في تجنب عناوين URL الطويلة للغاية (20+ حرفًا)

ما هي أفضل طريقة لتحقيق ذلك؟ هل العمل التالي؟

def hash_function(int):
    return fancy-hash-function # What function should I use??


def obfuscate_pk(sender, instance, created, **kwargs):
    if created:
        logger.info("MyClass #%s, created with created=%s: %s" % (instance.pk, created, instance))
        instance.pk = hash_function(instance.pk)
        instance.save()
        logger.info("\tNew Pk=%s" % instance.pk)

class MyClass(models.Model):
    blahblah = models.CharField(max_length=50, null=False, blank=False,)


post_save.connect(obfuscate_pk, sender=MyClass)

الفكرة

أوصي لك بنفس الطريقة المستخدمة من قبل Instragam . متطلباتهم ويبدو أن تتابع عن كثب لك.

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

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

توليد معرفات

START_TIME = a constant that represents a unix timestamp

def make_id():
    '''
    inspired by http://instagram-engineering.tumblr.com/post/10853187575/sharding-ids-at-instagram
        '''

    t = int(time.time()*1000) - START_TIME
    u = random.SystemRandom().getrandbits(23)
    id = (t << 23 ) | u

    return id


def reverse_id(id):
    t  = id >> 23
    return t + START_TIME 

ملاحظة ، START_TIME في الكود أعلاه هو بعض وقت البدء التعسفي. يمكنك استخدام time.time () * 1000 ، احصل على القيمة وقم بتعيينها على أنها START_TIME

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

الموديل

الآن هذا هو الشكل الذي سيبدو عليه النموذج الخاص بك.

class MyClass(models.Model):
   id = models.BigIntegerField(default = fields.make_id, primary_key=True)  

إذا قمت بإجراء تغييرات على قاعدة البيانات الخاصة بك خارج django ، فستحتاج إلى إنشاء المكافئ make_id sql

كملاحظة القدم. هذا يشبه إلى حد ما الطريقة المستخدمة من قبل Mongodb لإنشاء أنها _ID لكل كائن.


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


حافظ على AUTO_INCREMENT ، لكن AUTO_INCREMENT بطريقة شبه سرية: في ملف تعريف الارتباط. يتطلب الأمر بعض الترميز لإنشاء ملف تعريف الارتباط وتعيينه وقراءته. لكن ملفات تعريف الارتباط مخفية عن كل المتسللين باستثناء المتسللين الخطرين.





primary-key