Система голосования PHP + MySQL ограничена IP - PullRequest
1 голос
/ 16 июля 2011

Мне нужно внедрить систему анонимного голосования (регистрация пользователей не нужна). Я решил, что лучший вариант - ограничить количество голосов по одному предмету до 10 на IP (для учета школ и т. Д.).

Какой лучший способ обойти это. Я использую PHP + MySQL. В часы пик может быть до 20 голосов в секунду. Я использую интерфейсы с балансировкой нагрузки с выделенным сервером MySQL.

Меня беспокоит вставка строки в базу данных для каждого голосования, а затем запрос этих данных, чтобы узнать, достигли ли они своего предела, может быть слишком много для сервера?

Лучше бы я посмотрел на MongoDB или еще что-нибудь?

Есть еще идеи?

Ответы [ 6 ]

4 голосов
/ 16 июля 2011

Я бы предложил сохранить статус «проголосовал» в куки.Это позволит целым школам и офисам голосовать.Выполнение этого по 10 на IP позволит одному пользователю по адресу голосовать 10 раз.

Очевидно, что есть способы обойти это, например очистить куки и т. Д., Но я думаю, что это хороший вариант.

3 голосов
/ 16 июля 2011

Я думаю, что базы данных ключ / значение будут здесь лучше.
Кроме того, вам не нужна строка для каждого голосования, вам нужна только 1 строка для каждого IP и использовать запросы LIKE

INSERT INTO .. ON DUPLICATE KEY UPDATE
2 голосов
/ 16 июля 2011

Мне нужно внедрить систему анонимного голосования (регистрация пользователей не нужна)

IP-адреса не способ решить эту проблему, потому что многие компании / школы имеют тысячилюдей, сопоставленных только с парой IP-адресов.Если вы не хотите, чтобы пользователи входили в систему из-за анонимного голосования, я бы посоветовал вам использовать CAPTCHA (recaptcha) для защиты массового голосования, поскольку опытный программист может обойти все другие методы.Можно даже подделать IP-адрес .Я считаю, что во многих дистрибутивах Linux вы можете легко подделать IP-адреса.

alfred@alfred-laptop:~/bash$ apt-cache search ^fake$
fake - IP address takeover tool

http://en.wikipedia.org/wiki/IP_address_spoofing#Defense_against_spoofing:

Рекомендуется также разрабатывать сетевые протоколы и службы таким образом, чтобы онине полагайтесь на IP-адрес источника для аутентификации.

Но опытный программист не может обойти хорошо проверенные CAPTCHA, такие как recaptcha.Голосовать немного сложнее, но, на мой взгляд, это единственный способ противодействия поддельным голосованиям.Также капча не может сделать систему голосования неуязвимой для ошибочных голосов.Единственный способ создать такую ​​систему - использовать аутентификацию.Ведите список пользователей (личностей), которым разрешено голосовать.

Какой лучший способ обойти это.Я использую PHP + MySQL.В пиковое время может быть до 20 голосов в секунду.

Это даже не потеет Redis , потому что это безумно быстро.

Redis - это расширенное хранилище значений ключей с открытым исходным кодом.Его часто называют сервером структуры данных, поскольку ключи могут содержать строки, хэши, списки, наборы и отсортированные наборы.

Сначала моя системная информация.Мне это нравится, но оно уже довольно старое.

-Computer-
Processor       : 2x Intel(R) Core(TM)2 Duo CPU     T7100  @ 1.80GHz
Memory      : 2051MB (1403MB used)
Operating System        : Ubuntu 10.10
User Name       : alfred (alfred)
Date/Time       : Sat 16 Jul 2011 07:53:20 PM CEST
-Display-
Resolution      : 1280x800 pixels
OpenGL Renderer     : Unknown
X11 Vendor      : The X.Org Foundation
-Multimedia-
Audio Adapter       : HDA-Intel - HDA Intel
-Input Devices-
 Power Button
 Lid Switch
 Sleep Button
 Power Button
 AT Translated Set 2 keyboard
 Dell Dell USB Keyboard
 Logitech Trackball
 PS/2 Logitech Wheel Mouse
 Video Bus
-Printers (CUPS)-
Canon-MP150     : <i>Default</i>
HP-Photosmart-b110
-SCSI Disks-
HL-DT-ST DVDRAM GSA-T20N
ATA WDC WD1600BEVS-2

Далее я собираюсь сравнить мой редис-сервер:

alfred@alfred-laptop:~/database/redis-2.2.0-rc4/src$ ./redis-server --version
Redis server version 2.1.12 (00000000:0)

