Модераторы: skyboy, MoLeX, Aliance, ksnk
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Алгоритм выбора прокси, Для наименьшего времени скачивания 
:(
    Опции темы
teroni
Дата 5.10.2007, 13:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 381
Регистрация: 15.5.2007
Где: Днепропетровск

Репутация: 3
Всего: 22



Проблема скорее теоретического характера...
Я скачиваю через прокси файлы (их очень много).
Самих прокси тоже много, все они публичные - и, как следствие этого, работают не всегда.
То есть при скачивании файла довольно-таки часто ответ не приходит через время, указанное в таймауте.
Для хранения прокси использую табличку с такими полями:
proxy_id => просто номер прокси;
proxy => собственно ip:port;
failed_times => сколько раз подряд прокси не дает скачать файл (если только что скачал, то 0, если  последние n раз через эту прокси скачать не получилось - то n);
success => количество файлов, которые удалось скачать через эту прокси;
fail => количество файлов, которые не получилось скачать через эту прокси;
sum_time => общее время, за которое были выкачаны файлы, указанные в поле success.
При каждом шаге работы скрипта данные в этой таблице обновляются.

Вопрос такой... Как нужно выбирать следующую прокси для того, чтобы общее время на скачивание всех файлов было минимально?
Сейчас выбираю так:
Код

SELECT * FROM `proxy` ORDER BY `failed_times` LIMIT 0, 1

но этот путь, имхо, не оптимальный.


Сам принцип работы сейчас такой...
1. Делатся вышеуказанный запрос в базу.
2. Идет подключение  к полученной прокси.
3. Скачивается/не скачивается файл.
4. В БД происходит UPDATE инфы о прокси согласно результатам п.3.
5. Снова п.1.

Это сообщение отредактировал(а) teroni - 5.10.2007, 14:19
PM MAIL   Вверх
teroni
Дата 6.10.2007, 11:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 381
Регистрация: 15.5.2007
Где: Днепропетровск

Репутация: 3
Всего: 22



Код

SELECT * FROM `proxy`  ORDER BY ((`success`-2*`failed_times` - `fail`) / (`success` + `fail` + 1)) DESC  LIMIT 0, 1

пока сделал так.
PM MAIL   Вверх
ewolf
Дата 6.10.2007, 16:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 389
Регистрация: 15.8.2006
Где: г. Москва

Репутация: 2
Всего: 18



Этот вопрос не имеет непосредственного отношения к php или SQL, поскольку вся задача лежит в построении оптимальной оценочной функции, которая бы помогла выбрать лучшую проксю на данный момент.

По выбраной тобой функции возникает вопрос: зачем нужен делитель (`success` + `fail` + 1)? Почему нельзя обойтись просто линейной функцией (`success`-2*`failed_times` - `fail`)?
PM MAIL ICQ   Вверх
teroni
Дата 6.10.2007, 23:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 381
Регистрация: 15.5.2007
Где: Днепропетровск

Репутация: 3
Всего: 22



Ну я согласен, что к php или SQL вопрос имеет слабое отношение... Скорей к математике...
Да выбирал просто пальцем в небо... Видимо, он действительно и не нужен..
Плюс сейчас у меня вообще в этой функции никак не участвует время sum_time, а мне кажется оно тоже должно в ней быть, т.к. некоторые прокси скачивают файл очень быстро, а некоторые почти за время до таймаута.
PM MAIL   Вверх
ewolf
Дата 7.10.2007, 14:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 389
Регистрация: 15.8.2006
Где: г. Москва

Репутация: 2
Всего: 18



А в каких величинах выражается sum_time?

Можно попробовать несколько модифицировать функцию, например так

success - 2 * failed_times - fail - sum_time / (success + 1) / norm

где norm - нормирующая составляющая, что бы привести величину sum_time / (success+1) в соотвествие с остальными компонентами.

Можно поступить и еще проще - сделать сортировку по двум полям

Код

SELECT * FROM `proxy`  ORDER BY (`success`-2*`failed_times` - `fail`) DESC, sum_time / (success+1) ASC  LIMIT 0, 1

PM MAIL ICQ   Вверх
teroni
Дата 9.10.2007, 14:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 381
Регистрация: 15.5.2007
Где: Днепропетровск

Репутация: 3
Всего: 22



Сразу не додумался, но похоже вот этот запрос самый лучший:
Код

SELECT * FROM `proxy`  ORDER BY ((`sum_time` + `fail` * 20) / (`success` + 1)) LIMIT 0 , 1

(20 - это значение таймаута).
PM MAIL   Вверх
Alternator
Дата 17.3.2009, 15:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 18
Регистрация: 10.6.2007

Репутация: нет
Всего: 1



не сочтите за некропост.
рискну предложить. может кому понадобится свой вариант
собственно таблица(я ее видоизменил):
Код

CREATE  TABLE IF NOT EXISTS `plr_market`.`proxy` (
  `id_proxy` INT NOT NULL AUTO_INCREMENT ,
  `proxy` VARCHAR(22) NOT NULL COMMENT 'собственно ip:port' ,
  `success_times` INT UNSIGNED NOT NULL DEFAULT 0 COMMENT 'сколько раз подряд прокси дал скачать файл в последний раз' ,
  `success` INT UNSIGNED NOT NULL DEFAULT 0 COMMENT 'количество файлов, которые удалось скачать через эту прокси' ,
  `fail` INT UNSIGNED NOT NULL DEFAULT 0 COMMENT 'количество файлов, которые не получилось скачать через эту прокси' ,
  `sum_size` INT UNSIGNED NOT NULL DEFAULT 0 COMMENT 'сколько было перекачано успешно' ,
  `sum_time` FLOAT UNSIGNED NOT NULL DEFAULT 0 COMMENT 'общее время, за которое были выкачаны файлы, указанные в поле success' ,
  `last_success` TIMESTAMP NULL DEFAULT NULL COMMENT 'последня удача' ,
  `last_fail` TIMESTAMP NULL DEFAULT NULL COMMENT 'последняя неудача' ,
  `relevance` FLOAT NOT NULL DEFAULT 0 COMMENT 'релевантность.\nсчитается при update-ах' ,
  PRIMARY KEY (`id_proxy`) ,
  UNIQUE INDEX `proxy` (`proxy`(22) ASC) )
ENGINE = MyISAM;

запросы:
Код

-- добавление прокси
INSERT INTO `proxy`(`proxy`)
    VALUES('127.0.0.1:80')
-- обновление строки с проксей, если была удача
UPDATE `proxy` SET
    `success_times`=`success_times`+1,
    `success`=`success`+1,
    `sum_size`=`sum_size`+1234, -- сколько байтов было принято
    `sum_time`=`sum_time`+1.234, -- время закачки файла
    `last_success`=NOW(),
    `relevance`=
            (`sum_size`/(`sum_time`+fail*20+1))*
            (`success`/(`fail`+1))
    WHERE `proxy`='127.0.0.1:80' -- обновляемый прокси
-- обновление строки с проксей, если была НЕудача
UPDATE `proxy` SET
    `success_times`=0,
    `fail`=`fail`+1,
    `last_fail`=NOW(),
    `relevance`=
            (`sum_size`/(`sum_time`+fail*20+1))*
            (`success`/(`fail`+1))
    WHERE `proxy`='127.0.0.1:80' -- обновляемый прокси
-- получение наиболее релевантного прокси
( -- сперва те, которые еще ни разу не использовались
SELECT `proxy`  FROM `proxy`
    WHERE
        `last_fail` IS NULL AND `last_success` IS NULL
)
UNION
( -- те которые еще не потерпели ни одной неудачи
SELECT `proxy`  FROM `proxy`
    WHERE
        `last_fail` IS NULL AND NOT(`last_success` IS NULL)
)
UNION
( -- те, которые последний раз терпели неудачу более часа назад(а вдруг работают уже)
SELECT `proxy`  FROM `proxy`
    WHERE
        (UNIX_TIMESTAMP()-UNIX_TIMESTAMP(`last_fail`))>=3600
    ORDER BY
        `relevance`*
        ((UNIX_TIMESTAMP()-UNIX_TIMESTAMP(`last_fail`))/(UNIX_TIMESTAMP()-UNIX_TIMESTAMP(`last_success`)))
        DESC
)
UNION
( -- те, которые последний раз терпели неудачу менее часа назад(навряд ли востановились)
SELECT `proxy`  FROM `proxy`
    WHERE
        (UNIX_TIMESTAMP()-UNIX_TIMESTAMP(`last_fail`))<3600
    ORDER BY
        `relevance`*
        ((UNIX_TIMESTAMP()-UNIX_TIMESTAMP(`last_fail`))/(UNIX_TIMESTAMP()-UNIX_TIMESTAMP(`last_success`)))
        DESC
)
    LIMIT 1

в моем варианте релевантность вычисляется в отдельное поле при  UPDATE-ах, чтобы разгрузить базу слегка

релевантность у меня пропорциональна скорости передаваемых данных(средней),отношению количества удачных попыток к неудачным, и отношению "как давно была неудача" к "как давно была удача"
смена прокси предполагается после N неудачных попыток(это контролируется на уровне приложения а не базы)
через час(3600 секунд) после ряда неудач, прокси снова может быть взят для новой попытки(ранее, если не из чего выбирать)
таким образом, если час за часом, при каждой новой попытке получить доступ к прокси, он не работает, его релевантность резко падает(в 24 раза, после суток простоя), но если заработает снова, то его релевентность будет востановлена снова до максимума
полагаю(еще не провериял), стоит обернуть 
Код

((UNIX_TIMESTAMP()-UNIX_TIMESTAMP(`last_fail`))/(UNIX_TIMESTAMP()-UNIX_TIMESTAMP(`last_success`)))

в какую-нибудь функцию.потому что релевантность будет зашкаливать, если например 2 часа назад была неудача, а секунду назад была удача.надо над этим еще подумать

Это сообщение отредактировал(а) Alternator - 18.3.2009, 02:54
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | PHP: Базы Данных | Следующая тема »


 




[ Время генерации скрипта: 0.0502 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.