Здравствуйте, хотелось бы разобраться в вопросе генерации уникального числового ID в кластере.
Собственно смотря на
www.mongodb.org/display/DOCS/Object+IDs
пока видится такой же вариант, только размер выделенных байт будет чуть меньше.
Делаем 4 части:
1) время в формате epoch (unix, posix), в общем количество секунд с 1970 года.
time = 8 bytes integer (2 ** (4 * 8) = 4294967296 variants)
import time
int(time.time())
part1 = 1314823196 /…
2) machine_id = 2 bytes integer (2 ** (4 * 2) = 256 variants)
тут видится 2 варианта,
или генерация machine_id согласно hostname, или просто некий внутренний номер, который скажем прописывается в зависимости от hostname,
т.е. можно просто machine_id = 1 / 2 / 3 … / 10
part2 = 1 / 2 / 3 /…
3) pid = 2 bytes integer (2 ** (4 * 4) = 65536 variants)
тут точные варианты проверить пока не могу, но в макоси например pid такого вида: 01318, т.е. совсем немного.
part3 = 01318 /…
4) increment = 4 bytes integer (2 ** (4 * 4) = 65536 variants)
тут сложнее,
например на 8 ядрах будут одинаковые time, machine_id, pid.
остается только increment.
тут вижу вариант использовать какой-нибудь memcached incr например,
чтобы сразу увеличить и получить данное значение атомарно.
тогда 8 потоков получат ключ 1,2,3,4,5,6,7,8 соответственно и не будет коллизий.
import memcache
cache = memcache.Client(['127.0.0.1:11211'])
cache_key = ‘cache_pid_’.format(pid_id)
cache.set(cache_key, 0)
increment_id = cache.incr(cache_key) — увеличит и возвратит новое инкрементированное поле
part4 = 1 / 2 / 3 /…
получается в итоге что-то типа такого:
1314823196 + 1 + 01318 + 1
1314823196 + 1 + 01318 + 2
1314823196 + 1 + 01318 + 3
1314823196 + 2 + 71673 + 1
1314823196 + 2 + 71673 + 2
1314823196 + 2 + 71673 + 3
…
т.е. число где-то так:
13148231962716733
если взять для хранения BIGINT то получается
-9223372036854775808 to 9223372036854775807
13 148 231 962 716 733
9 223 273 036 854 775 807
т.е. запаса много.
собственно вопрос, все ли правильно в данном методе или где-то есть ошибка или что-то возможно улучшить?
а как бы вы генерировали такую штуку?
Спасибо!
update:
хм, а еще вариант просто брать memcache increment, не знаю он на весь кластер нормально работает?