Het idee
Ik zou je dezelfde aanpak aanbevelen die wordt gebruikt door Instagram . Hun eisen lijken de uwe nauw te volgen.
Gegenereerde ID's moeten op tijd kunnen worden gesorteerd (zo zou een lijst met foto-ID's bijvoorbeeld kunnen worden gesorteerd zonder meer informatie over de foto's op te halen) ID's zouden idealiter 64 bits moeten zijn (voor kleinere indexen en betere opslag in systemen zoals Redis) Het systeem zou moeten introduceren als zo min mogelijk nieuwe 'bewegende onderdelen' - een groot deel van hoe we Instagram hebben kunnen schalen met heel weinig ingenieurs, is door te kiezen voor eenvoudige, gemakkelijk te begrijpen oplossingen die we vertrouwen.
Ze kwamen met een systeem dat 41 bits heeft op basis van de tijdstempel, 13 o de database-shard en 10 voor een auto-increment-gedeelte. Aangezien je geen shards lijkt te gebruiken. U kunt slechts 41 bits hebben voor een op tijd gebaseerd bestanddeel en 23 willekeurig gekozen bits. Dat levert een uiterst onwaarschijnlijke kans van 1 op 8,3 miljoen op om een conflict te krijgen als u tegelijkertijd records invoegt. Maar in de praktijk zul je dit nooit bereiken. Goed, wat dacht je van wat code:
ID's genereren
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
Let op, START_TIME
in de bovenstaande code is een willekeurige starttijd. U kunt time.time()*1000 gebruiken, de waarde ophalen en deze instellen als START_TIME
Merk op dat de reverse_id
methode die ik heb gepost, stelt u in staat om erachter te komen op welk moment het record is gemaakt. Als u die informatie moet bijhouden, kunt u dat doen zonder dat u er een ander veld voor hoeft toe te voegen! Je primaire sleutel is dus eigenlijk het opslaan van je opslagruimte in plaats van het te vergroten!
Het model
Dit is hoe uw model eruit zou zien.
class MyClass(models.Model):
id = models.BigIntegerField(default = fields.make_id, primary_key=True)
Als u buiten django wijzigingen aanbrengt in uw database, moet u het equivalent van make_id
maken als een sql-functie
Als voetnoot. Dit lijkt een beetje op de benadering die Mongodb gebruikt om zijn _ID te genereren voor elk object.