2019年7月1日 星期一

NoSQL Redis intro

Redis是一個使用ANSI C編寫的開源、支援網路、基於記憶體、可選永續性的鍵值對儲存資料庫。

支援rdb 及aof 兩種儲存方式


Redis 目前擁有兩種資料持久化的格式: RDB、AOF
  • RDB:
    • 優點: 備份頻率較 AOF 低,但檔案小、適合作為災難還原的備份檔
    • 缺點: 當服務異常停止時,部分數據可能會遺失
當設定的條件被觸發時,Redis 會 fork() 出子進程 (child process) 在背景進行備份

  • AOF:
    • 優點: 紀錄所有寫入 (Write) 動作的,備份頻率、完整性較 RDB 高
    • 缺點: 檔案大,還原時間較長,不適合備份
在兩種持久化設定都打開的情況下,由於每次的寫入操作皆會被保存進 AOF ,使得它的資料完整度較高,因此 Redis 在重啟後會選擇讀取 AOF 檔案進行還原。若 AOF 設定為關閉的狀況,才會選用 RDB 進行還原。
RDB 在寫入檔案時,會開thread 去進行,較吃CPU資源
AOF 會依照檔案儲存大小吃掉對應的記憶體量


RDB vs AOF

安裝


1.Ubuntu
$sudo apt-get update
$sudo apt-get install redis-server
 
 
$ redis-server

2.Windows
下載binary
解壓或執行msi 安裝到任意目錄
cmd 進到安裝目錄後,執行 
redis-server.exe redis.windows.conf

3.Docker
看要哪個tag
$docker run -it --rm -p 6379:6379 library/redis:5-alpine

工具

1.redis-cli
指令工具,內部使用REST 發命令到redis-server 
可以查詢記憶體、新增移除資料、設置server 等等

2.redis-benchmark
協助測試調適redis 的工具

配置檔案

參考redis.conf 
#啟用/關閉 RDB
#300秒存一次RDB 或KEY 修改超過10次
#可以設多個閥值
save 300 10 
 
 
#關閉RDB
save ""
 
 
#儲存RDB 檔名為dump.rdb
dbfilename dump.rdb
 
 
#儲存RDB 及AOF的目錄
dir /usr/lib/mcm100/data
 
 
#同時可接受連線數
maxclients 10000
 
 
#REDIS 記憶體上限設置 單位byte
maxmemory 67108864
 
 
#當記憶體達上限時,要如何處理
# volatile-lru -> Evict using approximated LRU among the keys with an expire set.
# allkeys-lru -> Evict any key using approximated LRU.
# volatile-lfu -> Evict using approximated LFU among the keys with an expire set.
# allkeys-lfu -> Evict any key using approximated LFU.
# volatile-random -> Remove a random key among the ones with an expire set.
# allkeys-random -> Remove a random key, any key.
# volatile-ttl -> Remove the key with the nearest expire time (minor TTL)
# noeviction -> Don't evict anything, just return an error on write operations.
maxmemory-policy allkeys-lru
 
 
#啟用AOF,no 則關閉
appendonly yes
 
 
#AOF檔名
appendfilename "appendonly.aof"
 
#寫入AOF的頻率
# no: don't fsync, just let the OS flush the data when it wants. Faster.
# always: fsync after every write to the append only log. Slow, Safest.
# everysec: fsync only one time every second. Compromise.
appendfsync everysec
 
 
 
 
#當AOF 大小達64mb 自動壓縮
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

License

  • Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  • Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  • Neither the name of Redis nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
Reference:Redis license

Python Token sample


Token vs Cookie

流程差不多,差別在Cookie 是在第一次response 時代有set cookie 的訊息;Token 則是回傳一連串的字符
但Token 多了兩個優勢,讓他的scalability 更好
  • 無狀態:Token 不需要保存session,一切以Token 反計算判斷身分,Token 本身通常帶有時間性
  • 可以多裝置多網域:呈上,Token 是用計算的方式判斷身分,所以使用API 跟取得Token 的Server 只要共享用戶資料就行


