PHP+Redis 實例【一】點贊 + 熱度 下篇

来源:http://www.cnblogs.com/sunshine-H/archive/2017/11/30/7928034.html
-Advertisement-
Play Games

這篇主要講如何將數據保存回Mysql,但是裡面還會涉及到如何將錯誤信息以及提示信息保存到文件里,方便以後的運維,再有就是如何使用PHP寫進程BAT。 Redis數據刷回資料庫前的知識準備 首先針對上篇提到的關於redis刷回資料庫的安全性的設計模式,因為我們使用的是list來做數據索引,所以在我們將 ...


這篇主要講如何將數據保存回Mysql,但是裡面還會涉及到如何將錯誤信息以及提示信息保存到文件里,方便以後的運維,再有就是如何使用PHP寫進程BAT。

Redis數據刷回資料庫前的知識準備

  首先針對上篇提到的關於redis刷回資料庫的安全性的設計模式,因為我們使用的是list來做數據索引,所以在我們將list數據提取出來的時候,一旦redis在這時候出現異常,就會導致剛提取出來的數據丟失!有些小伙伴就說,丟失就丟失唄,才一點數據。但是我們做程式,就應該以嚴謹為基礎,所以下麵就來說下Redis List這位大佬給我們提供了什麼幫助。

  •   Redis List -》RpopLpush()函數
  •        使用方法:RPOPLPUSH source destination
  •        說明:命令RPOPLPUSH在一個原子時間內,執行以下兩個動作:①命令RPOPLPUSH在一個原子時間內,執行以下兩個動作;②source彈出的元素插入到列表destination,作為destination列表的的頭元素。
  •        設計模式:

      Redis的列表經常被用作隊列(queue),用於在不同程式之間有序地交換消息(message)。一個程式(稱之為生產者,producer)通過LPUSH命令將消息放入隊列中,而另一個程式(稱之為消費者,consumer)通過RPOP命令取出隊列中等待時間最長的消息。

    不幸的是,在這個過程中,一個消費者可能在獲得一個消息之後崩潰,而未執行完成的消息也因此丟失。

    使用RPOPLPUSH命令可以解決這個問題,因為它在返回一個消息之餘,還將該消息添加到另一個列表當中,另外的這個列表可以用作消息的備份表:假如一切正常,當消費者完成該消息的處理之後,可以用LREM命令將該消息從備份表刪除。

Redis數據刷回資料庫

方面文字太多?沒關係。下麵先來一段代碼!我們的主體部分:

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;        //無限迴圈的變數
 8 $num = 0;            //用來沒數據時的判斷依據
 9 date_default_timezone_set("Asia/Shanghai"); 
10 $now = date("Y-m-d H:i:s");        //當前時間
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     //開始幹活
21     if($num==0){
22         //這裡就是將信息輸出到文件里記錄,下麵很多地方都是一樣的。
23         $text = "start ".$name."\n";
24         echo $text;
25         $output->write($test,$text);
26     }
27 
28     //獲取備份隊列的長度
29     $copylistlength = $redis->llen("comment:uploadcopylist"); 
30 
31     //我這裡展示的是第一數據回滾到mysql,小伙伴想批量回滾的,自己改裝下就可以用了。
32     //自己動手豐衣足食!
33     if($copylistlength>1)
34     {
35         //由於是單一數據回滾,所以我要判斷它是否超過我設定的值,小伙伴們最好也自己定一個閾值。
36         //report error
37         echo $now." ->false\n";
38         $rel = false;
39         return;
40     }
41     else if($copylistlength==1)
42     {
43         //這裡判斷防止上次redis出現錯誤,導致數據沒有及時回到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         //獲取主要隊列的長度
53         $listlength = $redis->llen("comment:uploadlist");
54         if ($listlength>0) {
55             //使用之前說到的設計模式
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             // 隊列為空
64             // 列印關閉信息,這裡的寫法算是維持進程視窗不關閉,需要手動關閉
65             // 如果想讓它執行完自動關閉的,
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         //更新完畢,將備份隊列里的數據去掉
60         $this->redis->lrem("comment:uploadcopylist",$data);
61 
62         return $sql."\n";
63     }
64 }

 

 

 

