ETS. lookup и member изменяемой таблицы

97 views
Skip to first unread message

Evgen Polivoda

unread,
Jun 1, 2016, 9:53:11 AM6/1/16
to Erlang по-русски
Здравствуйте коллеги,
Хотел бы задать вопрос. 
Есть два ген сервера: 
1. ets_manager - держит в себе public ets таблицы и обновляет их по требованию (удаляет все данные и перезаливает снова).  
2. other_manager - делает ets:lookup и ets:member по этим собственно таблицам. 

Как будет вести себя other_manager при лукапе таблицы, если таблица в данный момент перестраивается? Будет ждать? Обрабатывать handle_call будет? Или замрет?

Спасибо. 

Андрей Веселов

unread,
Jun 1, 2016, 1:49:35 PM6/1/16
to erlang-...@googlegroups.com
У ets таблиц нет глобального mutex, там их много и на каждый backet в хеш-таблице. Поток заблокируется, но не так что бы на долго (если конечно не использовать ets:safe_fixtable). Вот статья по этому поводу.

Sergiy Kostyushkin

unread,
Jun 1, 2016, 7:09:51 PM6/1/16
to Erlang по-русски
lookup other_manager может попасть на пустую таблицу. Я так понимаю ets_manager играет роль кеширующего сервера. Если так то вам НЕ нужно удалять все данные, просто при заливке данных дополнительно сохраняйте timestamp последнего обновления, а затем удаляйте лишь те записи для которых он не обновился.

середа, 1 червня 2016 р. 16:53:11 UTC+3 користувач Evgen Polivoda написав:

Yuri Zhloba

unread,
Jun 2, 2016, 1:11:35 AM6/2/16
to erlang-...@googlegroups.com
Кешировние -- штука не простая. Я тож попадал на race condition, когда пытался читать кэш, а он пустой -- перестраивается.

Вариант, который предлагает Сергей, может быть выходом. Но тут есть один недостаток -- никак не ограничен объем памяти, который занимает кэш. Кэш может отъесть сколько угодно памяти, и держать невостребованные данные сколько угодно долго. Это подходит, если заранее известно, что все данные, которые попадают или потенциально могут попасть в кеш, занимают известный объем памяти, и не будут бесконтрольно расти.

Другие варианты кэша подразумевают установленный лимит памяти, и активное вытеснение невостребованных данных. Для этого нужно делать регулярные проходы по таблице с удалением.



2 июня 2016 г., 2:09 пользователь Sergiy Kostyushkin <s.kost...@gmail.com> написал:

--
Вы получили это сообщение, поскольку подписаны на группу "Erlang по-русски".
Чтобы отменить подписку на эту группу и больше не получать от нее сообщения, отправьте письмо на электронный адрес erlang-russia...@googlegroups.com.
Чтобы отправлять сообщения в эту группу, отправьте письмо на электронный адрес erlang-...@googlegroups.com.
Чтобы настроить другие параметры, перейдите по ссылке https://groups.google.com/d/optout.



--
Yuri Zhloba

skype: yzh44yzh
phone: +375 44 793 33 73

zheka_13

unread,
Jun 2, 2016, 1:28:07 AM6/2/16
to erlang-...@googlegroups.com
спасибо за ответы. То что у меня написано, надо однозначно переписать. Но вопрос был несколько в другом. Как будет вести себя other_manager  при lookup ets таблицы на которой выполняется сначала delete_all_objects и сразу за ним lists:foreach c инсертами.
Если lookup в этот момент получит not_found - то это приемлимо. А может так быть что lookup в такой момент залочивает other_manager он перестает обрабатывать handle_call и чего то ждет(точнее лукапа)? Фактически delete_all_objects и сразу за ним lists:foreach может делаться раз в секунду, вот так скажем. что тогда будет с lookup-ами в другом процессе?

2 июня 2016 г., 8:11 пользователь Yuri Zhloba <yzh4...@gmail.com> написал:

Evgeny M

unread,
Jun 2, 2016, 1:33:13 AM6/2/16
to Erlang по-русски
Может быть будет проще сделать два ets_manager - один грузится, другой в это время перестраивается. Потом при следующем обновлении переключаются. И lookup сначала делается по одному, потом по другому. Расходы памяти x2, но если таблицы небольшие, то это нормально. И можно обойтись без временных меток.

четверг, 2 июня 2016 г., 8:11:35 UTC+3 пользователь Yuri Zhloba написал:

Андрей Веселов

unread,
Jun 2, 2016, 1:43:25 AM6/2/16
to Erlang по-русски
При delete_all_objects, other_manager получит not_found

Max Lapshin

unread,
Jun 2, 2016, 2:51:41 AM6/2/16
to erlang-...@googlegroups.com
Только я бы ещё посоветовал убрать второй процесс. ets тем и хороши, что из них можно читать с нескольких ядер параллельно.

А для обновления кеша возможно стоит две таблицы.

Alexandre Beniaminov

unread,
Jun 2, 2016, 5:12:45 AM6/2/16
to erlang-...@googlegroups.com
Андрей Веселов уже написал: "При delete_all_objects, other_manager получит not_found".
Это следует из документации, где написано, что эта операция изолирована и атомарна.

Операция lists:foreach(ets:insert_new(Ets, Item), List) не атомарна. Атомарной будет операция ets:insert_new(Ets, List)



2 июня 2016 г., 8:28 пользователь zheka_13 <pol...@gmail.com> написал:



--
С уважением,
Александр Бениаминов

Maxim Filipovich

unread,
Jun 7, 2016, 3:46:00 AM6/7/16
to erlang-...@googlegroups.com
Можно держать 2 таблицы и хранить ключ, по которому можно найти активную на текущий момент таблицу. Когда необходима перестройка – параллельно наполняется таблица и когда всё готово, ключ меняется и все могут читать из новой таблицы, а старую можно очистить.
С уважением, Maxim Filippovich.

zheka_13

unread,
Jun 7, 2016, 4:02:44 AM6/7/16
to erlang-...@googlegroups.com
Переписал немного, все работает, спасибо. Но все же проблема была не в том чтобы получать правильные данные при лукапе. Проблема была в том, что как я заметил, когда шла волна перестройки этих таблиц, другой ген сервер просто падал с ошибкой timeout handle_call. При чем тот call, на котором он падал ничего не делал с ets, в других был lookup.  

7 июня 2016 г., 10:45 пользователь Maxim Filipovich <fat...@gmail.com> написал:
Reply all
Reply to author
Forward
0 new messages