NHibernate - счетчики с параллелизмом и кэшированием второго уровня - PullRequest
2 голосов
/ 22 ноября 2010

Я новичок в NHibernate и испытываю трудности при настройке его для моего текущего веб-сайта.Этот веб-сайт будет работать на нескольких веб-серверах с одним сервером базы данных, и поэтому у меня возникают некоторые проблемы с параллелизмом.На сайте будет зарегистрировано около 50 000 пользователей или около того, и у каждого пользователя будет страница профиля.На этой странице другие пользователи могут «понравиться» другому пользователю, так же, как Facebook.Это было проблемой параллелизма.

Я думал об использовании кэша второго уровня, скорее всего, с использованием поставщика MemChached, так как у меня будет несколько веб-серверов.Каков наилучший способ реализовать такую ​​функцию «Мне нравится» с помощью NHibernate?Я думал о трех вариантах:

  1. Использовать простой запрос Count ().Будет таблица «User_Likes», где каждая строка будет представлять подобное от одного пользователя к другому.Чтобы отобразить число лайков, я бы просто спросил количество лайков для пользователя, которое было бы переведено в базу данных как простой SELECT COUNT(*) FROM USER_LIKES WHERE ID = x или что-то в этом роде.Однако я полагаю, что это приведет к значительному снижению производительности, так как каждый раз, когда пользователь посещает страницу профиля и, как и другой пользователь, количество лайков должно быть пересчитано, кэш второго уровня или нет.
  2. Используйте дополнительный столбец NumberOfLikes в таблице User и увеличивайте / уменьшайте это значение, когда пользователь любит или не любит другого пользователя.Это, однако, дает мне проблемы с параллелизмом.Используя простой цикл for, я протестировал его, 1000 раз полюбив пользователя на двух серверах, и результат в БД составил около 1100 лайков.Это разница 900. Реалистичный тест или нет, это, конечно, не вариант.Теперь я рассмотрел оптимистическую и пессимистическую блокировку как решение (не так ли?), Но мой текущий шаблон репозитория на данный момент не подходит для использования этого, боюсь, поэтому, прежде чем я это исправлю,Я хотел бы знать, если это правильный путь.
  3. Как 2, но с использованием собственного HQL и сам написать оператор обновления, что-то вроде UPDATE User SET NumberOfLikes = NumberOfLikes + 1 WHERE id = x.Это не вызовет проблем с параллелизмом в базе данных, верно?Однако я не уверен, что у меня будет какое-либо несоответствие данных на моих нескольких серверах из-за кэширования второго уровня.

Так что ... Мне действительно нужен некоторый совет здесь.Есть ли другой вариант?Это похоже на обычную ситуацию, и, безусловно, NHibernate должен поддержать это элегантным образом.Я новичок в NHIbernate, поэтому четкий и подробный ответ необходим и ценится :-) Спасибо!

Ответы [ 2 ]

1 голос
/ 22 ноября 2010

Я подозреваю, что вы увидите эту проблему в других местах.Вы можете решить эту конкретную проблему с помощью 3., но это оставляет другие места, где вы столкнетесь с проблемами параллелизма.

Я бы посоветовал реализовать пессимистическую блокировку.Обычный способ сделать это - просто применить транзакцию ко всему HTTP-запросу.С BeginRequest в вашем Global.asax вы запускаете сеанс и транзакцию.Затем в EndRequest вы делаете это.С событием Error вы идете по альтернативному пути: откат и отбрасывание сеанса.

Это вполне приемлемый способ применения NHibernate.См. Например http://dotnetslackers.com/articles/aspnet/Configuring-NHibernate-with-ASP-NET.aspx.

0 голосов
/ 23 ноября 2010

Я бы пошел с 3 . Я считаю, что в такого рода приложениях не так важно, если на некоторых страницах какое-то время показывается немного устаревшее значение.

IIRC, обновления HQL не делают недействительной запись кэша сущностей, поэтому вам может потребоваться сделать это вручную.

...