alfred@alfred-laptop:~/database/redis-2.2.0-rc4/src$ ./redis-benchmark 
====== PING (inline) ======
  10000 requests completed in 0.23 seconds
  50 parallel clients
  3 bytes payload
  keep alive: 1

94.11% <= 1 milliseconds
97.77% <= 2 milliseconds
98.97% <= 3 milliseconds
99.02% <= 4 milliseconds
99.51% <= 6 milliseconds
99.88% <= 7 milliseconds
100.00% <= 7 milliseconds
44052.86 requests per second

====== PING ======
  10000 requests completed in 0.23 seconds
  50 parallel clients
  3 bytes payload
  keep alive: 1

87.97% <= 1 milliseconds
97.44% <= 2 milliseconds
98.83% <= 3 milliseconds
99.41% <= 4 milliseconds
99.51% <= 5 milliseconds
99.70% <= 6 milliseconds
100.00% <= 6 milliseconds
43478.26 requests per second

====== MSET (10 keys) ======
  10000 requests completed in 0.37 seconds
  50 parallel clients
  3 bytes payload
  keep alive: 1

11.02% <= 1 milliseconds
82.00% <= 2 milliseconds
93.94% <= 3 milliseconds
97.18% <= 4 milliseconds
98.17% <= 5 milliseconds
98.89% <= 6 milliseconds
99.44% <= 7 milliseconds
99.51% <= 9 milliseconds
99.52% <= 10 milliseconds
100.00% <= 10 milliseconds
26881.72 requests per second

====== SET ======
  10000 requests completed in 0.24 seconds
  50 parallel clients
  3 bytes payload
  keep alive: 1

86.50% <= 1 milliseconds
96.08% <= 2 milliseconds
97.45% <= 3 milliseconds
97.87% <= 4 milliseconds
99.02% <= 5 milliseconds
99.51% <= 6 milliseconds
99.52% <= 7 milliseconds
100.00% <= 7 milliseconds
40983.61 requests per second

====== GET ======
  10000 requests completed in 0.23 seconds
  50 parallel clients
  3 bytes payload
  keep alive: 1

86.06% <= 1 milliseconds
97.51% <= 2 milliseconds
98.89% <= 3 milliseconds
99.65% <= 4 milliseconds
100.00% <= 4 milliseconds
42553.19 requests per second

====== INCR ======
  10000 requests completed in 0.23 seconds
  50 parallel clients
  3 bytes payload
  keep alive: 1

90.72% <= 1 milliseconds
96.92% <= 2 milliseconds
98.12% <= 3 milliseconds
98.33% <= 4 milliseconds
99.27% <= 5 milliseconds
99.51% <= 7 milliseconds
100.00% <= 7 milliseconds
43103.45 requests per second

====== LPUSH ======
  10000 requests completed in 0.23 seconds
  50 parallel clients
  3 bytes payload
  keep alive: 1

87.92% <= 1 milliseconds
96.35% <= 2 milliseconds
98.26% <= 3 milliseconds
99.51% <= 7 milliseconds
100.00% <= 7 milliseconds
42735.04 requests per second

====== LPOP ======
  10000 requests completed in 0.24 seconds
  50 parallel clients
  3 bytes payload
  keep alive: 1

87.75% <= 1 milliseconds
96.67% <= 2 milliseconds
97.77% <= 3 milliseconds
98.64% <= 4 milliseconds
98.65% <= 5 milliseconds
99.80% <= 6 milliseconds
100.00% <= 6 milliseconds
41841.00 requests per second

====== SADD ======
  10000 requests completed in 0.23 seconds
  50 parallel clients
  3 bytes payload
  keep alive: 1

89.55% <= 1 milliseconds
96.56% <= 2 milliseconds
97.80% <= 3 milliseconds
98.76% <= 4 milliseconds
99.50% <= 5 milliseconds
99.63% <= 6 milliseconds
100.00% <= 6 milliseconds
42553.19 requests per second

====== SPOP ======
  10000 requests completed in 0.25 seconds
  50 parallel clients
  3 bytes payload
  keep alive: 1

88.12% <= 1 milliseconds
96.21% <= 2 milliseconds
97.45% <= 3 milliseconds
97.99% <= 4 milliseconds
98.53% <= 5 milliseconds
99.51% <= 6 milliseconds
100.00% <= 6 milliseconds
40322.58 requests per second

====== LPUSH (again, in order to bench LRANGE) ======
  10000 requests completed in 0.24 seconds
  50 parallel clients
  3 bytes payload
  keep alive: 1

