『壹』 php redis 需要使用單例嗎
<?php
/**
* Class RedisConnManager
*
* 單例模式對redis實例的操作的進一步封裝
* 主要目的:防止過多的連接,一個頁面只能存在一個聲明連接
*
* @author :cuihuan
*/
class RedisManager
{
private static $redisInstance;
/**
* 私有化構造函數
* 原因:防止外界調用構造新的對象
*/
private function __construct(){}
/**
* 獲取redis連接的唯一出口
*/
static public function getRedisConn(){
if(!self::$redisInstance instanceof self){
self::$redisInstance = new self;
}
// 獲取當前單例
$temp = self::$redisInstance;
// 調用私有化方法
return $temp->connRedis();
}
/**
* 連接ocean 上的redis的私有化方法
* @return Redis
*/
static private function connRedis()
{
try {
$redis_ocean = new Redis();
$redis_ocean->connect(G::$conf['redis-host'], G::$conf['redis-port']);
$redis_ocean->auth(G::$conf['redis-pass']);
}catch (Exception $e){
echo $e->getMessage().'<br/>';
}
return $redis_ocean;
}
}
『貳』 php 用 redis做隊列 運行過程是什麼樣的
Reids是一個比較高級的開源key-value存儲系統,採用ANSI C實現。其與memcached類似,但是支持持久化數據存儲入隊操作
復制代碼 代碼如下:
<?php
$redis = new Redis();
$redis->connect('127.0.0.1',6379);
while(True){
try{
$value = 'value_'.date('Y-m-d H:i:s');
$redis->LPUSH('key1',$value);
sleep(rand()%3);
echo $value."\n";
}catch(Exception $e){
echo $e->getMessage()."\n";
}
}
?>
出隊操作
復制代碼 代碼如下:
<?php
$redis = new Redis();
$redis->pconnect('127.0.0.1',6379);
while(True){
try{
echo $redis->LPOP('key1')."\n";
}catch(Exception $e){
echo $e->getMessage()."\n";
}
sleep(rand()%3);
}?>
如何使用Redis 做隊列操作
Reids是一個比較高級的開源key-value存儲系統,採用ANSI C實現。其與memcached類似,但是支持持久化數據存儲,同時value支持多種類型:字元串 (同memcached中的value),列表 ,集合 (Set),有序集合 (OrderSet)和Hash 。所有的值類型均支持原子操作,如列表中追加彈出元素,集合中插入移除元素等。Rdids的數據大部分位於內存中,其讀寫效率非常高,其提供AOF(追加 式操作記錄文件)和DUMP(定期數據備份)兩種持久化方式。Redis支持自定義的VM(虛擬內存)機制,當數據容量超過內存時,可以將部分Value 存儲到文件中。同時Redis支持Master-Slave機制,可以進行數據復制。
可以把Redis的list結構當隊列來用.
從上面Redis的場景和作用來說,對於我們現在的開發活動,究竟能把Redis引入在那些場景,而不是把這么好的東東演變成「為了使用Redis,而Redis」的慘烈局面呢?當然,具體問題具體分析,這個真的很重要哈。
緩存?分布式緩存?
隊列?分布式隊列?
某些系統應用(例如,電信、銀行和大型互聯網應用等)都會使用到,當然,現在大行其道的memcache就是很好的證明;但從某一方面來說,memcache是否能把兩張囊括其中,而且能做到更好(沒有實際的應用過,所以只是拋出)。但從Redis身上,我就能感覺到,Redis,就能把隊列和緩存兩張都囊括其中,而且都不會產生並發環境下的困擾,因為Redis中的操作都是原子操作來著。
至於評論兩者的孰好孰壞就免了,存在就是理由,選擇適合的就是最好的。
下面開始玩玩Redis中的隊列(分布式)設計YY吧,請大蝦們多多指點。
狀況場景:
現在的項目,都是部署在多個伺服器,或者多個IP上,而且前台經由F5分發,所以用戶的請求究竟落在那一台的伺服器上,是無法確定的。對於項目中,有一秒殺設計,剛開始沒有考慮到這種部署,同時也是使用最容易處理的方式,直接給資料庫表鎖行記錄(Oracle上的)。可以說,對於不同的應用部署,而只有一台資料庫伺服器來說,很「輕松」的就解決了這個並發的問題。所以現在考慮一下,是不是挪到應用上,避免資料庫伺服器也摻雜到業務上。
比如,現在有2台應用伺服器,1台資料庫伺服器。想法是,把Redis部署在資料庫伺服器上,兩台伺服器在操作並發緩存或者隊列時,先從Redis伺服器上,取得在兩台應用伺服器的代理對象,再做入列出列的操作。
看代碼實現(PHP)
入隊列操作文件 list_push.php
復制代碼 代碼如下:
<?php
$redis = getRedisInstance();//從Redis伺服器拿到redis實例$redis->connect('Redis伺服器IP', 6379);
while (true) {
$redis->lPush('list1', 'A_'.date('Y-m-d H:i:s'));sleep(rand()%3);
}
?>
執行# php list_push.php &
出隊列操作 list_pop.php文件
復制代碼 代碼如下:
<?php
$redis = getRedisInstance();//從Redis伺服器拿到redis實例$redis->pconnect('Redis伺服器IP', 6379);
while(true) {
try {
var_export( $redis->blPop('list1', 10) );} catch(Exception $e) {
//echo $e;
}
}
實現方法(python)
1.入隊列(write.py)
復制代碼 代碼如下:
#!/usr/bin/env python
import time
from redis import Redis
redis = Redis(host='127.0.0.1', port=6379)while True:
now = time.strftime("%Y/%m/%d %H:%M:%S")
redis.lpush('test_queue', now)
time.sleep(1)
2.出隊列(read.py)
復制代碼 代碼如下:
#!/usr/bin/env python
import sys
from redis import Redis
redis = Redis(host='127.0.0.1', port=6379)while True:
res = redis.rpop('test_queue')
if res == None:
pass
else:
print str(res)
『叄』 php redis如何使用
開始在 PHP 中使用 Redis 前,要確保已經安裝了 redis 服務及 PHP redis 驅動,且你的機器上能正常使用 PHP。
PHP安裝redis擴展
/usr/local/php/bin/phpize #php安裝後的路徑
./configure --with-php-config=/usr/local/php/bin/php-config
make && make install
修改php.ini文件
vi /usr/local/php/lib/php.ini
增加如下內容:
extension_dir = "/usr/local/php/lib/php/extensions/no-debug-zts-20090626"
extension=redis.so
安裝完成後重啟php-fpm 或 apache。查看phpinfo信息,就能看到redis擴展。
連接到 redis 服務
<?php
//連接本地的 Redis 服務
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
echo "Connection to server sucessfully";
//查看服務是否運行
echo "Server is running: " . $redis->ping();
?>
執行腳本,輸出結果為:
Connection to server sucessfully
Server is running: PONG
Redis PHP String(字元串) 實例
<?php
//連接本地的 Redis 服務
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
echo "Connection to server sucessfully";
//設置 redis 字元串數據
$redis->set("tutorial-name", "Redis tutorial");
// 獲取存儲的數據並輸出
echo "Stored string in redis:: " . jedis.get("tutorial-name");
?>
執行腳本,輸出結果為:
Connection to server sucessfully
Stored string in redis:: Redis tutorial
Redis PHP List(列表) 實例
<?php
//連接本地的 Redis 服務
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
echo "Connection to server sucessfully";
//存儲數據到列表中
$redis->lpush("tutorial-list", "Redis");
$redis->lpush("tutorial-list", "Mongodb");
$redis->lpush("tutorial-list", "Mysql");
// 獲取存儲的數據並輸出
$arList = $redis->lrange("tutorial-list", 0 ,5);
echo "Stored string in redis:: "
print_r($arList);
?>
執行腳本,輸出結果為:
Connection to server sucessfully
Stored string in redis::
Redis
Mongodb
Mysql
Redis PHP Keys 實例
<?php
//連接本地的 Redis 服務
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
echo "Connection to server sucessfully";
// 獲取數據並輸出
$arList = $redis->keys("*");
echo "Stored keys in redis:: "
print_r($arList);
?>
執行腳本,輸出結果為:
Connection to server sucessfully
Stored string in redis::
tutorial-name
tutorial-list
『肆』 thinkphp如何使用redis 有簡單的示例代碼嗎
$redis = new \think\cache\driver\Redis();//實例化Think的Redis驅動
$redis->has('鍵名');//判斷redis值是否存在
$redis->get('鍵名');//獲取redis的某個值;
$redis->set('鍵名','鍵值');//設置redis值
$redis->inc('鍵名',進長[默認為1]);//自增緩存。只對數字整型有效
$redis->dec('鍵名',進長[默認為1]);//自減緩存。只對數字整型有效
$redis->rm('鍵名');//刪除緩存
$redis->clear();//清空緩存
『伍』 php實現redis資料庫指定庫號遷移的方法
這篇文章主要介紹了php實現redis資料庫指定庫號遷移的方法,涉及對於redis資料庫的操作技巧,非常具有實用價值,需要的朋友可以參考下
本文實例講述了php實現redis資料庫指定庫號遷移的方法,分享給大家供大家參考。具體如下:
redis普通的資料庫遷移,只能整個redis
save,或者利用主從,當然也可以安裝一個redis-mp,不過比較麻煩,這里提供一種php的腳本,實現指定庫號的遷移,其實也就是遍歷根據存儲類型,讀出來,插入新庫,效果是這樣:
代碼如下:
[root@localhost
~]#
php
1.php
1/407
101/407
201/407
301/407
401/407
PHP實例代碼如下:
代碼如下:
<?php
$from
=
'10.0.2.52:6379/7';
$to
=
'127.0.0.1:6379/7';
$from_redis
=
redis_init($from);
$to_redis
=
redis_init($to);
$keys
=
$from_redis->keys('*');
$count
=
0;
$total
=
count($keys);
foreach($keys
as
$key){
if(++$count
%
100
==
1){
echo
"$count/$totaln";
}
$type
=
$from_redis->type($key);
switch($type){
case
Redis::REDIS_STRING:
$val
=
$from_redis->get($key);
$to_redis->set($key,
$val);
break;
case
Redis::REDIS_LIST:
$list
=
$from_redis->lRange($key,
0,
-1);
foreach($list
as
$val){
$to_redis->rPush($key,
$val);
}
break;
case
Redis::REDIS_HASH:
$hash
=
$from_redis->hGetAll($key);
$to_redis->hMSet($key,
$hash);
break;
case
Redis::REDIS_ZSET:
$zset
=
$from_redis->zRange($key,
0,
-1,
true);
foreach($zset
as
$val=>$score){
$to_redis->zAdd($key,
$score,
$val);
}
break;
}
}
function
redis_init($conf){
$redis
=
new
Redis();
preg_match('/^([^:]+)(:[0-9]+)?/(.+)?/',
$conf,
$ms);
$host
=
$ms[1];
$port
=
trim($ms[2],
':');
$db
=
$ms[3];
$redis->connect($host,
$port);
$redis->select($db);
return
$redis;
}
?>
希望本文所述對大家的php程序設計有所幫助。
『陸』 php 使用redis鎖限制並發訪問類示例
本文介紹了php
使用redis鎖限制並發訪問類,並詳細的介紹了並發訪問限制方法。
1.並發訪問限制問題
對於一些需要限制同一個用戶並發訪問的場景,如果用戶並發請求多次,而伺服器處理沒有加鎖限制,用戶則可以多次請求成功。
例如換領優惠券,如果用戶同一時間並發提交換領碼,在沒有加鎖限制的情況下,用戶則可以使用同一個換領碼同時兌換到多張優惠券。
偽代碼如下:
if
A(可以換領)
B(執行換領)
C(更新為已換領)
D(結束)
如果用戶並發提交換領碼,都能通過可以換領(A)的判斷,因為必須有一個執行換領(B)後,才會更新為已換領(C)。因此如果用戶在有一個更新為已換領之前,有多少次請求,這些請求都可以執行成功。
2.並發訪問限制方法
使用文件鎖可以實現並發訪問限制,但對於分布式架構的環境,使用文件鎖不能保證多台伺服器的並發訪問限制。
Redis是一個開源的使用ANSI
C語言編寫、支持網路、可基於內存亦可持久化的日誌型、Key-Value資料庫,並提供多種語言的API。
本文將使用其setnx方法實現分布式鎖功能。setnx即Set
it
N**ot
eX**ists。
當鍵值不存在時,插入成功(獲取鎖成功),如果鍵值已經存在,則插入失敗(獲取鎖失敗)
RedisLock.class.PHP
<?php
/**
*
Redis鎖操作類
*
Date:
2016-06-30
*
Author:
fdipzone
*
Ver:
1.0
*
*
Func:
*
public
lock
獲取鎖
*
public
unlock
釋放鎖
*
private
connect
連接
*/
class
RedisLock
{
//
class
start
private
$_config;
private
$_redis;
/**
*
初始化
*
@param
Array
$config
redis連接設定
*/
public
function
__construct($config=array()){
$this->_config
=
$config;
$this->_redis
=
$this->connect();
}
/**
*
獲取鎖
*
@param
String
$key
鎖標識
*
@param
Int
$expire
鎖過期時間
*
@return
Boolean
*/
public
function
lock($key,
$expire=5){
$is_lock
=
$this->_redis->setnx($key,
time()+$expire);
//
不能獲取鎖
if(!$is_lock){
//
判斷鎖是否過期
$lock_time
=
$this->_redis->get($key);
//
鎖已過期,刪除鎖,重新獲取
if(time()>$lock_time){
$this->unlock($key);
$is_lock
=
$this->_redis->setnx($key,
time()+$expire);
}
}
return
$is_lock?
true
:
false;
}
/**
*
釋放鎖
*
@param
String
$key
鎖標識
*
@return
Boolean
*/
public
function
unlock($key){
return
$this->_redis->del($key);
}
/**
*
創建redis連接
*
@return
Link
*/
private
function
connect(){
try{
$redis
=
new
Redis();
$redis->connect($this->_config['host'],$this->_config['port'],$this->_config['timeout'],$this->_config['reserved'],$this->_config['retry_interval']);
if(empty($this->_config['auth'])){
$redis->auth($this->_config['auth']);
}
$redis->select($this->_config['index']);
}catch(RedisException
$e){
throw
new
Exception($e->getMessage());
return
false;
}
return
$redis;
}
}
//
class
end
?>
demo.php
<?php
require
'RedisLock.class.php';
$config
=
array(
'host'
=>
'localhost',
'port'
=>
6379,
'index'
=>
0,
'auth'
=>
'',
'timeout'
=>
1,
'reserved'
=>
NULL,
'retry_interval'
=>
100,
);
//
創建redislock對象
$oRedisLock
=
new
RedisLock($config);
//
定義鎖標識
$key
=
'mylock';
//
獲取鎖
$is_lock
=
$oRedisLock->lock($key,
10);
if($is_lock){
echo
'get
lock
success<br>';
echo
'do
sth..<br>';
sleep(5);
echo
'success<br>';
$oRedisLock->unlock($key);
//
獲取鎖失敗
}else{
echo
'request
too
frequently<br>';
}
?>
測試方法:
打開兩個不同的瀏覽器,同時在A,B中訪問demo.php
如果先訪問的會獲取到鎖
輸出
get
lock
success
do
sth..
success
另一個獲取鎖失敗則會輸出request
too
frequently
保證同一時間只有一個訪問有效,有效限制並發訪問。
為了避免系統突然出錯導致死鎖,所以在獲取鎖的時候增加一個過期時間,如果已超過過期時間,即使是鎖定狀態都會釋放鎖,避免死鎖導致的問題。
源碼下載地址:點擊查看
『柒』 php怎樣使用redis緩存數據
<?php
/**
* Redis緩存操作
* @author hxm
* @version 1.0
* @since 2015.05.04
*/
class RCache extends Object implements CacheFace
{
private $redis = null; //redis對象
private $sId = 1; //servier服務ID
private $con = null;//鏈接資源
/**
* 初始化Redis
*
* @return Object
*/
public function __construct()
{
if ( !class_exists('Redis') )
{
throw new QException('PHP extension does not exist: Redis');
}
$this->redis = new Redis();
}
/**
* 鏈接memcahce服務
*
* @access private
* @param string $key 關鍵字
* @param string $value 緩存內容
* @return array
*/
private function connect( $sid )
{
$file = $this->CacheFile();
require $file;
if(! isset($cache) )
{
throw new QException('緩存配置文件不存在'.$file);
}
$server = $cache[$this->cacheId];
$sid = isset($sid) == 0 ? $this->sId : $sid;//memcache服務選擇
if ( ! $server[$sid])
{
throw new QException('當前操作的緩存伺服器配置文件不存在');
}希望能幫到你,我還在後盾網學習呢,有不會的可以問我,一會有空回答你。(^ω^)
『捌』 php怎麼將數據導入redis
對於大訪問量的站點使用默認的Session 並不合適,我們可以將其存入資料庫、或者使用Redis KEY-VALUE數據存儲方案
首先新建一個session表
CREATE TABLE `sessions` (
`sid` char(40) NOT NULL,
`updatetime` int(20) NOT NULL,
`data` varchar(200) NOT NULL,
UNIQUE KEY `sid` (`sid`) USING HASH
) ENGINE=MEMORY DEFAULT CHARSET=utf8;
Mysql 的memory引擎採用內存表,所有數據存儲在內存,操作速度快
復制代碼
<?php
//引入資料庫文件
include "db.php";
class MySessionHandler implements SessionHandlerInterface
{
private $savePath;
private $sessData;
public $expiretime; //設置過期時間
public $db; //資料庫
public function __construct($hanlder =''){
$this->db = Database::getInstance();
//獲取資料庫實力
///var_mp($this->db);
}
public function open($savePath, $sessionName)
{
return true;
}
public function close()
{
return true;
}
public function read($id)
{
$sql ="select * from sessions where sid ='$id'";
$result = $this->db->execute($sql);
if(!empty($result)){
return $this->sessData = $result;
}
}
//函數的參數 $id -> 當前會話ID
//數據DATA -> 序列化之後的字元串
public function write($id, $data)
{
// echo $id;
// echo $data;
$now = time();
$newExp = $now+$this->expiretime; //總時間=當前時間 + 期限時間
$sql = "select * from sessions where sid ='$id'";
$result = $this->db->getOne($sql);
//var_mp($result);
if($data==''||isset($data)){
$data = $this->sessData;
}
if($result){
//如果存在則更新
$sql ="update sessions set updatetime = '$newExp',data ='$data' where sid = '$id'";
//echo $sql;
$update_data =$this->db->execute($sql);
if($update_data){
return true;
}
}else{
//不存在則生成生成
$sql = "insert into sessions(sid,updatetime,data) values('$id','$now','$data')";
$insert_data = $this->db->execute($sql);
if($insert_data){
return true;
}
}
return false;
}
public function destroy($id)
{ //銷毀
$sql = "delete from sessions where sid="."$id";
$destory = $this->db->execute($sql);
if($destory){
return true;
}else{
return false;
}
}
public function gc($sessMaxLifeTime)
{
$t = time();
$sql ="delete from sessions where $t - 'updatetime'>${sessMaxLifeTime}";
$data = $this->db->execute($this->tosql);
if($data){
return true;
}else{
return false;
}
return true;
}
}
復制代碼
實例化
此處 PHP 手冊可以有兩種方法
1,實現了SessionHandlerInterface借口的對象,自PHP5.4可以使用
2 ,直接使用 session_set_save_handler
復制代碼
//判斷PHP版本
if(version_compare(PHP_VERSION,5.4)==1){
session_set_save_handler($handler, true);
session_start();
}else{
ini_set('session.use_trans_sid',0);
ini_set('session.use_cookies',1);
ini_set('session.cookie_path','/');
ini_set('session.save_handler','user');
session_mole_name('user');
session_set_save_handler(array($session,"open"),array($session,"close"),array($session,"read"),array($session,"write"),array($session,"destory"),array($session,"gc"));
session_start();
}
$_SESSION['QQ']="QQ";
echo $_SESSION['QQ'];
復制代碼
資料庫代碼 db.php
復制代碼
<?php
class Database{
static $instance;
static $db;
static function getInstance(){
if(self::$instance){
return self::$instance;
}else{
return new Database();
}
}
public function __construct(){
self::$db = new PDO('mysql:host=localhost;dbname=session', 'root','');
}
public function getOne($sql){
$rs =self::$db->query($sql);
@$rs->setFetchMode(PDO::FETCH_ASSOC);//返回關聯數組
$result = $rs -> fetch();
return $result;
}
public function execute($sql){
$rs = self::$db->exec($sql);
return $rs;
}
}
//$data = Database::getInstance();
//var_mp($data);
復制代碼
使用REDIS 存儲SESSION
復制代碼
<?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); //連接redis
$retval = session_set_save_handler(
array($this,"open"),
array($this,"close"),
array($this,"read"),
array($this,"write"),
array($this,"destory"),
array($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 destory($id){
if($this->redis->delete($id)){
return true;
}
return false;
}
public function gc($maxlifetime){
return true;
}
//析構函數
public function __destruct(){
session_write_close();
}
}
$re = new SessionManager();
$_SESSION['name'] = "qq";
echo $_SESSION['name'];
『玖』 如何判斷 redis 連接是否有效
<?php
//第一步:實例化redis對象
$redis = new redis();
//第二步:php客戶端設置的ip及埠
$redis->connect("127.0.0.1","6379");
//第三部:配置連接密碼 檢測redis伺服器連接狀態
//連接失敗直接結束 並輸出
$auth = $redis->auth('zhenai') or die("redis 伺服器連接失敗");
// var_mp($auth);連接成功 返回 true 反之 返回false
//第四步 可用可不用
echo $connect_status=$redis->ping();
if($connect_status==="+PONG")
{
echo "redis 伺服器連接成功";
}
//就是如此簡單
『拾』 PHP 如何在Redis中實現事物(事物提交和事物
public function index()
{
$serv = new \swoole_server("0.0.0.0", 9501);
$serv->set([
'worker_num' => 1,//一般設置為伺服器CPU數的1-4倍
'task_worker_num' => 8,//task進程的數量
'daemonize' => 1,//以守護進程執行
'max_request' => 10000,//最大請求數量
"task_ipc_mode " => 2 //使用消息隊列通信,並設置為爭搶模式
]);
$serv->on('Receive', [$this, 'onReceive']);//接收任務,並投遞
$serv->on('Task', [$this, 'onTask']);//可以在這個方法裡面處理任務
$serv->on('Finish', [$this, 'onFinish']);//任務完成時候調用
$serv->start();
}