Python module:itsdangerous  https://itsdangerous.readthedocs.io/en/latest/

itsdangerous  提供多種簽名或序列化的物件
  • Signing : 在string 後面加亂數簽章
  • Timestamp Signing :同上,但是有時效性
  • Serialization :Signing 只能針對字串,Serialization  則不限
  • Timestamp Serialization :同上,但是有時效性
  • URL Safe Serialization : 有別於前面的,會保留原內容再外加簽章,此物件只會產生簽章
  • JSON Web Signature:是一種常用的Token 標準,將JSON 物件 隱含在簽章內,通常稱為JWT (JSON Web Token)
  • Timestamp JSON Web Signature:同上,但是有時效性


JWT

由header、payload、Signature 組成,如下
eyJhbGciOiJIUzI1NiJ9 表header,表示使用的演算法
eyJ4Ijo0Mn0 表{"X":42}
ZdTn1YyGz9Yx5B5wNpWRL221G1WpVE5fPCPKNuc6UAo 簽章,搭配secret key 任一字串讓server 匹配檢查用
from itsdangerous import JSONWebSignatureSerializer
= JSONWebSignatureSerializer("secret-key")
s.dumps({"x"42})
'eyJhbGciOiJIUzI1NiJ9.eyJ4Ijo0Mn0.ZdTn1YyGz9Yx5B5wNpWRL221G1WpVE5fPCPKNuc6UAo'

若使用JWT,將帳號資料代入payload,則產生的token 就可以在有相同帳號資料的Server 使用

以下有個不錯的範例,使用itsdangerous 搭配flask

1.啟動後預設port 5000
2.使用curl 建立帳密,因為一開始沒SQL,先用一次這個API後,目錄內會產生sqlite 檔案存放帳號資料
帳號 miguel、密碼 python
$ curl -i -X POST -H "Content-Type: application/json" -d '{"username":"miguel","password":"python"}' http://127.0.0.1:5000/api/users
3.使用curl 取得token
代入帳密,若符合SQL內資料就會回傳JSON 內有Token,時效為600秒
$ curl -u miguel:python -i -X GET http://127.0.0.1:5000/api/token
HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 139
Server: Werkzeug/0.9.4 Python/2.7.3
Date: Thu, 28 Nov 2013 20:04:15 GMT
 
{
  "duration": 600,
  "token""eyJhbGciOiJIUzI1NiIsImV4cCI6MTM4NTY2OTY1NSwiaWF0IjoxMzg1NjY5MDU1fQ.eyJpZCI6MX0.XbOEFJkhjHJ5uRINh2JA1BPzXjSohKYDRT472wGOvjc"
}
4.使用curl 呼叫需要身分認證的API
注意因為這個實作是使用HTTP 的authorization 欄位,有帳號跟密碼,帳號填Token,密碼為任意;見下方範例填 ignore
$ curl -u eyJhbGciOiJIUzI1NiIsImV4cCI6MTM4NTY2OTY1NSwiaWF0IjoxMzg1NjY5MDU1fQ.eyJpZCI6MX0.XbOEFJkhjHJ5uRINh2JA1BPzXjSohKYDRT472wGOvjc:ignore -i -X GET http://127.0.0.1:5000/api/resource
HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 30
Server: Werkzeug/0.9.4 Python/2.7.3
Date: Thu, 28 Nov 2013 20:05:08 GMT
 
{
  "data""Hello, miguel!"
}

簡單實驗Token 的好處:
1.將範例的api.py 複製一份,然後修改port 4000,再啟動
2.現在兩支程式都啟動後,假設你在port 5000 取得Token,該Token 一樣可以用在port 4000 的API
因為同個目錄有分享同一個SQL
3.簡單得證,若A和B 有分享帳號資料,在A 地方取得Token ,可以在B地方使用Token

NoSQL Redis intro

Redis是一個使用ANSI C編寫的開源、支援網路、基於記憶體、可選永續性的鍵值對儲存資料庫。 支援rdb 及aof 兩種儲存方式 From  https://zh.wikipedia.org/wiki/Redis Redis 目前擁有兩種資料...