Идеята
Бих ви препоръчал същия подход, който се използва от Instagram . Техните изисквания изглежда точно следват вашите.
Генерираните идентификационни номера трябва да се сортират по време (така че списък с идентификационни номера на снимки, например, може да бъде сортиран, без да се извлича повече информация за снимките) Идентификаторите в идеалния случай трябва да са 64 бита (за по-малки индекси и по-добро съхранение в системи като Redis) Системата трябва да въведе като възможно най-много нови „движещи се части“ — голяма част от начина, по който успяхме да мащабираме Instagram с много малко инженери, е чрез избора на прости, лесни за разбиране решения, на които вярваме.
Те измислиха система, която има 41 бита въз основа на клеймото за време, 13 o фрагмента на базата данни и 10 за частта с автоматично увеличение. Тъй като изглежда, че не използвате парчета. Можете просто да имате 41 бита за времево базиран copmonent и 23 бита, избрани на случаен принцип. Това създава изключително малко вероятен шанс 1 на 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 за всеки обект.