Мы создаем новый REST API и должны принять несколько решений относительно первичного ключа и idempotency_key. У нашего API много пользователей, и пользователям разрешено искать только те объекты, которые им принадлежат. Запросы аутентифицируются, поэтому мы знаем, что userId связан с данным запросом.
Обеспокоенные свойства:
userId Идентификатор пользователя.idempotenyKey Ключ идемпотентности, используемый в идемпотентных запросах к API. Уникальный для каждого пользователя.Предположим, существует гипотетическая таблица Cars с конечной точкой GET .../cars/{id}, на которой мы будем основывать наше обсуждение.
Вариант 1. Используйте сочетание userId и idempotencyKey в качестве первичного ключа
CREATE TABLE Cars (
userId VARCHAR(255) NOT NULL,
idempotencyKey VARCHAR(255) NOT NULL,
description VARCHAR(255),
PRIMARY KEY (userId, idempotencyKey),
INDEX user_index (userId)
);
Поиск товара:
GET .../cars/{idempotencyKey}
Мысли:
Вариант 2 - Использование хеша userId + idempotencyKey в качестве первичного ключа
CREATE TABLE Cars (
id VARCHAR(255) NOT NULL,
userId VARCHAR(255) NOT NULL,
idempotencyKey VARCHAR(255) NOT NULL,
description VARCHAR(255),
PRIMARY KEY (id),
INDEX user_index (userId)
);
При вставке рассчитывали id = hash(userId + idempotencyKey).
Поиск товара:
GET .../cars/{id}
Мысли:
ids.Вариант 3 - Генерация первичного ключа uuid
CREATE TABLE Cars (
id VARCHAR(255) NOT NULL,
userId VARCHAR(255) NOT NULL,
idempotencyKey VARCHAR(255) NOT NULL,
description VARCHAR(255),
PRIMARY KEY (id),
INDEX user_index (userId),
CONSTRAINT unique_by_user UNIQUE (userId, idempotencyKey)
);
При прошивке ставили id = UUID.randomUUID().
Поиск товара:
GET .../cars/{id}
Мысли:
Вариант 4 - автоматически увеличиваемый первичный ключ, который никогда не открывается пользователю
CREATE TABLE Cars (
id INT NOT NULL AUTO_INCREMENT,
userId VARCHAR(255) NOT NULL,
idempotencyKey VARCHAR(255) NOT NULL,
description VARCHAR(255),
PRIMARY KEY (id),
INDEX user_index (userId),
CONSTRAINT unique_by_user UNIQUE (userId, idempotencyKey)
);
Есть несколько способов выполнить поиск. Поиск может быть основан исключительно на idempotencyKey, то есть:
GET .../cars/{idempotencyKey}
В качестве альтернативы мы могли бы автоматически сгенерировать uuid referenceId, который будет индексироваться и использоваться для поиска.
Мысли:
Ищу совет, какой подход выбрать. Очень важно учитывать производительность и масштаб.
Спасибо!
Есть ли в таблице пользователя (я полагаю, у вас есть таблица пользователей) столбец с idempotency_key? Если это так, вы сохраняете один и тот же дубликат данных, и вам следует удалить idempotency_key из таблицы car .. Вы можете просто найти отношение idempotencyKey между пользователем и автомобилем с помощью этого запроса SELECT * FROM user INNER JOIN car ON user.id = car.userId WHERE user.idempotencyKey = "key"
Для дополнительной безопасности вы можете добавить ограничение, с каких IP-адресов можно использовать idempotencyKey.
Для аутентификации мы используем JWT с userId в полезной нагрузке. Меня больше интересуют отзывы о возможных вариантах первичного ключа в отношении схемы базы данных. @RaymondNijland, что касается таблицы пользователей, мы также можем предположить, что она существует и что существует ограничение внешнего ключа на свойство userId на автомобилях. Невозможно удалить idempotencyKey из Cars, поскольку у пользователя может быть много автомобилей, и для запросов на создание автомобилей необходимо принудительно применять идемпотентность.






Я обрабатываю что-то подобное: отправляю идентификатор пользователя в заголовке
Authorization(идентификатор пользователя будет заявкой в JWT в заголовке авторизации), а затем использую его для сравнения с идентификатором пользователя в пути запроса, например/user/1. Если они совпадают, то аутентифицированный пользователь может действовать от имени пользователя в пути запроса. Это очень безопасно, потому что идентификатор пользователя в заголовке авторизации никогда не может быть изменен, пока никто не знает ваш секретный ключ. Просто имейте в виду, что JWT может использоваться злонамеренно, поэтому делайте это только в том случае, если пользователь действует на себя, а не на кого-то другого.