mysql大数据更新缓存_redis缓存mysql
Redis是一個key-value存儲系統。和Memcached類似,它支持存儲的value類型相對更多,包括string(字符串)、list(鏈表)、set(集合)和zset(有序集合)。這些數據類型都支持push/pop、add/remove及取交集并集和差集及更豐富的操作,而且這些操作都是原子性的。在此基礎上,redis支持各種不同方式的排序。與memcached一樣,為了保證效率,數據都是緩存在內存中。區別的是redis會周期性的把更新的數據寫入磁盤或者把修改操作寫入追加的記錄文件,并且在此基礎上實現了master-slave(主從)同步。
Redis 是一個高性能的key-value數據庫。 redis的出現,很大程度補償了memcached這類keyvalue存儲的不足,在部 分場合可以對關系數據庫起到很好的補充作用。它提供了Python,Ruby,Erlang,PHP客戶端,使用很方便。
在Redis中,并不是所有的數據都一直存儲在內存中的。這是和Memcached相比一個最大的區別。Redis只會緩存所有的key的信息,如果Redis發現內存的使用量超過了某一個閥值,將觸發swap的操作,Redis根據“swappability = age*log(sizeinmemory)”計算出哪些key對應的value需要swap到磁盤。然后再將這些key對應的value持久化到磁盤中,同時在內存中清除。這種特性使得Redis可以 保持超過其機器本身內存大小的數據。當然,機器本身的內存必須要能夠保持所有的key,畢竟這些數據是不會進行swap操作的。同時由于Redis將內存 中的數據swap到磁盤中的時候,提供服務的主線程和進行swap操作的子線程會共享這部分內存,所以如果更新需要swap的數據,Redis將阻塞這 操作,直到子線程完成swap操作后才可以進行修改。
從Redis中讀取數據的時候,如果讀取的key對應的value不在內存中,那么Redis就需要從swap文件中加載相應數據,然后再返回給請求方。 這里就存在一個I/O線程池的問題。在默認的情況下,Redis會出現阻塞,即完成所有的swap文件加載后才會相應。這種策略在客戶端的數量較小,進行批量操作的時候比較合適。但是如果將Redis應用在一個大型的網站應用程序中,這顯然是無法滿足大并發的情況的。所以Redis運行我們設置I/O線程 池的大小,對需要從swap文件中加載相應數據的讀取請求進行并發操作,減少阻塞的時間。
所有Redis的操作是原子的,這保證了如果兩個客戶端同時訪問的Redis服務器將獲得更新后的值。Redis是一個多實用的工具,可以在一些像緩存,消息,隊列用例中使用(Redis原生支持發布/訂閱),在應用程序,如Web應用程序的會話,網絡頁面點擊數短期數據等等。
此外對于變化頻率非常快的數據來說,如果還選擇傳統的靜態緩存方式(Memocached、File System等)展示數據,可能在緩存的存取上會有很大的開銷,并不能很好的滿足需要,而Redis這樣基于內存的NoSQL數據庫,就非常適合擔任實時數據的容器。
在用Redis作為Mysql的緩存時我們可以用gearman來進行數據的同步。
Gearman是一個支持分布式的任務分發框架。設計簡潔,獲得了非常廣泛的支持。一個典型的Gearman應用包括以下這些部分:
Gearman Job Server:Gearman核心程序,需要編譯安裝并以守護進程形式運行在后臺
Gearman Client:可以理解為任務的收件員,比如我要在后臺執行一個發送郵件的任務,可以在程序中調用一個Gearman Client并傳入郵件的信息,然后就可以將執行結果立即展示給用戶,而任務本身會慢慢在后臺運行。
Gearman Worker:任務的真正執行者,一般需要自己編寫具體邏輯并通過守護進程方式運行,Gearman Worker接收到Gearman Client傳遞的任務內容后,會按順序處理。
Gearman實現redis緩存mysql的大致流程:
首先利用mysql UDF(通過了libmysqludfjson和gearman-mysql-udf的組合實現)在mysql中的數據發生改變時觸動觸發器將數據傳入Gearman中,這時的mysql相當于Gearman的clinet。然后運行自己編寫的php程序作為worker,將Gearman中的數據傳到Redis中去,這時的Redis相當于是Gearman的consumer。
下面redis緩存mysql的配置過程了(實驗環境rhel6.5):
Redis的安裝:
tar?zxf?redis-3.0.2.tar.gz
yum?install?gcc?-y
cd?redis-3.0.2
make
make?install
配置并啟動服務
cd?utils/
./install_server.sh?#安裝服務啟動程序,同一臺服務器可以有多個啟動程序
#redis的運行端口為6379
配置Redis做mysql的緩存服務器
安裝所需的軟件包:
yum?install??mysql-server?nginx-1.8.0-1.el6.ngx.x86_64.rpm?php-5.3.3-38.el6.x86_64.rpm?php-cli-5.3.3-38.el6.x86_64.rpm?php-common-5.3.3-38.el6.x86_64.rpm?php-devel-5.3.3-38.el6.x86_64.rpm?php-fpm-5.3.3-38.el6.x86_64.rpm?php-gd-5.3.3-38.el6.x86_64.rpm?php-mbstring-5.3.3-38.el6.x86_64.rpm?php-mysql-5.3.3-38.el6.x86_64.rpm?php-pdo-5.3.3-38.el6.x86_64.rpm?-y
配置php:
vim?/etc/php.ini
date.timezone?=Asia/Shanghai
vim?/etc/php-fpm.d/www.conf
user?=?nginx
group?=?nginx
unzip?phpredis-master.zip
cd?phpredis-master
phpize
./configure
make
make?install
vim?/etc/php.d/redis.ini
extension=redis.so
/etc/init.d/php-fpm?start
配置nginx:
vim?/etc/nginx/conf.d/default.conf
server?{
listen???????80;
server_name??localhost;
location?/?{
root???/usr/share/nginx/html;
index??index.php?index.html?index.htm;
}
location?~?\.php$?{
root???????????html;
fastcgi_pass???127.0.0.1:9000;
fastcgi_index??index.php;
fastcgi_param??SCRIPT_FILENAME??/usr/share/nginx/html$fastcgi_script_name;
include????????fastcgi_params;
}
/etc/init.d/nginx?start
配置mysql
/etc/init.d/mysqld?start
mysql?
cat?test.sql
use?test;
CREATE?TABLE?`test`?(`id`?int(7)?NOT?NULL?AUTO_INCREMENT,?`name`?char(8)?DEFAULT?NULL,?PRIMARY?KEY?(`id`))?ENGINE=InnoDB?DEFAULT?CHARSET=utf8;
INSERT?INTO?`test`?VALUES?(1,'test1'),(2,'test2'),(3,'test3'),(4,'test4'),(5,'test5'),(6,'test6'),(7,'test7'),(8,'test8'),(9,'test9');
mysql>?grant?all?on?test.*?to?[email?protected]?identified?by?'westos';?#創建用于緩存mysql數據的redis用戶
mysql?-uredis?-pwestos?#測試這個用戶
創建測試用的php頁面:
cat?/usr/share/nginx/html/index.php
$redis?=?new?Redis();
$redis->connect('127.0.0.1',6379)?or?die?("could?net?connect?redis?server");
#?$query?=?"select?*?from?test?limit?9";
$query?=?"select?*?from?test";
for?($key?=?1;?$key?
{
if?(!$redis->get($key))
{
$connect?=?mysql_connect('127.0.0.1','redis','westos');
mysql_select_db(test);
$result?=?mysql_query($query);
//如果沒有找到$key,就將該查詢sql的結果緩存到redis
while?($row?=?mysql_fetch_assoc($result))
{
$redis->set($row['id'],$row['name']);
}
$myserver?=?'mysql';
break;
}
else
{
$myserver?=?"redis";
$data[$key]?=?$redis->get($key);
}
}
echo?$myserver;
echo?"
";
for?($key?=?1;?$key?
{
echo?"number?is?$key";
echo?"
";
echo?"name?is?$data[$key]";
echo?"
";
}
?>
測試結果
Redis對mysql的緩存已經完成,但是當更新了mysql,Redis不會跟著更新,就會出現mysql與redis數據不一致的情況,接下來我們來處理這種情況:
配置gearman實現數據同步
安裝gearman
yum?install?gearmand-1.1.8-2.el6.x86_64.rpm?libgearman-1.1.8-2.el6.x86_64.rpm?-y
/etc/init.d/gearmand?start#開啟gearman它的端口是4730
安裝php的gearman模塊:
tar?zxf?gearman-1.1.2.tgz
cd?gearman-1.1.2
phpize
yum?install?-y?libgearman-devel-1.1.8-2.el6.x86_64.rpm?libevent-doc-1.4.13-4.el6.noarch.rpm?libevent-devel-1.4.13-4.el6.x86_64.rpm?libevent-headers-1.4.13-4.el6.noarch.rpm?#解決依賴性
./configure
make
make?install
vim?/etc/php.d/gearman.ini
extension=gearman.so
/etc/init.d/php-fpm?reload
安裝lib_mysqludef_json將mysql數據轉換為Redis能用的JSON格式
yum?install?mysql-devel?-y
unzip?lib_mysqludf_json-master.zip
cd?lib_mysqludf_json-master
gcc?$(mysql_config?--cflags)?-shared?-fPIC?-o?lib_mysqludf_json.so?lib_mysqludf_json.c
將lib_mysqludf_json.so模塊拷貝到mysql的插件目錄
cp?lib_mysqludf_json.so?/usr/lib64/mysql/plugin/
注冊UDF函數(只用于mysql5.7以前的版本,5.7以后mysql自帶JSON格式)
mysql>?CREATE?FUNCTION?json_object?RETURNS?STRING?SONAME?'lib_mysqludf_json.so';
mysql>?select?*?from?mysql.func;#查看函數
安裝 gearman-mysql-udf來調用Gearman的分布式隊列
tar?zxf?gearman-mysql-udf-0.6.tar.gz
cd?gearman-mysql-udf-0.6
yum?install?gcc-c++?-y
./configure?--libdir=/usr/lib64/mysql/plugin/
make
make?install
注冊UDF函數:
mysql>?CREATE?FUNCTION?gman_do_background?RETURNS?STRING?SONAME?'libgearman_mysql_udf.so';
CREATE?FUNCTION?gman_servers_set?RETURNS?STRING?SONAME?'libgearman_mysql_udf.so';
mysql>?select?*?from?mysql.func;#查看函數
mysql>?SELECT?gman_servers_set('127.0.0.1:4730');#指定gearman的服務信息,如果是遠程就填寫遠程IP
編寫mysql觸發器:
mysql?
cat?test.sql
use?test;
DELIMITER?$$
CREATE?TRIGGER?datatoredis?AFTER?UPDATE?ON?test?FOR?EACH?ROW?BEGIN
SET?@RECV=gman_do_background('syncToRedis',?json_object(NEW.id?as?`id`,?NEW.name?as?`name`));
END$$
DELIMITER?;
最后配置gearman的worker端并使它一直運行在后端
cat?/usr/local/bin/worker.php
$worker?=?new?GearmanWorker();
$worker->addServer();
$worker->addFunction('syncToRedis',?'syncToRedis');
$redis?=?new?Redis();
$redis->connect('127.0.0.1',?6379);
while($worker->work());
function?syncToRedis($job)
{
global?$redis;
$workString?=?$job->workload();
$work?=?json_decode($workString);
if(!isset($work->id)){
return?false;
}
$redis->set($work->id,?$work->name);
}
?>
nohup?php?worker.php?&
測試:更新mysql數據庫可以看到redisye跟著更新了
mysql>?use?test
mysql>?update?test?set?name='hello'?where?id=1;
[[email?protected]?bin]#?redis-cli
127.0.0.1:6379>?get?1
"hello"
刷新頁面數據也跟著更新了
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的mysql大数据更新缓存_redis缓存mysql的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 5g技术特点是什么(ZigBee技术)
- 下一篇: mysql 汇总行_MySQL查询汇总行