Сохраняйте отсортированный набор с элементами вывода, используя в качестве оценки bonus ÷ amount
.
Для
w/d |w/d amt|w/d-bonus
personA |10000 | 100
Вы сохраняете его, используя ZADD :
ZADD withdrawers 0.01 "personA|10000|100"
Затем вы используете ZPOPMAX , чтобы получить и удалить верхний элемент. Или вы можете использовать ZREVRANGEBYSCORE , чтобы получить то же самое, не удаляя, как показано ниже:
ZREVRANGEBYSCORE withdrawers +inf -inf WITHSCORES LIMIT 0 1
При обработке вывода с помощью ZPOPMAX
, если совпадение является частичным, тогда вы ZADD
снова с уменьшенной суммой и бонусом.
Если вы обслуживаете своих вкладчиков в порядке очереди, используйте список для постановки их в очередь: LPU SH для постановки в очередь, RPOP для обработки.
При обработке вкладчика, если совпадение является частичным, вы RPUSH
делаете это с уменьшенной суммой.
Ваш клиент для сопоставителя может использовать блокирующие версии команд для использования: BRPOP для вкладчиков и BZPOPMAX для снимающих.
Но если у вас есть несколько двигателей, выполняющих матчи, вам лучше провести весь матч, используя Lua скрипт для атомарности. Сценарий должен выскочить из обеих очередей, если ни одна не пуста, pu sh вернет любую обновленную запись, частично сопоставленную, а затем вернет результат сопоставления, если он есть (nil
, если очередь пуста), чтобы вы могли обработать ее: сохранить ее, выполняйте его, что бы вы ни делали.
Изначально мы говорили, что для снятия средств score = bonus ÷ amount
, чтобы максимизировать бонус для вкладчиков. Но это оставляет случайным образом, как разрешить связи в счете (сначала вы получите лексографически отсортированную максимальную запись).
Есть много решений для этого.
Вы можете использовать более сложная оценка, чтобы решить связи. Например, чтобы сначала получить бонус-максимизатор с минимальной суммой:
счет = раунд (бонус * 1000000 ÷ сумма) + 1 ÷ сумма
При округлении вы рассматриваете техническую сумму ie диапазон bonus ÷ amount
. Размер этого диапазона определяется обратным множителю. Здесь 1000000 делает этот диапазон размером 0,000001.
Или вы можете просто сделать ZREVRANGEBYSCORE withdrawers score score
, чтобы получить все элементы в ie вверху, после вызова ZREVRANGEBYSCORE withdrawers +inf -inf WITHSCORES LIMIT 0 1
, чтобы получить максимальный балл. Затем вы разрешаете t ie на стороне клиента.
Или вы можете попытаться использовать лексикографическое свойство отсортированных наборов, настраивая способ хранения элементов.