«Параллельный вывод, как обеспечить согласованность данных? 》, когда один и тот же пользователь одновременно списывает средства, существует определенная вероятность несогласованности данных.Вы можете использовать метод оптимистической блокировки CAS, чтобы обеспечить согласованность данных без снижения пропускной способности и с небольшими изменениями.
Менее чем через 24 часа после публикации статьи было почти 200 комментариев.
Среди них наиболее часто задаваемые вопросыАВА-проблема, эта проблема обсуждалась в разделе "Оптимизация согласованности параллельного вывода, проблема ABA в CAS, эта тема еще не закончена! ! ! "Расширенный.
Во-вторых, большинство задаваемых вопросов являются домашними заданиями, почемуиспользовать select&setспособ сделатьбаланс отпишитесь:
UPDATE t_yue SET money=uid AND money=$old_money;
Почемунельзя использоватьМетод прямого вывода:
UPDATE t_yue SET money=money-uid;
Многие говорят, что в случае параллелизма деньги будут вычитаться в отрицательное число.
Чтобы сохранить балансне тарифицироваться как отрицательное число, плюс условие where:
UPDATE t_yue SET money=money-uid AND money-$diff>0_;_
Это возможно?
_Голос за кадром: _Ну, кроме бизнеса, этот SQL, использующий столбцы для операций, на самом деле не годится.Рекомендуется использовать:
UPDATE t_yue SET money=money-uid AND money>$diff_;_
Извините, все еще не работает. Причина вКак обеспечить согласованность данных для параллельных выводов?"Самый популярный комментарий в статье,не идемпотент.
_Голос за кадром: _Объясните, что большинство учащихся могут правильно ответить на домашнее задание.
Прежде чем говорить об идемпотентности, давайте рассмотрим еще один тестовый пример.
Предположим, что есть сервисный интерфейс,Зарегистрировать нового пользователя:
bool RegisterUser(name){
// Проверить, существует ли уже uid
select uid from t_user where uid=$uid;
// Не новый пользователь, ошибка возврата
if(rows>0)return false;
else{
// вставить нового пользователя в таблицу пользователей
insert into t_user values(name);
// вернуть успех
return true;
}
}
Есть инженер-испытатель, который написалпрецедент:
bool TestCase_RegisterUser(){
// сделать некоторые поддельные данные
long uid=123;
String name='shenjian';
// вызвать тестируемый интерфейс
bool result= RegisterUser(uid,name);
// Ожидается успешная регистрация,Делайте утверждения о результатах
Assert(result,true);
// вернуть результат теста
return result;
}
Это хороший тест?
Что не так с этим вариантом использования?
Вы обнаружите, что при одних и тех же условиях этот тестовый пример выполняется дважды, и результаты разные:
(1) первое выполнение, первое создание данных, вызывающий интерфейс и успешная регистрация;
(2) При втором выполнении снова создаются те же данные, вызывается интерфейс, и регистрация завершается ошибкой;
Это не хороший тестовый пример, несколько запусков дают разные результаты.
Что такое идемпотентность?
При тех же условиях выполняется тот же запрос и тот же результат, то есть идемпотент.
Голос за кадром: Погуглите, объясните лучше, чем я могу, но должно быть понятно.
Как изменить приведенный выше тестовый пример на «идемпотентный» тестовый пример?
Просто добавьте одну строку кода:
bool TestCase_RegisterUser(){
// создаем поддельные данные
long uid=123;
строка then = 'Экскалибур';
// Сначала удалите этого фальшивого пользователя
DeleteUser(uid);
// вызов тестируемого интерфейса
bool result= RegisterUser(uid,name);
// Ожидаем, что регистрация будет успешной, и делаем вывод о результате
Assert(result,true);
// возвращаем результат теста
return result;
}
так,на тех же условиях, независимо от того, сколько раз выполняется этот вариант использования, результат теста одинаков.
Вы немного относитесь к идемпотентности?
Запросы на чтение, как правило, идемпотентны.
Пишите запросы по мере необходимости:
-
вставка x, вообще говоря, не является идемпотентной, и результаты, полученные повторной вставкой, не обязательно будут одинаковыми.
-
delete x, вообще говоря, является идемпотентным, и результат многократного удаления все тот же
-
установить a=x идемпотентно
-
set a=a-x не является идемпотентным
-
…
Итак, вычитаем остаток следующим образом:
UPDATE t_yue SET money=uid AND money=$old_money;
является идемпотентной операцией.
Если вычесть остаток следующим образом:
UPDATE t_yue SET money=money-uid AND money-$diff>0;
не является идемпотентной операцией.
Говоря здесь, может быть, некоторые друзья собираются поднять планку,Тестовый пример будет выполняться повторно, как можно повторно выполнять вывод?
Повторить.
Retry — очень распространенный метод обработки исключений.
Вы когда-нибудь писали такой код, когда писали свой бизнес:
result = DoSomething();
if(false==result || TIMEOUT){
// ошибка или тайм-аут, попробуйте еще раз
result= DoSomething();
}
return result;
Конечно, найдутся друзья, которые снова поднимут планку, и я больше никогда не буду пробовать! ! !
Голос за кадром: А, это успех или провал?
Вы сами решаете, как писать бизнес-код.Не могу решить, как написать базовый код фреймворка:
(1) Платформа сайта автоматически повторяет попытку?
(2) Платформа службы автоматически повторяет попытку?
(3) Автоматически ли повторяются попытки пула соединений службы и пула соединений базы данных?
Голос за кадром:
(1) В многоуровневой архитектуре на основе служб рекомендуется, чтобы повторные попытки выполнялись только на уровне входа, а уровень служб не должен повторять попытки для предотвращения лавин;
(2) Нижний уровень dubbo, время ожидания вызова повторяется по умолчанию, этот дизайн не очень хорош;
следовательно,В архитектурах с повторными попытками необходимо учитывать идемпотентность..
Теперь пришло время понять, почему бизнес удержания и пополнения обычно используется:
- выберите и установите, с решением CAS
Вместо того, чтобы использовать:
- установить схему деньги-=Х
Голос за кадром: Я оплатил 100 телефонных счетов, зачем еще 200 юаней?
знай это, знай это, я надеюсь, что у каждого есть что-то получить.
Путь архитектора- Делитесь техническими идеями
Также есть много комментариев от друзей: номер версии, CAS можно использовать только при низком параллелизме, а при высоком параллелизме будет много сбоев модификации. Может быть, все неправильно поняли «высокий параллелизм». Давайте поговорим о связанных с этим вопросах в следующей статье.