use MySQL server as "cache" - php

I know this is a weird question but I have 2 servers, one a vps and another, a mysql host. Now my issue is that I want to try and lower the load on the vps as it is a startup 128mb vps.
Slight problem, what would be required to make the MySQL server work as if it were a cache, I have no access to anything on the MySQL server save the databases im given.
Will this require a separate database? please tell me so if it is possible i can ask my host to add another database.
Thanks!

If you host a website on the VPS that uses MySQL as the database, a typical request goes like this:
the client makes a request to the web server running on your VPS
your script running inside the web server makes a database query
the database returns the query results
your script formats and prints the results
the results appear in the browser (client)
There is no way to make a request hit the database without going through the web server first.
If you want to lighten the load on the VPS you can make your script run faster. The most time-consuming part of most web applications is making database queries and waiting for the results. You can, in a lot of cases, avoid that by caching the results of your database queries on the VPS using an in-memory cache like memcached. Be careful with the memory settings though - be sure to set the maximum allocated memory to a sufficiently low setting because your server has very little memory.
Here is a basic example of caching the result of a SELECT query:
$cache = new Memcached();
$cache->addServer('localhost', 11211);
$article_key = "article[$article_id]";
$article = $cache->get($article_key);
if ($article === FALSE) {
$statement = $conn->prepare("SELECT * FROM articles WHERE id = :id");
$statement->exec(array('id' => $article_id));
$result = $statement->fetchAll(PDO::FETCH_ASSOC);
if (count($result) === 0) {
// return a 404 status
}
$article = $result[0];
$cache->set($article_key, $article);
}
// display the article

Related

Memcache add key to specific memcached server