89.41% <= 1 milliseconds
96.05% <= 2 milliseconds
97.76% <= 3 milliseconds
98.76% <= 4 milliseconds
99.01% <= 5 milliseconds
99.51% <= 7 milliseconds
99.96% <= 8 milliseconds
100.00% <= 8 milliseconds
42016.81 requests per second

====== LRANGE (first 100 elements) ======
  10000 requests completed in 0.40 seconds
  50 parallel clients
  3 bytes payload
  keep alive: 1

11.56% <= 1 milliseconds
76.23% <= 2 milliseconds
91.93% <= 3 milliseconds
94.47% <= 4 milliseconds
97.80% <= 5 milliseconds
99.23% <= 6 milliseconds
99.87% <= 9 milliseconds
100.00% <= 9 milliseconds
24937.66 requests per second

====== LRANGE (first 300 elements) ======
  10000 requests completed in 0.86 seconds
  50 parallel clients
  3 bytes payload
  keep alive: 1

2.28% <= 1 milliseconds
10.90% <= 2 milliseconds
35.68% <= 3 milliseconds
63.74% <= 4 milliseconds
86.00% <= 5 milliseconds
92.65% <= 6 milliseconds
94.96% <= 7 milliseconds
97.50% <= 8 milliseconds
98.04% <= 9 milliseconds
98.75% <= 10 milliseconds
99.56% <= 11 milliseconds
99.96% <= 12 milliseconds
100.00% <= 12 milliseconds
11682.24 requests per second

====== LRANGE (first 450 elements) ======
  10000 requests completed in 1.15 seconds
  50 parallel clients
  3 bytes payload
  keep alive: 1

1.13% <= 1 milliseconds
6.20% <= 2 milliseconds
10.38% <= 3 milliseconds
27.37% <= 4 milliseconds
53.45% <= 5 milliseconds
74.60% <= 6 milliseconds
89.41% <= 7 milliseconds
95.40% <= 8 milliseconds
98.04% <= 9 milliseconds
98.98% <= 10 milliseconds
99.46% <= 11 milliseconds
99.58% <= 12 milliseconds
99.73% <= 13 milliseconds
99.87% <= 14 milliseconds
100.00% <= 14 milliseconds
8695.65 requests per second

====== LRANGE (first 600 elements) ======
  10000 requests completed in 1.45 seconds
  50 parallel clients
  3 bytes payload
  keep alive: 1

0.52% <= 1 milliseconds
6.23% <= 2 milliseconds
10.67% <= 3 milliseconds
16.37% <= 4 milliseconds
27.51% <= 5 milliseconds
46.06% <= 6 milliseconds
60.82% <= 7 milliseconds
79.70% <= 8 milliseconds
90.96% <= 9 milliseconds
96.01% <= 10 milliseconds
97.99% <= 11 milliseconds
99.43% <= 12 milliseconds
99.90% <= 13 milliseconds
100.00% <= 13 milliseconds
6896.55 requests per second

Операция incr что вам нужно, и вы можете видеть, что моя система может справиться с этим 43103.45 requests per second.

Буду ли я лучше смотреть на MongoDB или что-то в этом роде?

Я бы порекомендовал redis как доказано выше.

1 голос
/ 16 июля 2011

10 является совершенно произвольным значением и не учитывает офисы, где могут быть сотни или даже тысячи людей за одним общедоступным IPv4-адресом. Не говоря уже о том, что вы потенциально позволяете людям голосовать десять раз.

Понятно, что это не надежное и не подходящее решение.

Найдите другой способ уникальной идентификации людей.

1 голос
/ 16 июля 2011

Балансировка нагрузки, как вы описали, должна быть в порядке. У выделенного сервера MySQL не должно быть проблем с такой частотой запросов. Я не думаю, что MongoDB поможет решить такую ​​проблему. Что-то вроде memcached намного эффективнее, но вам все равно придется отправлять данные в более постоянную базу данных MySQL в какой-то момент.

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

1 голос
/ 16 июля 2011

Просто убедитесь, что вы индексировали поле IP и рассматриваете его как нечто отличное от строки (например, целое число).Смотрите здесь для получения более подробной информации: http://daipratt.co.uk/mysql-store-ip-address/

Кроме того, идея cookie от adlawson хороша.Вы можете использовать оба, и, возможно, заставить IP-адрес просто вызвать предупреждение для вас, где вы можете перейти к некоторому экрану администратора и решить, выглядят ли эти IP как кто-то, кто пытается обмануть систему, а не как школа.

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

...