Mysql.class.php  mysql類

 1 <?php
 2 //封裝函數
 3 class MysqlCtrl
 4 {
 5     //初始化參數
 6     //資料庫參數配置
 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     //睡眠時間
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     //保存數據到資料庫
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

上面這些就是整套數據保存到mysql的操作,這是本人源碼copy過來的,所以細分程度比較高,但是可擴展性也很高。有什麼錯誤的地方希望小伙伴們能提出,謝謝。

最後就是我們的進程調用了,其實很簡單

創建一個txt文件,然後改名為clickgood.bat,記得把txt尾碼文件名改為bat

clickgood.bat:

 1 D:\Software\wamp64\bin\php\php7.0.10\php.exe index.php 

關於上面的bat註意兩點,一前面那個php.exe,按照你自己的路徑去找,我使用wampserver測試環境,基本就是上面的路徑。第二點,後面的index.php和clickgood.bat同一目錄下。

好了!終於可以收尾了!、

歡迎大家交流,上面只是本人自己的做法,希望大家能夠指出錯誤的地方!或者提供更好的做法。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一、kafka安裝(集群模式) 1、安裝前準備 機器:10.199.240.232,10.199.206.20 kafka版本:2.12-0.10.1.1 下載地址; https://mirrors.tuna.tsinghua.edu.cn/apache/ 相關目錄: /apps/svr/kafka ...
  • 經過一段時間的學習,對於Hadoop有了一些瞭解,於是決定用MapReduce實現PageRank演算法,以下簡稱PR 先簡單介紹一下PR演算法(摘自百度百科:https://baike.baidu.com/item/google%20pagerank/2465380?fr=aladdin&fromid ...
  • 跟蹤標記:610 功能: 用批量導入操作(Bulk Import Operations)載入數據時,對於索引組織表(即有聚集索引的表) 最小化日誌; 上圖為simple/bulk-logged恢復模式下,最小化日誌的幾種操作,其中包含了批量導入操作,而批量導入操作的最小化日誌有一些前提條件,概括如下 ...
  • 系統環境:Ubuntu 16.04 LTS. 安裝robomongo Robo 3T,運行時報以下錯誤: 可以嘗試按照以下方法解決: 即將robo3t解壓目錄下的/lib/libstdc++*所匹配的文件移到備份一個備份目錄中,然後再嘗試啟動robo3t,可以解決該問題。 如何將robo3t添加到U ...
  • 在我們開發項目的時候,經常會遇到大塊數據的問題(2M-100M),比如說保存報表中1w個人的ID號,他就像一個腫瘤一樣,存儲在伺服器哪裡都 覺得噁心,放在redis,mongodb中吧,一下子你就會收到報警,因為記憶體滿了。。。放在mysql吧???你還得建立一個text欄位,和一些小欄位混在一起, ...
  • 1 ;SQL Server 2014 Configuration File 2 [OPTIONS] 3 4 ; 指定安裝程式的工作流,如 INSTALL、UNINSTALL 或 UPGRADE。這是必需的參數。 5 6 ACTION="Install" 7 8 ; 尚未定義命令行參數 ROLE 的詳 ...
  • [20171130]關於rman備份疑問.txt--//前面測試太亂,重新做一些rman as copy相關測試.1.環境:SCOTT@book> @ &r/ver1PORT_STRING VERSION BANNER x86_64/Linux 2.4.xx 11.2.0.4.0 Oracle Da ...
  • 聲明局部變數語法:DECLARE @variable_name DataType其中 variable_name為局部變數的名稱,DataType為數據類型。給局部變數賦值有兩種方法:1、SET @variable_name=value2、SELECT @variable_name=value兩者的 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...