mysql-proxy + memcached -- Инсталиране и конфигуриране

Идеята е да се обедини mysql-proxy + memcache. Защо ?
Защото искам всяка select заявка да се кешира в memcache. Ако не е кеширана да я кешира и при следващо извикване да я извлича от memcache.

Защо не се пусне само memcache и от самото php да се свързва към memcache демона ?

Защото по този метод (разгледана в публикацията) не се налага да се променя кода на писане т.е. просто се php приложението се свързва към localhost:4040 вместо към localhost (порта 4040 може да бъде променян разбира се, дори и на 3306 )

aptitude install lua5.1 liblua5.1-md5-0 liblua5.1-socket2 luarocks memcached mysql-proxy
mkdir /tmp/mysql-proxy-memcache-temp;
cd /tmp/mysql-proxy-memcache-temp;

wget http://luaforge.net/frs/download.php/4041/liblua5.1-memcached0.deb
wget http://luamemcached.googlecode.com/files/liblua5.1-memcached0.deb

wget http://luarocks.org/releases/luarocks-2.0.4.1.tar.gz

tar zxvf luarocks-2.0.4.1.tar.gz

./configure
make
make install;

luarocks install md5

cd /tmp/mysql-proxy-memcache-temp;
wget http://luaforge.net/frs/download.php/4542/luamemcached.0.7.tar.gz
tar xzvf luamemcached.0.7.tar.gz
mv *.lua /usr/local/share/lua/5.1/
luarocks install luasocket

cp mysql-proxy-cache.lua /usr/share/mysql-proxy/

mysql-proxy --proxy-lua-script=/usr/share/mysql-proxy/mysql-proxy-cache.lua

Код на mysql-proxy-cache.lua :

require('luarocks.require')
require('md5')
require('Memcached')
local memcache = Memcached.Connect()
cache_hits = 0
cache_misses = 0
cache_timeout = 30
function is_query(packet)
return packet:byte() == proxy.COM_QUERY
end

function is_cacheable(query)
return query:sub(1,6):lower() == 'select'
end

function to_hash(query)
db = proxy.connection.client.default_db
return md5.sumhexa(query..'db'..db)
end

function cache_get(query)
db = proxy.connection.client.default_db
local result = deserialize(memcache:get(to_hash(query)))
if result then
print('HIT: '..to_hash(query)..' ('..query..') DB:'..db)
cache_hits = cache_hits + 1
else
print('MISS: '..to_hash(query)..' ('..query..') DB:'..db)
cache_misses = cache_misses + 1
end

print('Cache hit ratio: '..cache_hits..'/'..cache_misses..' = '..cache_hits/cache_misses..' DB:'..db)

return result
end

function cache_set(result_packet)
local resultset_is_needed = false
local query = result_packet.query:sub(2)
local field_count = 1
local fields = result_packet.resultset.fields
local resultset = {rows={}, fields={}}

print('SET: '..to_hash(query)..' ('..query..')')

while fields[field_count] do
local field = fields[field_count]
--added third option, expiry time.
table.insert(resultset.fields, {type=field.type, name=field.name} )
field_count = field_count + 1
end

for row in result_packet.resultset.rows do
table.insert(resultset.rows, row)
end

memcache:set(to_hash(query), serialize(resultset), cache_timeout)
end

function serialize(o)
local result = {}
local o_type = type(o)

if o_type == "number" then
table.insert(result, o)

elseif o_type == "string" then
table.insert(result, string.format("%q", o))

elseif o_type == "table" then
table.insert(result, "{")
for key, value in pairs(o) do
for i, str in pairs({"[", serialize(key), "]=",
serialize(value), ","}) do
table.insert(result, str)
end
end
table.insert(result, "}")

elseif o_type == "nil" then
table.insert(result, "nil")

else
error("cannot serialize a " .. o_type)
end

return table.concat(result, ")
end

function deserialize(s)
if s then
return loadstring('return '..s)()
else
return nil
end
end

function read_query( packet )
if is_query(packet) then
local query = packet:sub(2)

if is_cacheable(query) then
local resultset = cache_get(query)
if resultset then
--- Cache hit
proxy.response.type = proxy.MYSQLD_PACKET_OK
proxy.response.resultset = resultset

return proxy.PROXY_SEND_RESULT
else
--- Cache miss
proxy.queries:append(1, packet,{resultset_is_needed = true})

return proxy.PROXY_SEND_QUERY
end
end
end
end

function read_query_result(result_packet)
--- This only gets called if the proxy.queries queue is modified
cache_set(result_packet)
end

PS: Нямах намерение да пиша тази публикация, но я написах защото Благо беше казал, че ще му бъде интересно това решение. Ето Благо,  специално за теб :P

VN:F [1.9.22_1171]
Rating: 5.0/5 (1 vote cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)
mysql-proxy + memcached - Инсталиране и конфигуриране, 5.0 out of 5 based on 1 rating

6 thoughts on “mysql-proxy + memcached -- Инсталиране и конфигуриране”

  1. Хммм доста интересно. Преди гони бях пробвал mysql_proxy-то и беше бъгаво ама товага беше в началните стадии на разработка. Интересно какво подобрението при производителноста с mem cache на заявките.

    VA:F [1.9.22_1171]
    Rating: 0.0/5 (0 votes cast)
    VA:F [1.9.22_1171]
    Rating: 0 (from 0 votes)
  2. Pingback: Ново 20
  3. ДОСТА сериозно е подобрението, но под доста не мога да ти конкретизирам със стойност, понеже не съм ги записвал. Може да го пуснеш да работи по този начин и да направиш тази статистика. Мисля, че доста хора биха се заинтересували от този експеримент ;)

    VN:F [1.9.22_1171]
    Rating: 0.0/5 (0 votes cast)
    VN:F [1.9.22_1171]
    Rating: 0 (from 0 votes)
  4. Какво става ако данните в таблицата са променени в интервала от времето между различните SELECT-ове? Инвалидира ли се кеша по някакъв начин?
    Проксито прозрачно ли е? Ако случаен клиент се върже към сървъра на порт 3306 дефаултния демон ли ще намери или проксито?
    Питам пак във връзка с инвалидирането :) Да не се случи някой да се върже и да променя данни, а проксито да връща все едни и същи неща на моето приложение.

    VA:F [1.9.22_1171]
    Rating: 0.0/5 (0 votes cast)
    VA:F [1.9.22_1171]
    Rating: 0 (from 0 votes)
  5. като се вържеш към 3306 разбира се, че няма никакво прокси, а директна връзка към mysql. По другият начин с прокси се запазва в memcache и минава timeout за да изтрие стария кеш(резултат) и да направи нов.

    VN:F [1.9.22_1171]
    Rating: 0.0/5 (0 votes cast)
    VN:F [1.9.22_1171]
    Rating: 0 (from 0 votes)
  6. По-добре ми се струва да оставиш на MySQL да управлява кеша, тоест да дадеш на MySQL сървъра да използва паметта, която си заделил за memcache.

    Бтв, ако използваш mysql proxy + memcache, то е добре да изключиш кеша на mysql. В противен случай ще имаш два кеша.

    VA:F [1.9.22_1171]
    Rating: 0.0/5 (0 votes cast)
    VA:F [1.9.22_1171]
    Rating: 0 (from 0 votes)

Вашият коментар

Вашият email адрес няма да бъде публикуван Задължителните полета са отбелязани с *