I have add two memcached servers to my web app with the following code:
$servers = array(
array('xxx.xxx.xxx.185', 11211),
array('xxx.xxx.xxx.10', 11211)
);
global $m;
$m = new Memcached('persistant-id');
if (0 == count($m->getServerList())) {
error_log("add memcache servers num: " . count($m->getServerList()));
return $m->addServers($servers);
}
I want to add the key/values to specific server.
How can I add a specific key for example to xxx.xxx.xxx.185 server?
I wonder in the web and find the addByKey($serverKey, $key, $value, $expiration = null) but I can't find what is the $serverKey.
Any help?
I don't think you can pick a specific server by ip to store the data on when using a pooled connection (I could be wrong, but haven't seen anything to the contrary). It's my understanding in the *ByKey() functions, the $serverKey is just an arbitrary grouping you can assign. You are not picking which server the data is stored on, only specifying that you want all items added with that $serverKey to end up on the same server.
The only sure fire way I know of to guarantee data ends up on a specific server would be to create the connection and only add the data to that specific server.
A less than ideal alternative suggestion I can think of trying (which I have no idea if it would work, and is purely a hypothesis), would be create a connection to just the xxx.185 server, add a single item with whatever $serverKey you want, then create a pooled connection, add a bunch of items using that same $serverKey, and then use the getServerByKey() method to see if all the data you added all ended up on the same server.
If so, you would just have to seed the server you want with all the $serverKey's you use.
If both servers show up, then the $serverKey might be specific to the connection and not the available data set.
But this is not an ideal solution, particularly with the volatility of the memcached data, if this works at all (Like I said, never tried it, it's purely a guess). You'd have to re-seed the server every time your memcached restarts or all the data with that $serverKey is discarded for more room
Hope that helps

How do I make query faster with PHP?

I have a problem with the time to query my database with PHP. I recently started creating an MMO RPG ONLINE using the program engine001, I also use PHP and MySQL to query info of my database but it takes too long to make a query (it usually takes one sec to query).
Steps:
First of all I query a webpage of my website which has the .php file (site.com/file.php)
This php file, will query into my database
This is printed (echo) at the page so my game pick the value e then make whatever it wants.
Here we have an example, this PHP file will send the new position of an actor:
include("mysqlconfig.inc");
$id = $_REQUEST['id'];
$positionX = $_REQUEST['positionX'];
$positionY = $_REQUEST['positionY'];
$query = "UPDATE players SET positionX = '$positionX',positionY = '$positionY' WHERE ID = $id ";
$res = mysql_query($query);
mysql_close($con);
I have no idea how online games are made and why they are so fast but this is how I do mine. It's the only way I figured out how to do that.
My question is, is there any way to make it a little bit faster?
I don't think this approach will ever be fast enough for a real time game. As you have discovered, making database queries for things like player positions is far too slow. Real time games do not typically use web-based backends because HTTP is a stateless protocol, but you need to have the game state persist in the process's memory to make it fast enough. So you will probably have to look at writing the backend as a custom server using sockets.

Speeding Up Image Loading from DB

I'm loading 9 images from a database and my syntax looks roughly like this:
<img src="image_loader.php?id=4"></img>
My PHP for image_loader.php looks like:
<?php
/* I set up my connection using mysql_connect and mysql_select_db */
$query = sprintf("SELECT ... FROM ... WHERE id='".$_GET["id"]."'");
$result = mysql_query($query, $con);
mysql_close($con);
if (!$result) {
// no result
}
else {
$row = mysql_fetch_row($result);
header('Content-type: image/png');
echo $row[0];
mysql_free_result($result);
}
?>
Each image is about 10-13k but the bunch seems to be loading very slow. I realize that there is some bottle-necking in the number of requests a browser can execute at a time but the wait times seem to be gratuitous.
Any suggestions on how to get images loaded from a database fast?
Also, and this is almost a separate question, but is it possible to instruct a browser (or server) to cache images with now .gif/.png/.jpg srcs? It seems that Firefox does and Chrome doesn't, but I'm not certain of this.
I'd first consider whether storing images in a database makes the most sense. It may, but it should be seriously considered, as giving each image a unique filename in the filesystem and storing that in the database will often be faster.
You would gain additional speed if you could request that file directly from the client as opposed to requesting a generic PHP script that does some sort of fopen()-style abstraction.
In order to narrow down the source of delay, it first might be helpful to check whether your database is hosted on the same server as your webserver. One indication that it is not hosted locally but on a remote database server is to check the host string you're providing in the mysql_connect() call. localhost would suggest its local, something else would suggest it's not. As a note, many shared hosted services (e.g. GoDaddy) split their database server from the webserver.
For a better idea of the source of the delay, I'd suggest instrumenting your image_loader.php code with timestamps to locate the delay? My guess is that it'll be in the query.
If the delay is in your query, you will want to limit the number of queries you make. A strategy that allows you to make one query instead of 9 would limit the impact any webserver-to-database server delay.

How does memcache with MySQL work?

I am trying to understand (and probably deploy) memcached in our env.
We have 4 web servers on loadbalancer running a big web app developed in PHP. We are already using APC.
I want to see how memcached works? At least, may be I don't understand how caching works.
We have some complex dynamic queries that combine several tables to pull data. Each time, the data is going to be from different client databases and data keeps changing. From my understanding, if some data is stored in cache, and if the request is same next time, the same data is returned. (Or I may be completely wrong here).
How does this whole memcache (or for that matter, any caching stuff works)?
Cache, in general, is a very fast key/value storage engine where you can store values (usually serialized) by a predetermined key, so you can retrieve the stored values by the same key.
In relation to MySQL, you would write your application code in such a way, that you would check for the presence of data in cache, before issuing a request to the database. If a match was found (matching key exists), you would then have access to the data associated to the key. The goal is to not issue a request to the more costly database if it can be avoided.
An example (demonstrative only):
$cache = new Memcached();
$cache->addServer('servername', 11211);
$myCacheKey = 'my_cache_key';
$row = $cache->get($myCacheKey);
if (!$row) {
// Issue painful query to mysql
$sql = "SELECT * FROM table WHERE id = :id";
$dbo->prepare($sql);
$stmt->bindValue(':id', $someId, PDO::PARAM_INT);
$row = $stmt->fetch(PDO::FETCH_OBJ);
$cache->set($myCacheKey, serialize($row));
}
// Now I have access to $row, where I can do what I need to
// And for subsequent calls, the data will be pulled from cache and skip
// the query altogether
var_dump(unserialize($row));
Check out PHP docs on memcached for more info, there are some good examples and comments.
There are several examples on how memcache works. Here is one of the links.
Secondly, Memcache can work with or without MySQL.
It caches your objects which are in PHP, now whether it comes from MySQL, or anywhere else, if its an PHP Object, it can be stored in MemCache.
APC gives you some more functionality than Memcache. Other than storing/caching PHP objects, it also caches PHP-executable-machine-readable-opcodes so that your PHP files won't go through the processes of loading in memory-> Being Comiled, rather, it directly runs the already compiled opcode from the memory.
If your data keeps changing(between requests) then caching is futile, because that data is going to be stale. But most of the times(I bet even in your cache) multiple requests to database result in same data set in which case a cache(in memory) is very useful.
P.S: I did a quick google search and found this video about memcached which has rather good quality => http://www.bestechvideos.com/2009/03/21/railslab-scaling-rails-episode-8-memcached. The only problem could be that it talks about Ruby On Rails(which I also don't use that much, but is very easy to understand). Hopefully it is going to help you grasp the concept a little better.

How do odbc (or mysql) resources work in php?

When you run a query like so:
$query = "SELECT * FROM table";
$result = odbc_exec($dbh, $query);
while ($row = odbc_fetch_array($result)) {
print_r($row);
}
Does the resource stored in $result point to data that exists on the server running php? Or is pointing to data in the database? Put another way, as the while loop does it's thing ,is PHP talking to the DB every iteration or is it pulling that $row from some source on the application side?
Where this is mattering to me is I have a database I'm talking to over VPN using ODBC with PHP. This last weekend something strange has happened where huge pauses are happening during the while loop. So between iterations, the script will stop execution for seconds and up to minutes. It seems to be completely random where this happens. I'm wondering if I need to talk to the server over VPN each iteration and maybe the connection is flaky or if something has gone wrong with my ODBC driver (FreeTDS).
mysql_query and odbc_exec both return a resource which (quote from php.net) "is a special variable, holding a reference to an external resource." This suggests the server is talking with the database server every iteration, I am not sure though.
However, there are 2 connections we are talking about here. The first being your connection with the PHP server, and the second one being the connection between the PHP server and the database server. If both servers have a fast connection, the strange behaviour you are experiencing might not have anything to do with your VPN.
The resource identifies the internal data structure used by PHP for interacting with the external resource.
In the case of the resource returned by mysql_query(), this data structure will include the rows returned by the query (and won't return until all the data has been returned or the conenction fails). However this behaviour is specific to MySQL - there is no requirement that the DBMS return the data before it is explicitly requested by the client.
If there is some strange problem causing lots of latency in your setup, then the only obvious solution would be to compile the results of the query at the database side then deliver them to your PHP code, aither batched or as a whole (think webservice).
C.

Categories