2016/06/26

Redis-Server with PHP 的使用 in CentOS7

Redis-Server with PHP 的使用 in CentOS7

* Redis DB server 的用途
Redis 是一個 key-value 架構的 database , 且因為它工作在記憶體上面,所以速度非常的快。
可以用來當 DB cache 加速的功能或是需要快速反應的 DB

* CentOS 7 的 Redis-server 安裝方式
# yum install redis -y 
* 安裝參考
http://sharadchhetri.com/2014/10/04/install-redis-server-centos-7-rhel-7/

* 通常會搭配 php 等 client 端工具一起安裝, 這裡我是以 php56w 的版本安裝, 因為有比較多 lib 支援
# yum install php56w-pecl-redis
* php56w 可以參考 webtatic 釋出的 yum repo 安裝參考 https://webtatic.com/packages/php56/ RHEL7 OR EPEL7  官方網站跑的版本有點慢,可以先參考這個版本。

* 啟動
# systemctl start redis.service
* 預設開機啟動
# systemctl enable redis.service
* 看狀態
# systemctl status redis.service

* 測試 , 剛裝好的 redis-server 是沒有密碼的, 且只能 127.0.0.1 執行。 可以用 redis-cli client 端工具測試 PONG 是正確的回應。
[root@c7 ~]# redis-cli ping
PONG

* 所以我都會設定個密碼, 並且把 bind 打開讓所有人都可以連上來。
* 請找到下面兩行, 修改為你要的密碼及主機 ip
# vim /etc/redis.conf
bind 111.111.22.22
requirepass 123456

* 重新啟動
# systemctl restart redis.service

* 驗證看看 port , 應該是 6379
# netstat -antlp | grep redis
tcp        0      0 111.111.22.22:6379     0.0.0.0:*               LISTEN      22326/redis-server

* 加了密碼的測試
# redis-cli -a '123456' -h 111.111.22.22 ping
PONG

* man page 內的 Examples , 不帶密碼的測試, 可以試試看
  cat /etc/passwd | redis-cli -x set mypasswd
  redis-cli get mypasswd
  redis-cli -r 100 lpush mylist x
  redis-cli -r 100 -i 1 info | grep used_memory_human:
  redis-cli --eval myscript.lua key1 key2 , arg1 arg2 arg3
  redis-cli --scan --pattern '*:12345*'

* 專案網站 http://redis.io/
* 文件網站:http://redis.io/documentation
* 中文翻譯的教學文件(redis-cli) http://www.runoob.com/redis/redis-tutorial.html
* Redis 中文文件 https://www.gitbook.com/book/wizardforcel/redis-doc/details

* 通常會裝個 REDIS 桌面管理工具來觀看, 否則看不到東西怪怪的 http://redisdesktop.com/download











----------------------------------------
* PHP 在 REDIS 上面的操作
----------------------------------------

* 在 php 上面有個 phpredis/phpredis 的函式庫, 可以讓你利用他來寫 redis 上面的程式
* https://github.com/phpredis/phpredis github 上面的 readme 就是使用的方式, 幾乎可以很完整的操作了

使用 php + redis server 模擬 session 的動作
https://github.com/mtchang/code/blob/master/redis_session.php


<?php
// ref:https://github.com/mtchang/code/blob/master/redis_session.php
// 使用 php + redis server 模擬 session 的動作
// Author: mtchang.tw@gmail.com
// Date: 2016.6.26
$time_start = microtime(true);
// --------------------------------------
// 建立一個 redis client 連線
// --------------------------------------
$redis = new Redis();
// 2 秒 timeout
if($redis->connect('192.168.111.111', 6379, 2)) {
// success
if($redis->auth('12345678')) {
echo 'Authentication Success';
}else{
die('Authentication failed');
}
}else{
// error
die('Connection Failed');
}
// 選擇 DB
$redis->select(1);
echo "Server is running: ".$redis->ping();
// --------------------------------------
// 建立一個 redis 的 session 連線
// --------------------------------------
// 如果 jangmt_session 存在 user cookie 的話, 取回這個 session 的資料
if(isset($_COOKIE['jangmt_session'])) {
$session['key'] = $_COOKIE['jangmt_session'];
$get_session_string = $redis->get($session['key']);
$get_session = json_decode($get_session_string);
// 取回 session 後, 更新 cookie and session timeout value
// 設定 timeout 值
$session['server_time'] = time(true);
$session['expire'] = 300;
$session['expire_time'] = $session['server_time']+$session['expire'];
// 將編碼成為 json 的 array 寫入 redis , 以 $session['key'] 為 key , $session['expire_time'] 為 timeout
$session_json = json_encode($session);
$redis->set($session['key'], $session_json);
$redis->expireAt($session['key'], $session['expire_time']);
// setcookie(name,value,expire,path,domain,secure)
$cookie['name'] = 'jangmt_session';
$cookie['value'] = $session['key'];
$cookie['expire'] = $session['expire_time'];
$cookie['domain'] = 'jangmt.com';
$cookie['secure'] = '';
// 執行 setcookie , 如果重複就是更新 timeout value ,
// setcookie 這行一定要是 http 第一個輸出。
setcookie($cookie['name'], $cookie['value'], $cookie['expire']);
echo '取回存在的 session <br>';
}else{
// 如果沒有 cookie 的話, 註冊一個 session
$session['server_microtime'] = microtime(true);
$session['key_plain'] = $session['server_microtime'].':'.$_SERVER['REMOTE_ADDR'].':'.rand();
$session['key_id'] = md5("mtchang.tw@gmail.com");
$session['key'] = 'jangmt_session:'.$session['key_id'].':'.md5($session['key_plain']);
// 設定 timeout 值
$session['server_time'] = time(true);
$session['expire'] = 300;
$session['expire_time'] = $session['server_time']+$session['expire'];
// 對於使用者 browser 寫入 cookie , 並設定 timeout, 下次如果還沒 timeout 的話, 就使用這個 cookie
// setcookie(name,value,expire,path,domain,secure)
$cookie['name'] = 'jangmt_session';
$cookie['value'] = $session['key'];
$cookie['expire'] = $session['expire_time'];
$cookie['domain'] = 'jangmt.com';
$cookie['secure'] = '';
// 執行, 如果重複就是更新 timeout value
setcookie($cookie['name'], $cookie['value'], $cookie['expire']);
$session_json = json_encode($session);
// 將編碼成為 json 的 array 寫入 redis , 以 $session['key'] 為 key
$redis->set($session['key'], $session_json);
$redis->expireAt($session['key'], $session['expire_time']);
$get_session_string = $redis->get($session['key']);
$get_session = json_decode($get_session_string);
echo '註冊一個新的 session <br>';
}
$time_end = microtime(true);
$time = $time_end - $time_start;
echo "<p>Did nothing in $time seconds </p>";
?>

