『壹』 在php中 為什麼不能使用redis類
redis是一個key-value存儲系統。和Memcached類似,它支持存儲的value類型相對更多,包括string(字元串)、list(鏈表)、set(集合)和zset(有序集合)。這些數據類型都支持push/pop、add/remove及取交集並集和差集及更豐富的操作,而且這些操作都是原子性的。在此基礎上,redis支持各種不同方式的排序。與memcached一樣,為了保證效率,數據都是緩存在內存中。區別的是redis會周期性的把更新的數據寫入磁碟或者把修改操作寫入追加的記錄文件,並且在此基礎上實現了master-slave(主從)同步。
Redis 是一個高性能的key-value資料庫。redis的出現,很大程度補償了memcached這類keyvalue存儲的不足,在部 分場合可以對關系資料庫起到很好的補充作用。它提供了Python,Ruby,Erlang,PHP客戶端,使用很方便。
若想在PHP中使用redis,首先要先安裝redis。然後在PHP中配置擴展。
安裝redis。
首先下載好redis安裝文件,解壓到D盤或其他盤。
然後通過Dos命令行進行安裝。
把這個文件夾復制到其它地方,比如D:\redis 目錄下。
打開一個cmd窗口 使用cd命令切換目錄到D:\redis 運行 redis-server.exe redis.conf
如果想方便的話,可以把redis的路徑加到系統的環境變數里,這樣就省得再輸路徑了,後面的那個redis.conf可以省略,如果省略,會啟用默認的。
這時候另啟一個cmd窗口,原來的不要關閉,不然就無法訪問服務端了
切換到redis目錄下運行 redis-cli.exe -h 127.0.0.1 -p 6379
這時候,就已經完成配置了。
完成了配置之後,要在PHP中添加redis的擴展,之後才可以用PHP靈活的使用它。
在windows下安裝php的redis擴展非常簡單,下載一個.dll擴展包放到php的ext目錄下,在php.ini里邊添加一行配置就可以了。
php代碼測試
redis=newRedis();redis->connect(『127.0.0.1′,6379);
redis−>set(『test′,′helloworld!′);echoredis->get(『test』);
輸出hello world!
『貳』 php 怎麼把session寫入redis
一、 安裝phpredis擴展
php連接redis需要安裝phpredis擴展。
下載地址:https://github.com/phpredis/phpredis/releases,選用相應版本。
筆者用的是php5.6.29,下載了phpredis-3.0.0安裝出了問題,於是換成phpredis-2.2.8,正常。
# tar zxvf phpredis-2.2.8.tar.gz && cd phpredis-2.2.8
# /usr/local/php/bin/phpize
# ./configure --with-php-config=/usr/local/php/bin/php-config
# make && make install
正常情況下會提示在下面目錄下生成redis.so文件
Installing shared extensions: /usr/local/php/lib/php/extensions/no-debug-non-zts-20131226/
# sed -i '$aextension="redis.so"' /usr/local/php/etc/php.ini
# service httpd restart
驗證:
# php -i | grep redis | grep -xq redis && echo ok || echo "phpredis extended failure"
二、 配置php連接redis(筆者使用的阿里雲redis)
# sed -i 's/session.save_handler.*/session.save_handler = redis/' /usr/local/php/etc/php.ini
# sed -i '/session.save_handler/asession.save_path ="tcp://xxxx.rds.aliyuncs.com?auth=redis密碼"' /usr/local/php/etc/php.ini
# service httpd restart
『叄』 java subscribe監聽超時怎麼解決
問題描述
redis提供了pub/sub功能,但在使用phpredis的subscribe時發現這樣一個問題,代碼如下(sub.php):
<?php/*監聽demo頻道,列印收到的信息*/function process($redis, $chan, $msg){
var_mp($msg);
}$redis = new Redis();$res = $redis->connect('127.0.0.1', '7979');$redis->subscribe(array('demo'), 'process');123456789
代碼運行後,發現如果在一段時間內未收到來自demo頻道的消息,則會報如下錯誤:
PHP Fatal error: Uncaught exception 'RedisException' with message 'read error on connection' in sub.php:11Stack trace:#0 /search/ballqiu/sub.php(11): Redis->subscribe(Array, 'process')#1 {main}
thrown in sub.php on line 1112345
原因分析
為了查找原因,我們使用strace對代碼進行了跟蹤:
strace php sub.php1
截取部分重要輸出如下:
//連接redis
connect(3, {sa_family=AF_INET, sin_port=htons(7979), sin_addr=inet_addr("127.0.0.1")}, 16) = -1 EINPROGRESS (Operation now in progress)
//發送subscribe命令
sendto(3, "subscribe demo
", 17, MSG_DONTWAIT, NULL, 0) = 17//收到響應
recvfrom(3, "*3
$9
subscribe
$4
demo
:1
"..., 8192, MSG_DONTWAIT, NULL, NULL) = 33poll([{fd=3, events=POLLIN|POLLPRI|POLLERR|POLLHUP}], 1, 0) = 0 (Timeout)
//套機字超時時間設為60s
poll([{fd=3, events=POLLIN|POLLERR|POLLHUP}], 1, 60000) = 0 (Timeout)
//等待超時,關閉連接
close(3) = 0//輸出錯誤信息
write(2, "PHP Fatal error: Uncaught excep"..., 261PHP Fatal error: Uncaught exception 'RedisException' with message 'read error on connection' 12345678910111213
可見報錯的本質是poll設置接收超時所致,從starce結果我們知道這個超時默認是60s。
解決
我們有兩種方法改變超時
- 方法1
在代碼起始處設置
ini_set('default_socket_timeout', -1);1
方法2
在redis connect後執行
兩種方法中的-1均表示永不超時,你也可以將超時設置為自己希望的時間。
無論使用哪種方法,再次strace, 你會發現poll的超時被設為了-1。
個人比較推薦方法2,它隻影響到redis本身。而方法1會對其它方法產生影響,比如
file_get_contents等。
總結
使用phpredis的subscribe時,默認60內沒有收到消息,sub端就會因超時異常退出。可以自行設置延長超時時間或永不超時。
『肆』 用PHP+Redis實現延遲任務 實現自動取消訂單(詳細教程)
使用PHP和Redis實現延遲任務,如自動取消訂單,可以藉助Redis 2.8版本及以上提供的keyspace notifications功能。這個特性會在指定鍵失效時發送通知,適合處理如業務觸發後需定時執行的任務場景。
首先,你需要在Redis配置中開啟keyspace notifications,雖然這會增加CPU消耗,但為了實時監控,這是必要的。Windows用戶需修改`redis.windows.conf`,將默認配置中的keyevent和過期事件(x)啟用。重啟服務後,配置生效。
接下來,用PHPredis擴展編寫監聽腳本。例如,你可以創建`db.class.php`、`index.php`、`psubscribe.php`和`Redis2.class.php`文件來處理過期事件。在`psubscribe.php`中,使用nohup命令確保腳本後台運行,即使終端關閉也能繼續監聽。遇到MySQL連接問題,可通過調整`wait_timeout`參數或在業務邏輯完成後主動斷開連接解決。
最後,使用`jobs -l`查看和管理後台進程,確保nohup.out文件的清理以及正確退出當前賬戶,以保持命令的持續運行。完整教程中還提到,作者提供了更多進階學習資源,如分布式架構、性能優化等內容,供需要的開發者參考。
『伍』 thinkphp redis 怎麼選擇資料庫
1、redis 中的每一個資料庫,都由一個 redisDb 的結構存儲。其中,redisDb.id 存儲著 redis 資料庫以整數表示的號碼。redisDb.dict 存儲著該庫所有的鍵值對數據。redisDb.expires 保存著每一個鍵的過期時間。
2、當redis 伺服器初始化時,會預先分配 16 個資料庫(該數量可以通過配置文件配置),所有資料庫保存到結構 redisServer 的一個成員 redisServer.db 數組中。當我們選擇資料庫 select number 時,程序直接通過 redisServer.db[number] 來切換資料庫。有時候當程序需要知道自己是在哪個資料庫時,直接讀取 redisDb.id 即可。
3、既然我們知道一個資料庫的所有鍵值都存儲在redisDb.dict中,那麼我們要知道如果找到key的位置,就有必要了解一下dict 的結構了:
typedef struct dict {
// 特定於類型的處理函數
dictType *type;
// 類型處理函數的私有數據
void *privdata;
// 哈希表(2個)
dictht ht[2];
// 記錄 rehash 進度的標志,值為-1 表示 rehash 未進行
int rehashidx;
// 當前正在運作的安全迭代器數量
int iterators;
} dict;
由上述的結構可以看出,redis 的字典使用哈希表作為其底層實現。dict 類型使用的兩個指向哈希表的指針,其中 0 號哈希表(ht[0])主要用於存儲資料庫的所有鍵值,而1號哈希表主要用於程序對 0 號哈希表進行 rehash 時使用,rehash 一般是在添加新值時會觸發,這里不做過多的贅述。所以redis 中查找一個key,其實就是對進行該dict 結構中的 ht[0] 進行查找操作。
4、既然是哈希,那麼我們知道就會有哈希碰撞,那麼當多個鍵哈希之後為同一個值怎麼辦呢?redis採取鏈表的方式來存儲多個哈希碰撞的鍵。也就是說,當根據key的哈希值找到該列表後,如果列表的長度大於1,那麼我們需要遍歷該鏈表來找到我們所查找的key。當然,一般情況下鏈表長度都為是1,所以時間復雜度可看作o(1)。
二、當redis 拿到一個key 時,如果找到該key的位置。
了解了上述知識之後,我們就可以來分析redis如果在內存找到一個key了。
1、當拿到一個key後, redis 先判斷當前庫的0號哈希表是否為空,即:if (dict->ht[0].size == 0)。如果為true直接返回NULL。
2、判斷該0號哈希表是否需要rehash,因為如果在進行rehash,那麼兩個表中者有可能存儲該key。如果正在進行rehash,將調用一次_dictRehashStep方法,_dictRehashStep 用於對資料庫字典、以及哈希鍵的字典進行被動 rehash,這里不作贅述。
3、計算哈希表,根據當前字典與key進行哈希值的計算。
4、根據哈希值與當前字典計算哈希表的索引值。
5、根據索引值在哈希表中取出鏈表,遍歷該鏈表找到key的位置。一般情況,該鏈表長度為1。
6、當 ht[0] 查找完了之後,再進行了次rehash判斷,如果未在rehashing,則直接結束,否則對ht[1]重復345步驟。
到此我們就找到了key在內存中的位置了。
『陸』 怎麼安裝redis PHP擴展,windows下
1、首先到相應網站下載redis:
下載完成後解壓到任意盤符如:D:/redis
裡麵包括:如圖所示。
redis-server.exe:服務程序
redis-check-mp.exe:本地資料庫檢查
redis-check-aof.exe:更新日誌檢查
redis-benchmark.exe:性能測試,用以模擬同時由N個客戶端發送M個 SETs/GETs 查詢 (類似於 Apache 的ab 工具).
當然還需要一個:redis.conf(具體內容網上隨便搜都會有)
8、PHP代碼測試
$redis = new Redis();
$redis->connect("192.168.138.2","6379"); //php客戶端設置的ip及埠
//存儲一個 值
$redis->set("say","Hello World");
echo $redis->get("say"); //應輸出Hello World
//存儲多個值
$array = array('first_key'=>'first_val',
'second_key'=>'second_val',
'third_key'=>'third_val');
$array_get = array('first_key','second_key','third_key');
$redis->mset($array);
var_mp($redis->mget($array_get));