Pomysł
Polecam ci to samo podejście, które jest stosowane przez Instagram . Ich wymagania wydają się ściśle odpowiadać Twoim.
Wygenerowane identyfikatory powinny być możliwe do sortowania według czasu (więc można na przykład posortować listę identyfikatorów zdjęć bez pobierania więcej informacji o zdjęciach) Identyfikatory powinny być najlepiej 64-bitowe (dla mniejszych indeksów i lepszego przechowywania w systemach takich jak Redis) System powinien wprowadzić jako jak najmniej nowych „ruchomych części” — duża część tego, jak udało nam się skalować Instagram przy niewielkiej liczbie inżynierów, to wybór prostych, łatwych do zrozumienia rozwiązań, którym ufamy.
Wymyślili system, który ma 41 bitów w oparciu o znacznik czasu, 13 fragmentów bazy danych i 10 dla części autoinkrementacji. Ponieważ wydaje się, że nie używasz odłamków. Możesz mieć tylko 41 bitów dla składnika opartego na czasie i 23 bity wybrane losowo. Daje to niezwykle mało prawdopodobną szansę 1 na 8,3 miliona wystąpienia konfliktu, jeśli wstawiasz rekordy w tym samym czasie. Ale w praktyce prawdopodobnie nigdy w to nie trafisz. A co z kodem:
Generowanie identyfikatorów
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
Uwaga, START_TIME
w powyższym kodzie jest jakiś arbitralny czas rozpoczęcia. Możesz użyć time.time()*1000 , pobrać wartość i ustawić ją jako START_TIME
Zauważ, że reverse_id
Metoda, którą zamieściłem, pozwala dowiedzieć się, w jakim czasie rekord został utworzony. Jeśli chcesz śledzić te informacje, możesz to zrobić bez konieczności dodawania do nich kolejnego pola! Tak więc kluczem podstawowym jest w rzeczywistości oszczędzanie pamięci, a nie jej zwiększanie!
Model
Teraz tak będzie wyglądał Twój model.
class MyClass(models.Model):
id = models.BigIntegerField(default = fields.make_id, primary_key=True)
Jeśli dokonasz zmian w swojej bazie danych poza django, będziesz musiał stworzyć odpowiednik make_id
jako funkcja sql
Jako notatkę. Jest to trochę podobne do podejścia stosowanego przez Mongodb do generowania jego _ID dla każdego obiektu.