Cache integration examples

git-svn-id: https://svn.php.net/repository/phpdoc/en/trunk@324246 c90b9560-bf6c-de11-be94-00142212c4b1
This commit is contained in:
Ulf Wendel 2012-03-14 17:31:20 +00:00
parent 902cbcc2df
commit 18ac0c56e9

View file

@ -1510,6 +1510,206 @@ var_dump($res->fetch_assoc());
</example>
</para>
</section>
<section xml:id="mysqlnd-ms.quickstart.cache">
<title>Cache integration</title>
<note>
<title>Version requirement and dependencies</title>
<para>
Cache integration is available as of PECL/mysqlnd_ms 1.3.0-beta (under development).
PECL/mysqlnd_qc 1.1.0 (under development) or newer is used as a cache. Both plugins
must be installed. PECL/mysqlnd_ms must be compiled to support the cache feature.
Use of PHP 5.4.0 or newer is mandatory.
</para>
</note>
<para>
Databases clusters can deliver different levels of consistency. As of
PECL/mysqlnd_ms 1.2.0 it is possible to advice the plugin to consider only
cluster nodes that can deliver the consistency level requested. For example,
if using asynchronous MySQL Replication with its cluster-wide eventual
consistency, it is possible to request session consistency (read your writes)
at any time using <function>mysqlnd_ms_set_quos</function>. Please, see also the
<link linkend="mysqlnd-ms.quickstart.qos-consistency">service level and consistency</link>
introduction.
</para>
<para>
<example>
<title>Recap: quality of service to request read your writes</title>
<programlisting role="php">
/* Request session consistency: read your writes */
if (!mysqlnd_ms_set_qos($mysqli, MYSQLND_MS_QOS_CONSISTENCY_SESSION))
die(sprintf("[%d] %s\n", $mysqli->errno, $mysqli->error));
</programlisting>
</example>
</para>
<para>
Assuming PECL/mysqlnd has been explicitly told to deliver no consistency level
higher than eventual consistency, it is possible to replace a database node
read access with a client-side cache using time-to-live (TTL) as its invalidation
strategy. Both the database node and the cache may or may not serve
current data as this is what eventual consistency defines.
</para>
<para>
Replacing a database node read access with a local cache access can improve
overall performance and lower the database load. If the cache entry is every
reused by other clients than the one creating the cache entry,
a database access is saved and thus database load is lowered. Furthermore,
system performance can become better if computation and delivery
of a database query is slower than a local cache access.
</para>
<para>
<example>
<title>Plugin config: no special entries for caching</title>
<programlisting role="ini">
<![CDATA[
{
"myapp": {
"master": {
"master_0": {
"host": "localhost",
"socket": "\/tmp\/mysql.sock"
}
},
"slave": {
"slave_0": {
"host": "127.0.0.1",
"port": "3306"
}
},
}
}
]]>
</programlisting>
</example>
</para>
<para>
<example>
<title>Caching a slave request</title>
<programlisting role="php">
<![CDATA[
<?php
$mysqli = new mysqli("myapp", "username", "password", "database");
if (!$mysqli)
/* Of course, your error handling is nicer... */
die(sprintf("[%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()));
if (!$mysqli->query("DROP TABLE IF EXISTS test") ||
!$mysqli->query("CREATE TABLE test(id INT)") ||
!$mysqli->query("INSERT INTO test(id) VALUES (1)"))
die(sprintf("[%d] %s\n", $mysqli->errno, $mysqli->error));
/* Explicitly allow eventual consistency and caching (TTL <= 60 seconds) */
if (false == mysqlnd_ms_set_qos($mysqli, MYSQLND_MS_QOS_CONSISTENCY_EVENTUAL, MYSQLND_MS_QOS_OPTION_CACHE, 60)) {
die(sprintf("[%d] %s\n", $mysqli->errno, $mysqli->error));
}
/* To make this example work, we must wait for a slave to catch up. Brute force style. */
$attempts = 0;
do {
/* check if slave has the table */
if ($res = $mysqli->query("SELECT id FROM test")) {
break;
} else if ($mysqli->errno) {
die(sprintf("[%d] %s\n", $mysqli->errno, $mysqli->error));
}
/* wait for slave to catch up */
usleep(200000);
} while ($attempts++ < 10);
/* Query has been run on a slave, result is in the cache */
assert($res);
var_dump($res->fetch_assoc());
/* Served from cache */
$res = $mysqli->query("SELECT id FROM test");
?>
]]>
</programlisting>
</example>
</para>
<para>
The example shows how to use the cache feature. First, you have to set
the quality of service to eventual consistency and explicitly allow for caching.
This is done by calling <function>mysqlnd_ms_set_qos</function>.
Then, the result set of every read-only statement is cached for upto that
many seconds as allowed with <function>mysqlnd_ms_set_qos</function>.
</para>
<para>
The actual TTL is lower or equal to the value set
with <function>mysqlnd_ms_set_qos</function>. The value passed to the
function sets the maximum age (seconds) of the data delivered. To calculate
the actual TTL value the replication lag on a slave is checked and substracted
from the given value. If, for example, the maximum age is set to 60 seconds and
the slave reports a lag of 10 seconds the resulting TTL is 50 seconds.
The TTL is calculated individually for every cached query.
</para>
<para>
<example>
<title>Read your writes and caching combined</title>
<programlisting role="php">
<![CDATA[
<?php
$mysqli = new mysqli("myapp", "username", "password", "database");
if (!$mysqli)
/* Of course, your error handling is nicer... */
die(sprintf("[%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()));
if (!$mysqli->query("DROP TABLE IF EXISTS test") ||
!$mysqli->query("CREATE TABLE test(id INT)") ||
!$mysqli->query("INSERT INTO test(id) VALUES (1)"))
die(sprintf("[%d] %s\n", $mysqli->errno, $mysqli->error));
/* Explicitly allow eventual consistency and caching (TTL <= 60 seconds) */
if (false == mysqlnd_ms_set_qos($mysqli, MYSQLND_MS_QOS_CONSISTENCY_EVENTUAL, MYSQLND_MS_QOS_OPTION_CACHE, 60)) {
die(sprintf("[%d] %s\n", $mysqli->errno, $mysqli->error));
}
/* To make this example work, we must wait for a slave to catch up. Brute force style. */
$attempts = 0;
do {
/* check if slave has the table */
if ($res = $mysqli->query("SELECT id FROM test")) {
break;
} else if ($mysqli->errno) {
die(sprintf("[%d] %s\n", $mysqli->errno, $mysqli->error));
}
/* wait for slave to catch up */
usleep(200000);
} while ($attempts++ < 10);
assert($res);
/* Query has been run on a slave, result is in the cache */
var_dump($res->fetch_assoc());
/* Served from cache */
if (!($res = $mysqli->query("SELECT id FROM test")))
die(sprintf("[%d] %s\n", $mysqli->errno, $mysqli->error));
var_dump($res->fetch_assoc());
/* Update on master */
if (!$mysqli->query("UPDATE test SET id = 2"))
die(sprintf("[%d] %s\n", $mysqli->errno, $mysqli->error));
/* Read your writes */
if (false == mysqlnd_ms_set_qos($mysqli, MYSQLND_MS_QOS_CONSISTENCY_SESSION)) {
die(sprintf("[%d] %s\n", $mysqli->errno, $mysqli->error));
}
/* Fetch latest data */
if (!($res = $mysqli->query("SELECT id FROM test")))
die(sprintf("[%d] %s\n", $mysqli->errno, $mysqli->error));
var_dump($res->fetch_assoc());
?>
]]>
</programlisting>
</example>
</para>
<para>
The quality of service can be changed at any time to avoid further cache usage.
If needed, you can switch to read your writes (session consistency). In that case,
the cache will not be used and fresh data is read.
</para>
</section>
</chapter>
<!-- Keep this comment at the end of the file
Local variables: