redis存儲token案例,redis 使用案例

 2023-10-18 阅读 26 评论 0

摘要:1.使用redis消息列隊發布信息 在一些用戶創造用戶的應用中(如SNS,微博),可能出現1秒有上千萬個用戶同時發布消息的情況,此時如果使用mysql可能出現‘too many connections’ 錯誤,當然,把mysql的max_connections 參數設置為更大數&

1.使用redis消息列隊發布信息

在一些用戶創造用戶的應用中(如SNS,微博),可能出現1秒有上千萬個用戶同時發布消息的情況,此時如果使用mysql可能出現‘too many connections’ 錯誤,當然,把mysql的max_connections 參數設置為更大數,不過這是一個治標不治本的方法,這是可以考慮使用redis。

使用redis的list類型作為消息列隊,把用戶發布的消息暫時存儲在消息列隊中,接著使用一個cron程序把消息列隊中的消息插入mysql,這樣有效率降低mysql的并發量。

例如發布一條微博使用一下接口:

<?php
$uid = get_uid();
$content = get_content();$timestamp = time();
$weibo = new weibo();
$weibo->pot($uid,$contnet,$timestamp);
?>

redis存儲token案例,weibo對象的post方法就是發布微博的接口,它直接把微博寫入mysql。參數$uid是用戶的UID,$content是微博的內容,$timestamp是發布的時間戳。

為了降低mysql的并發數,先把用戶發布的微博存在redis中,代碼如下:

<?php
$redis = new redis('127.0.0.1',6379);
$redis -> connect();
$weibo_info = [
'uid' => get_uid(),
'content' => get_cntent(),
'timestamp' => time()
];$redis->lpush('weibo_list',json_encode($weibo_info));
$redis -> close();
?>

?先把微博信息使用json_encode編碼成JSON格式。然后使用redis對象的lpush方法把微博信息插入到weibo_list列隊。

把微博存到redis以后,編寫一個cron程序吧redis中的微博信息插入到mysql中代碼如下:

<?php
$redis = new redis('127.0.0.1',6379);
$redis->connect();
$weibo = new weibo();
while(true){if($redis->lsize('weibo_list') > 0){$info = $redis->rpop('weibo_list');$info = json_decode($info);$weibo -> post($info->uid,$info->content,$info->timestamp);}else{sleep(1);}}
$redis ->close();
?>        

在cron程序中,先使用redis對象的rpop()方法從weibo_list列表中取得一條微博信息,然后使用json_decode ()函數解碼,最后調用weibo對象的post方法把微博信息插入mysql。

redis的使用、使用消息列隊有一個缺點,就是‘延時’。為了把延時降低,運行多個cron程序同時把消息列隊中的數據插入mysql。使用消息列隊的好處是擴展性好,當一臺redis服務器不能應付大量并發時,使用‘一致性Hash算法’把并發分發到redis服務器。

2.使用redis代替文件存儲session

PHP默認使用文件存儲session,如果并發量大,效率非常低。而redis對高并發的支持非常好,所以,可以使用redis替代文件存儲session。

在講解實例之前,先了解php的session_set_save_handler函數的作用和使用方法。該函數定義設置用戶自定義會話存儲函數(如打開、關閉、寫入等)。原型如下:

bool session_set_save_handler(callback open,callback close,callback read,callback write,callback destroy,callback gc,callable create_sid)

redis詳解。sesson_set_save_handler 函數各參數作用如下:

open 回調函數類似于類的構造函數, 在會話打開的時候會被調用。 這是自動開始會話或者通過調用?session_start()?手動開始會話 之后第一個被調用的回調函數。 此回調函數操作成功返回?TRUE,反之返回?FALSE

close 回調函數類似于類的析構函數。 在 write 回調函數調用之后調用。 當調用?session_write_close()?函數之后,也會調用 close 回調函數。 此回調函數操作成功返回?TRUE,反之返回?FALSE

?

read?如果會話中有數據,read 回調函數必須返回將會話數據編碼(序列化)后的字符串。 如果會話中沒有數據,read 回調函數返回空字符串。

在自動開始會話或者通過調用?session_start()?函數手動開始會話之后,PHP 內部調用 read 回調函數來獲取會話數據。 在調用 read 之前,PHP 會調用 open 回調函數。

read 回調返回的序列化之后的字符串格式必須與?write?回調函數保存數據時的格式完全一致。 PHP 會自動反序列化返回的字符串并填充?$_SESSION?超級全局變量。 雖然數據看起來和?serialize()?函數很相似, 但是需要提醒的是,它們是不同的。 請參考:?session.serialize_handler。

write在會話保存數據時會調用?write?回調函數。 此回調函數接收當前會話 ID 以及?$_SESSION?中數據序列化之后的字符串作為參數。 序列化會話數據的過程由 PHP 根據?session.serialize_handler?設定值來完成。

序列化后的數據將和會話 ID 關聯在一起進行保存。 當調用?read?回調函數獲取數據時,所返回的數據必須要和 傳入?write?回調函數的數據完全保持一致。

PHP 會在腳本執行完畢或調用?session_write_close()?函數之后調用此回調函數。 注意,在調用完此回調函數之后,PHP 內部會調用?close回調函數。

destroy當調用?session_destroy()?函數, 或者調用?session_regenerate_id()?函數并且設置 destroy 參數為?TRUE?時, 會調用此回調函數。此回調函數操作成功返回?TRUE,反之返回?FALSE

gc為了清理會話中的舊數據,PHP 會不時的調用垃圾收集回調函數。 調用周期由?session.gc_probability?和?session.gc_divisor?參數控制。 傳入到此回調函數的 lifetime 參數由?session.gc_maxlifetime?設置。 此回調函數操作成功返回?TRUE,反之返回?FALSE

create_sid當需要新的會話 ID 時被調用的回調函數。 回調函數被調用時無傳入參數, 其返回值應該是一個字符串格式的、有效的會話 ID。

在使用該函數前,先把php.ini配置文件的session.save_handler選項設置為user,否則session_set_save_handler 不會生效。

編寫一個session管理sessionManager,代碼如下:

<?php
class SessionManager{private $redis;private $sessionSavePath;private $sessionName;private $sessionExpireTime = 30;public function __construct(){$this->redis = new redis();$this->redis->connect('127.0.0.1',6379);$retval = session_set_save_handler ([$this,'open'],[$this,'close'],[$this,'read'],[$this,'write'],[$this,'destroy'],[$this,'gc']);session_start();}public function open($path,$name){return true;}public function close(){return true;}public function read($id){$value = $this->redis->get($id);if($value){return $value;}else{return '';}}public function write($id,$data){if($this->redis->set($id,$data)){$this->redis->expire($id,$this->sessionExpireTime);return true;}return false;}public function destroy($id){if($this->redis->delete($id)){return false;}return false;}public function gc($maxlifetime){return true;}public function __destruct(){session_write_close();}}

redis是什么、?

?

SessionManager構造函數主要用來連接redis服務器,使用session_set_save_handler函數設置session函數回調,并調用session_start函數開始session功能。因為本例中open、close和gc回調的作用不大,所以直接返回true。

在write回調函數中,以SessionID作為key,把session的數據作為value存儲到redis服務器,設置session的過期時間為30秒。在read回調函數中,以SessionID作為key從redis服務器中讀取數據,并返回數據。而在destroy回調函數中,則以sessionID 作為key從redis服務器中刪除對應的session數據。

使用時只需要包含SessionManager類,然后實例化一個SessionManager對象。下面例子使用SessionManager來管理session,首先創建一個session_set.php,輸入代碼如下:

include('SessionManager.php');
new SessionManager();
$_SESSION['username'] = 'newsession';

然后再建立一個sesion_get.php 文件代碼如下:

include('SessionManager.php');
new SessionManager();
echo $_SESSION['username'];

測試時先訪問 session_set.php 然后再訪問 session_get.php

redis 集群、轉載于:https://www.cnblogs.com/phpshen/p/6306739.html

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/2/146764.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息