* 可以使用 phpRedisAdmin 工具, 從網頁觀看 redis 的使用狀況
https://github.com/erikdubbelboer/phpRedisAdmin 原始碼位置,此工具可以用 composer 安裝。

PHPRedisAdmin 網頁界面看 redis session 程式


* 可以 把 PHP 的 session handler 改用 redis server 紀錄
方法如這裡 https://github.com/phpredis/phpredis#php-session-handler

* 直接修改 php.ini 檔案,找到 session 這段, 設定完成後 restart httpd or php-fpm 就可以
# vim /etc/php.ini
[Session]
; 支持 redis db 的 php session
session.save_handler = redis
session.save_path = "tcp://111.111.22.22:6379?auth=123456"

* 也可以寫成類似這樣, 當多台主機同時用時可以分散負載.
;session.save_path="tcp://127.0.0.1:11211?persistent=1&weight=1&timeout=1&retry_interval=15″
* 在 centos7 實際執行時發現, 因為 php.ini 有很多地方都有放, 要注意不同的設定檔蓋掉這個設定。

PHPSESSION 再 redis 上的顯示

# 當網頁可以執行 phpinfo(); 會有有安全性風險 , 有可能洩漏你的認證密碼, 建議多設定防火牆防外賊。
[root@c7 etc]# php -i | grep session
.... skip ....
session.save_path => tcp://111.111.22.22:6379?auth=123456 => tcp://111.111.22.22:6379?auth=123456
.... skip ....

* 建議設定 iptalbes 範例
# 擋掉特定 ip , 允許特定 ip, 開啟 port
EXTIF="enp2s0f0" # 系統對外網卡
iptables -A INPUT -p TCP -s 111.111.69.0/24 --dport  6379 --sport 1024:65534 -j ACCEPT # redis accept
iptables -A INPUT -p TCP -i $EXIT  --dport  6379 --sport 1024:65534 -j REJECT # redis reject

# 效能測試
# redis-benchmark -a '123456' -h 111.111.22.22 -c 1000 -n 100 -q
PING_INLINE: 3703.70 requests per second
PING_BULK: 7692.31 requests per second
SET: 4347.83 requests per second
GET: 8333.33 requests per second
INCR: 11111.11 requests per second
LPUSH: 8333.33 requests per second
LPOP: 3703.70 requests per second
SADD: 9090.91 requests per second
SPOP: 8333.33 requests per second
LPUSH (needed to benchmark LRANGE): 4347.83 requests per second
LRANGE_100 (first 100 elements): 3448.28 requests per second
LRANGE_300 (first 300 elements): 9090.91 requests per second
LRANGE_500 (first 450 elements): 8333.33 requests per second
LRANGE_600 (first 600 elements): 7142.86 requests per second
MSET (10 keys): 8333.33 requests per second

* 使用 redis 來當成 php session handler in Ubuntu
https://www.digitalocean.com/community/tutorials/how-to-set-up-a-redis-server-as-a-session-handler-for-php-on-ubuntu-14-04

* 可以用來做統計的 
piwik http://demo.piwik.org/

* redis 統計工具
https://github.com/junegunn/redis-stat

* 程式開發參考
http://www.cnblogs.com/ikodota/archive/2012/03/05/php_redis_cn.html
https://github.com/phpredis/phpredis
https://scotch.io/tutorials/getting-started-with-redis-in-php
http://www.runoob.com/redis/redis-hashes.html

2016/06/04

53 分鐘

今天看到一個數字, 53 分鐘. 就想到 Amazon Route 53 (http://aws.amazon.com/tw/route53/)

小小的算了一下
一年的時間 60*24*365.25=525,960 分鐘
可用性指標 = (1-故障時間/整年分鐘)*100%
99.99=(1- X/525960)*100%
X = 53分鐘

所以  Route53 應該是Amazon很委婉的表達他是 99.99% 的網站可用性...

好巴,算你有囂張的本錢。