PHP+Redis 实例【一】点赞 + 热度 下篇
這篇主要講如何將數(shù)據(jù)保存回Mysql,但是里面還會(huì)涉及到如何將錯(cuò)誤信息以及提示信息保存到文件里,方便以后的運(yùn)維,再有就是如何使用PHP寫進(jìn)程BAT。
Redis數(shù)據(jù)刷回?cái)?shù)據(jù)庫(kù)前的知識(shí)準(zhǔn)備
首先針對(duì)上篇提到的關(guān)于redis刷回?cái)?shù)據(jù)庫(kù)的安全性的設(shè)計(jì)模式,因?yàn)槲覀兪褂玫氖莑ist來(lái)做數(shù)據(jù)索引,所以在我們將list數(shù)據(jù)提取出來(lái)的時(shí)候,一旦redis在這時(shí)候出現(xiàn)異常,就會(huì)導(dǎo)致剛提取出來(lái)的數(shù)據(jù)丟失!有些小伙伴就說(shuō),丟失就丟失唄,才一點(diǎn)數(shù)據(jù)。但是我們做程序,就應(yīng)該以嚴(yán)謹(jǐn)為基礎(chǔ),所以下面就來(lái)說(shuō)下Redis List這位大佬給我們提供了什么幫助。
- Redis List -》RpopLpush()函數(shù)
- ? ? ? ?使用方法:RPOPLPUSH source destination
- ? ? ? ?說(shuō)明:命令RPOPLPUSH在一個(gè)原子時(shí)間內(nèi),執(zhí)行以下兩個(gè)動(dòng)作:①命令RPOPLPUSH在一個(gè)原子時(shí)間內(nèi),執(zhí)行以下兩個(gè)動(dòng)作;②將source彈出的元素插入到列表destination,作為destination列表的的頭元素。
- ? ? ? ?設(shè)計(jì)模式:
Redis的列表經(jīng)常被用作隊(duì)列(queue),用于在不同程序之間有序地交換消息(message)。一個(gè)程序(稱之為生產(chǎn)者,producer)通過(guò)LPUSH命令將消息放入隊(duì)列中,而另一個(gè)程序(稱之為消費(fèi)者,consumer)通過(guò)RPOP命令取出隊(duì)列中等待時(shí)間最長(zhǎng)的消息。
不幸的是,在這個(gè)過(guò)程中,一個(gè)消費(fèi)者可能在獲得一個(gè)消息之后崩潰,而未執(zhí)行完成的消息也因此丟失。
使用RPOPLPUSH命令可以解決這個(gè)問(wèn)題,因?yàn)樗诜祷匾粋€(gè)消息之余,還將該消息添加到另一個(gè)列表當(dāng)中,另外的這個(gè)列表可以用作消息的備份表:假如一切正常,當(dāng)消費(fèi)者完成該消息的處理之后,可以用LREM命令將該消息從備份表刪除。
Redis數(shù)據(jù)刷回?cái)?shù)據(jù)庫(kù)
方面文字太多?沒(méi)關(guān)系。下面先來(lái)一段代碼!我們的主體部分:
index.php:
?
1 <?php 2 require_once(__DIR__."/Mysql.class.php"); 3 require_once(__DIR__."/Redis.class.php"); 4 require_once(__DIR__."/Output_Log.class.php"); 5 6 7 $rel = true; //無(wú)限循環(huán)的變量 8 $num = 0; //用來(lái)沒(méi)數(shù)據(jù)時(shí)的判斷依據(jù) 9 date_default_timezone_set("Asia/Shanghai"); 10 $now = date("Y-m-d H:i:s"); //當(dāng)前時(shí)間 11 //file log 12 $txt = dirname(__DIR__)."/Script_Log/clickgood_log.txt"; 13 $output = new OutputLog(); 14 $test = $output->open($txt,"a+"); 15 16 while($rel) 17 { 18 $redis = new RedisCtrl(); 19 20 //開(kāi)始干活 21 if($num==0){ 22 //這里就是將信息輸出到文件里記錄,下面很多地方都是一樣的。 23 $text = "start ".$name."\n"; 24 echo $text; 25 $output->write($test,$text); 26 } 27 28 //獲取備份隊(duì)列的長(zhǎng)度 29 $copylistlength = $redis->llen("comment:uploadcopylist"); 30 31 //我這里展示的是第一數(shù)據(jù)回滾到mysql,小伙伴想批量回滾的,自己改裝下就可以用了。 32 //自己動(dòng)手豐衣足食! 33 if($copylistlength>1) 34 { 35 //由于是單一數(shù)據(jù)回滾,所以我要判斷它是否超過(guò)我設(shè)定的值,小伙伴們最好也自己定一個(gè)閾值。 36 //report error 37 echo $now." ->false\n"; 38 $rel = false; 39 return; 40 } 41 else if($copylistlength==1) 42 { 43 //這里判斷防止上次redis出現(xiàn)錯(cuò)誤,導(dǎo)致數(shù)據(jù)沒(méi)有及時(shí)回到mysql 44 $data = $redis->rpop("comment:uploadcopylist"); 45 $rel = $redis->UpdateClickGoodDataToMysql($data); 46 $text = $rel."\n"; 47 echo $text; 48 $output->write($test,$text); 49 } 50 else 51 { 52 //獲取主要隊(duì)列的長(zhǎng)度 53 $listlength = $redis->llen("comment:uploadlist"); 54 if ($listlength>0) { 55 //使用之前說(shuō)到的設(shè)計(jì)模式 56 $data = $redis->rpoplpush("comment:uploadlist","comment:uploadcopylist"); 57 58 $rel = $redis->UpdateClickGoodDataToMysql($data); 59 $text = $rel."\n"; 60 echo $text; 61 $output->write($test,$text); 62 }else{ 63 // 隊(duì)列為空 64 // 打印關(guān)閉信息,這里的寫法算是維持進(jìn)程窗口不關(guān)閉,需要手動(dòng)關(guān)閉 65 // 如果想讓它執(zhí)行完自動(dòng)關(guān)閉的, 66 // 把下面改寫成$rel = false; 67 if($num<=3){ 68 $text = $now." -> please close .\n"; 69 echo $text; 70 $output->write($test,$text); 71 $num++; 72 } 73 else 74 { 75 $output->close($test); 76 } 77 } 78 } 79 80 }?
?
Redis.class.php: redis操作類
?
?
?
1 <?php 2 class RedisCtrl 3 { 4 //init redis 5 static $redisIp = "127.0.0.1"; 6 static $redisPort =6379; 7 static $redisPass =""; 8 public $redis = null; 9 10 //Redis 11 public function __construct() 12 { 13 $this->redis = new Redis(); 14 $this->redis->connect(self::$redisIp,self::$redisPort); 15 $this->redis->auth(self::$redisPass); 16 } 17 18 public function llen($key) 19 { 20 $rel = $this->redis->llen($key); 21 return $rel; 22 } 23 24 public function rpop($key) 25 { 26 $rel = $this->redis->rpop($key); 27 return $rel; 28 } 29 30 public function rpoplpush($source,$destination) 31 { 32 $rel = $this->redis->rpoplpush($source,$destination); 33 return $rel; 34 } 35 36 public function UpdateClickGoodDataToMysql($data) 37 { 38 //get id and time from redis list 39 $result = json_decode($data,true); 40 $id = $result['id']; 41 $time = $result['time']; 42 $arr = array(); 43 44 //like 45 $like = $this->redis->zscore("comment:like",$id); 46 $like = $like?$like:0; 47 //hate 48 $hate = $this->redis->zscore("comment:hate",$id); 49 $hate = $hate?$hate:0; 50 51 $sql = "update comment_info set like_count=".$like.", hate_count=".$hate." where id=".$id; 52 $arr[] = $sql; 53 //update sql 54 $mysql = new MysqlCtrl(); 55 $mysql->saveMySQL($arr); 56 57 //更新完,將set集合里需要更新的id去掉 58 $this->redis->srem("comment:uploadset",$id); 59 //更新完畢,將備份隊(duì)列里的數(shù)據(jù)去掉 60 $this->redis->lrem("comment:uploadcopylist",$data); 61 62 return $sql."\n"; 63 } 64 }?
?
?
Mysql.class.php mysql類
1 <?php 2 //封裝函數(shù) 3 class MysqlCtrl 4 { 5 //初始化參數(shù) 6 //數(shù)據(jù)庫(kù)參數(shù)配置 7 static $dbms = "mysql"; 8 static $host = Your host; 9 static $user = Your user; 10 static $pass = Your pass; 11 static $database = Your database; 12 //睡眠時(shí)間 13 static $sleep = 1; 14 15 public $dsn = null; 16 public $dbh = null; 17 18 public function __construct() 19 { 20 $this->dsn = self::$dbms.":host=".self::$host.";dbname=".self::$database; 21 //return $dsn; 22 try { 23 $this->dbh = new PDO($this->dsn, self::$user, self::$pass); 24 echo "Connected\n"; 25 } catch (Exception $e) { 26 echo $this->dsn; 27 die("Unable to connect: " . $e->getMessage()); 28 } 29 } 30 31 //保存數(shù)據(jù)到數(shù)據(jù)庫(kù) 32 //PDO 33 public function saveMySQL($arr) 34 { 35 36 try { 37 $this->dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 38 39 $this->dbh->beginTransaction(); 40 41 $count = count($arr); 42 for ($i=0; $i < $count; $i++) { 43 $this->dbh->exec($arr[$i]); 44 } 45 46 $this->dbh->commit(); 47 48 } catch (Exception $e) { 49 $this->dbh->rollBack(); 50 echo "Failed: " . $e->getMessage()."\n"; 51 $json = json_encode($arr); 52 echo "False-SQL: ".$json."\n"; 53 exit(); 54 } 55 } 56 }?
Output_Log.class.php 輸出信息到文件的類
1 <?php 2 class OutputLog 3 { 4 public function open($name,$r) 5 { 6 $text = fopen($name, $r); 7 return $text; 8 } 9 10 public function write($name,$title) 11 { 12 $rel = fwrite($name, $title); 13 return $rel; 14 } 15 16 public function close($name) 17 { 18 fclose($name); 19 } 20 }?
clickgood_log.txt 這里是保存輸出的信息,里面是空白的。
hellO world上面這些就是整套數(shù)據(jù)保存到mysql的操作,這是本人源碼copy過(guò)來(lái)的,所以細(xì)分程度比較高,但是可擴(kuò)展性也很高。有什么錯(cuò)誤的地方希望小伙伴們能提出,謝謝。
最后就是我們的進(jìn)程調(diào)用了,其實(shí)很簡(jiǎn)單
創(chuàng)建一個(gè)txt文件,然后改名為clickgood.bat,記得把txt后綴文件名改為bat
clickgood.bat:
?1 D:\Software\wamp64\bin\php\php7.0.10\php.exe index.php?
關(guān)于上面的bat注意兩點(diǎn),一前面那個(gè)php.exe,按照你自己的路徑去找,我使用wampserver測(cè)試環(huán)境,基本就是上面的路徑。第二點(diǎn),后面的index.php和clickgood.bat同一目錄下。
好了!終于可以收尾了!、
歡迎大家交流,上面只是本人自己的做法,希望大家能夠指出錯(cuò)誤的地方!或者提供更好的做法。
轉(zhuǎn)載于:https://www.cnblogs.com/sunshine-H/p/7928034.html
總結(jié)
以上是生活随笔為你收集整理的PHP+Redis 实例【一】点赞 + 热度 下篇的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 创业板市盈率
- 下一篇: php之判断点在多边形内的api