php實現含有redis命令的原子操作

來源:互聯網
上載者:User
關鍵字 php redis
在做一個爬蟲,其中有一部分是評論資料。因為評論數太多,所以想要將爬取下來的評論進行分表。
目前的思路是:
每個表儲存100萬條資料(1-1000000儲存在table1,1000001-2000000儲存在table2)。

在redis建立一個String鍵comment:totalNum,儲存資料庫中已有的評論數。

根據 comment:totalNum 來確定評論的主鍵id以及儲存到哪個表中。

目前思路是:

$id = $redis->get( 'comment:totalNum' );$tableName = getTableName( $id );$sql = "insert xxx";$res = $db->mysql_query( 'sql' );if( $res ){    $redis->incr( 'comment:totalNum' );}

因為考慮用多線程,所以當一個錶快要到100萬條資料時,就會有一個問題:
如果一個進程擷取了comment:totalNum為1000000,判斷可以放在表一中,然後去執行對資料庫的操作,但是如果此時也有一個進程擷取了comment:totalNum的值,那麼也會進行對資料庫的操作,結果就會是資料庫中增加了兩條記錄,一條主鍵為1,000,000,一條主鍵為1,000,001,不符合初衷。

所以我想問一下,有沒有比較好的方法,能實現:

原子操作 start    $id = $redis->get( 'comment:totalNum' );    $tableName = getTableName( $id );    $sql = "insert xxx";    $res = $db->mysql_query( 'sql' );    if( $res ){        $redis->incr( 'comment:totalNum' );    }原子操作 end

回複內容:

在做一個爬蟲,其中有一部分是評論資料。因為評論數太多,所以想要將爬取下來的評論進行分表。
目前的思路是:
每個表儲存100萬條資料(1-1000000儲存在table1,1000001-2000000儲存在table2)。

在redis建立一個String鍵comment:totalNum,儲存資料庫中已有的評論數。

根據 comment:totalNum 來確定評論的主鍵id以及儲存到哪個表中。

目前思路是:

$id = $redis->get( 'comment:totalNum' );$tableName = getTableName( $id );$sql = "insert xxx";$res = $db->mysql_query( 'sql' );if( $res ){    $redis->incr( 'comment:totalNum' );}

因為考慮用多線程,所以當一個錶快要到100萬條資料時,就會有一個問題:
如果一個進程擷取了comment:totalNum為1000000,判斷可以放在表一中,然後去執行對資料庫的操作,但是如果此時也有一個進程擷取了comment:totalNum的值,那麼也會進行對資料庫的操作,結果就會是資料庫中增加了兩條記錄,一條主鍵為1,000,000,一條主鍵為1,000,001,不符合初衷。

所以我想問一下,有沒有比較好的方法,能實現:

原子操作 start    $id = $redis->get( 'comment:totalNum' );    $tableName = getTableName( $id );    $sql = "insert xxx";    $res = $db->mysql_query( 'sql' );    if( $res ){        $redis->incr( 'comment:totalNum' );    }原子操作 end

1.mysql 基本上是單表1000w 資料,100w 量很小,不要急著分表
2.分表要根據需求來處理.
現在你需要儲存聊天記錄,可以根據時間維度進行分表,先做個統計,一天的資料量能達到多少,計算下大概多久可以達到1000w 的資料量,假設一個月資料量到達1000w, 那麼就一個月一張表.

說下你現在方案問題,依賴性較強, redis 掛了或者資料丟失,你就需要手動處理.
如果按你現在的方案來做,要解決的是這個衝突問題,可以使用 redis的 watch 和 事務功能.
Talk is cheap. Show me the code

$num = $redis->get("num");$redis->watch("num");//開啟 mysql 事務begin()//根據 num 插入資料到指定表中insert  xxxxxx//開啟 redis 事務,進行遞增$redis->multi();$redis->incr("num");$incr = $redis->exec();//如果在這期間,其他進程更改了 num 的值,會返回 false, 沒有就返回遞增後的值if(! $incr ){    //復原}else{    //提交 mysql 事務}

根據評論的id號 模數 表的數量 然後在每個表平均的插入資料 你覺得是不是好點? 原子操作都可以不要了

  • 相關文章

    聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.