2015年1月21日 星期三

Redis RedisOutputCacheProvider

先開個Web專案

安裝Microsoft.Web.RedisOutputCacheProvider套件

web.config中的caching區段會自動帶入預設的設定
註解的說明也很清楚
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5" />
    <caching>
      <outputCache defaultProvider="MyRedisOutputCache">
        <providers>
          <!-- Either use 'connectionString' and provide all parameters as string OR use 'host','port','accessKey','ssl','connectionTimeoutInMilliseconds' and 'operationTimeoutInMilliseconds'. -->
          <!-- 'databaseId' and 'applicationName' can be used with both options. -->
          <!--
          <add name="MyRedisOutputCache" 
            host = "127.0.0.1" [String]
            port = "" [number]
            accessKey = "" [String]
            ssl = "false" [true|false]
            databaseId = "0" [number]
            applicationName = "" [String]
            connectionTimeoutInMilliseconds = "5000" [number]
            operationTimeoutInMilliseconds = "1000" [number]
            connectionString = "<valid StackExchange.Redis connection string>" [String]
          />
          -->
          <add name="MyRedisOutputCache" type="Microsoft.Web.Redis.RedisOutputCacheProvider" host="10.9.11.64" accessKey="" ssl="false" />
        </providers>
      </outputCache>
    </caching>
  </system.web>
</configuration>

隨便輸出點東西
namespace WebApplication1
{
    using System;

    public partial class WebForm1 : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            Response.Write(DateTime.Now);
        }
    }
}

頁面啟用快取
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="WebApplication1.WebForm1" %>
<%@ OutputCache Duration="60" VaryByParam="*" %>
<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
    
    </div>
    </form>
</body>
</html>

網頁輸出的結果

Redis上面存在的資料

Redis SessionStateProvider

首先開一個Web專案

安裝Microsoft.Web.RedisSessionStateProvider套件

設定檔中的sessionState自動會加入一段設定,註解的說明也很清楚
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5" />
    <sessionState mode="Custom" customProvider="MySessionStateStore">
      <providers>
        <!-- Either use 'connectionString' and provide all parameters as string OR use 'host','port','accessKey','ssl','connectionTimeoutInMilliseconds' and 'operationTimeoutInMilliseconds'. -->
        <!-- 'throwOnError','retryTimeoutInMilliseconds','databaseId' and 'applicationName' can be used with both options. -->
        <!--
          <add name="MySessionStateStore" 
            host = "127.0.0.1" [String]
            port = "" [number]
            accessKey = "" [String]
            ssl = "false" [true|false]
            throwOnError = "true" [true|false]
            retryTimeoutInMilliseconds = "5000" [number]
            databaseId = "0" [number]
            applicationName = "" [String]
            connectionTimeoutInMilliseconds = "5000" [number]
            operationTimeoutInMilliseconds = "1000" [number]
            connectionString = "<valid StackExchange.Redis connection string>" [String]
          />
        -->
        <add name="MySessionStateStore" type="Microsoft.Web.Redis.RedisSessionStateProvider" host="10.9.11.64" accessKey="" ssl="false" />
      </providers>
    </sessionState>
  </system.web>
</configuration>


隨便存取一個session
namespace WebApplication1
{
    using System;

    public partial class WebForm1 : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            var obj = Session["abc"];
            if (obj == null)
            {
                obj = DateTime.Now;
                Session["abc"] = obj;
            }

            Response.Write(Session.SessionID + "<br/>");
            Response.Write(obj);
        }
    }
}

網頁輸出的資料

Redis上面存放的資料




Redis 持久化

Redis有兩種持久化方式,一種是RDB,一種是Append,可同時使用
RDB是定時快照,觸發條件發生時,會把當時記憶體的資料存成檔案
所以一旦發生故障,損失的資料較多

啟用RDB持久化
# save 900 1
# save 300 10
# save 60 10000

關閉RDB持久化
#   save ""

設定是否可以壓縮
rdbcompression yes

設定RDB的檔名
dbfilename dump.rdb

設定檔案的資料夾位置
dir ./

===============================================
AOF是把收到的指令,用純文字檔的方式附加到檔案中,資料持久化的效能較完整

啟用AOF持久化
# appendonly no

AOF檔案名稱
# appendfilename appendonly.aof

AOF檔案寫入的方式
# appendfsync always
appendfsync everysec
# appendfsync no

設定AOF檔案重整的時間
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

Redis StoredSet

指令 說明
ZADD 將一個或多個元素加入有序集合
ZCARD 取得有序集合中的元素個數
ZCOUNT 取得有序集合中,score值在min到max的元素個數
ZINCRBY 設定有序集合中的成員score遞增值
ZRANGE 取得有序集合中指定位置範圍的元素
ZRANGEBYSCORE 取得有序集合中指定score範圍的元素
ZRANK 取得有序集合中元素從大到小的排列順序
ZREM 移除有序集合中一個或多個元素
ZREMRANGEBYRANK 移除有序集合中指定排名範圍的元素
ZREMRANGEBYSCORE 移除有序集合中指定score範圍的元素
ZREVRANGE 取得有序集合中指定位置範圍的元素
元素以遞減方式排列
ZREVRANGEBYSCORE 取得有序集合中指定score範圍的元素
元素以遞減方式排列
ZREVRANK 取得有序集合中元素從小到大的排列順序
ZSCORE 取得有序集點中元素的score值
ZUNIONSTORE 合併一個或多個有序集合的聯集
並把合併後的資料存成另一個有序集合
ZINTERSTORE 合併一個或多個有序集合的交集
並把合併後的資料存成另一個有序集合
ZSCAN 搜尋有序集合元素
ZRANGEBYLEX 取得有序集合中指定位置範圍的元素
當元素有相同的score時,用成員的字典順序排列
ZLEXCOUNT 取得有序集合中指定位置範圍的元素數量
當元素有相同的score時,用成員的字典順序排列
ZREMRANGEBYLEX 移除有序集合中指定排名範圍的元素
當元素有相同的score時,用成員的字典順序排列

2015年1月20日 星期二

Redis Set

指令 說明
SADD 將一或多個元性加入集合
SCARD 取得集合中元素的數量
SDIFF 取得集合中的差集
SDIFFSTORE 取得集合中的差集,並將結果存到另一個集合
SINTER 取得集合中的合集
SINTERSTORE 取得集合中的合集,並將結果存到另一個集合
SISMEMBER 判斷集合中是否有指定的元素
SMEMBERS 取得集合中的所有元素
SMOVE 將集合中的元素移動到另一個集合
SPOP 隨機取得集合中的元素,並移除該元素
SRANDMEMBER 隨機取得集合中的元素,不移除該元素
SREM 移除集合中的一個或多個元素
SUNION 取得集合中的聯集
SUNIONSTORE 取得集合中的聯集,並將結果存到另一個集合
SSCAN 搜尋集合中的元素

Redis List

指令 說明
BLPOP 阻塞式指令,從開頭彈出內容
BRPOP 阻塞式指令,從尾端彈出內容
BRPOPLPUSH 阻塞式指令,從尾端彈出內容,並把彈出的內容加入一個List的頭部
LINDEX 取得List中指定位置的內容
LINSERT 配合AFTER和BEFORE來決定插入指定位置的前面或後面
LLEN 取得List的長度
LPOP 從開頭彈出資料
LPUSH 從開頭加入資料
LPUSHX 從開頭加入資料,只有當鍵值存在並且是一個List的時後才成功
LRANGE 取得指定範圍內的資料
LREM 移除和指定內容相同的元素和個數
LSET 設定指定的資料
LTRIM 只保留指定範圍內的資料,不在指定範圍的資料全部移除
RPOP 從尾部彈出資料
RPOPLPUSH 從尾部彈出資料,並把彈出的資料加入一個List的頭部
RPUSH 從尾部加入資料
RPUSHX 從尾部加入資料,只有當鍵值存在並且是一個List的時後才成功

Redis Hash

指令 說明
HDEL 刪除指定的鍵值裡面的欄位
HEXISTS 檢查指定的鍵值欄位是否存在
HGET 取得指定的鍵值欄位內容
HGETALL 取得指定的鍵值所有欄位內容
HINCRBY 指定的鍵值欄位內容遞增加一
HINCRBYFLOAT 指定的鍵值欄位內容遞指定的浮點數
HKEYS 取得指定鍵值的所有欄位名稱
HLEN 取得指定鍵值的欄位數量
HMGET 同時取得多組指定鍵值的欄位內容
HMSET 同時設定多組指定鍵值的欄位內容
HSET 設定指定鍵值的欄位內容
HSETNX 設定指定鍵值的欄位內容
HVALS 取得指定鍵值的所有欄位的內容
HSCAN 查詢指定鍵值的欄位名稱

Redis String

指令 說明
APPEND 拼接字串
BITCOUNT 計算字串中的二進位值被設成1的個數
BITOP 字串中的二進位值的位元操作
DECR 遞減值一
DECRBY 遞減指定的值
GET 取得指定鍵值的內容
GETBIT 取得指定鍵值的二進位內容
GETRANGE 取得指定鍵值的資料特定位置的內容
GETSET 設定指定鍵值的內容,並返回舊值
INCR 遞增值一
INCRBY 遞增指定的值
INCRBYFLOAT 遞增指定的浮點數值
MGET 一次取回多組指定的key value
MSET 一次設定多組key value
MSETNX 一次設定多組key value,並且所有設定的key都不存在才成功
PSETEX 設定key value,並指定過期時間,單位是毫秒
SET 設定key value
配合ex參數設定過期時間,單位是秒
配合px參數設定過期時間,單位是毫秒
配合nx參數只有key不存在時才成功
配合xx參數只有key已存在時才成功
SETBIT 設定指定鍵值的二進位資料
SETEX 設定key value,並指定過期時間,單位是秒
SETNX 設定key value,並只有在key不存在時才成功
SETRANGE 更改特定位置的資料內容
STRLEN 取得指定鍵值的內容長度

Redis Key

指令 說明
DEL 刪除指定的Key
DUMP 將指定key的內容匯出二進位內容
配合RESTORE指令可以把資料還原
EXISTS 判斷指定的Key是否存在
EXPIRE 用來設定Key的過期時間,單位是秒
EXPIREAT 用來設定Key的過期時間,單位是秒,UNIX時間戳記
KEYS 用來查詢目前Redis實體上的Key
可配合pattern查詢
MIGRATE 搬移資料到不同的Redis執行個體
MOVE 將指定的Key值搬到同一個Redis執行個體的不同資料庫
OBJECT 用來顯示該Key值的特性
OBJECT REFCOUNT <key> 取得該key的異動次數
OBJECT ENCODING <key> 取得該key的編碼
OBJECT IDLETIME <key> 取得該key未被存取的秒數
PERSIST 取消KEY上面的過期時間
PEXPIRE 用來設定Key的過期時間,單位是毫秒
PEXPIREAT 用來設定Key的過期時間,單位是毫秒,UNIX時間戳記
PTTL 取得Key到期的剩餘時間,單位是毫秒
RANDOMKEY 隨機取得一個Key
RENAME 更名Key的名稱,如果新名稱已存在會覆蓋
RENAMENX 當key的新名稱不存在時,才更名Key的名稱
RESTORE 配合DUMP指令匯出的二進位內容
用來把資料還原
SORT 排序指定key的內容
配合limit可限制筆數

TTL 取得Key到期的剩餘時間,單位是秒
TYPE 取得指定Key的內容的資料型態
SCAN 搜尋Key,可配合pattern
返回結果是一個迭代的指標

Redis C# Client - StackExchange.Redis

先透過NuGet安裝StackExchange.Redis這個套件
如果需要簽署的元件,可以安裝StackExchange.Redis.StrongName這個套件


透過ConnectionMultiplexer這個類別來產生連線,並重覆使用
再透過GetDatabase來取得要IDatabase介面,就可以存取Redis了
namespace ConsoleApplication1
{
    using System;
    using StackExchange.Redis;

    class Program
    {
        static void Main(string[] args)
        {
            ConnectionMultiplexer conn = ConnectionMultiplexer.Connect("127.0.0.1:6379");
            IDatabase cache = conn.GetDatabase();
            cache.StringSet("key1", "value1");
            string data = cache.StringGet("key1");
            Console.WriteLine(data);
        }
    }
}


參考資料

StackExchange.Redis官網

2015年1月19日 星期一

Redis 設定檔

用來指派空間的單位簡寫,不區分大小寫
# 1k => 1000 bytes
# 1kb => 1024 bytes
# 1m => 1000000 bytes
# 1mb => 1024*1024 bytes
# 1g => 1000000000 bytes
# 1gb => 1024*1024*1024 bytes

伺服器埠號
port 6379

繫結位址,預設是本機全部
# bind 127.0.0.1

Client連線閒置多久要切斷連線,單位為秒,0是不限制時間
timeout 0

################################ 快照設定  #################################
第一個參數是秒數,第二個參數是異動次數
符合以下任一條件,就執行一次快照,產生dump.rdb

save 900 1
save 300 10
save 60 10000

產生快照檔時是否要壓縮檔案
rdbcompression yes

快照檔案的檔名
dbfilename dump.rdb

快照檔案的路徑
dir ./

################################# 覆寫 #################################

在slave的實體上,用來指定master的位址
# slaveof <masterip> <masterport>

如果master需要驗證密碼時設定
# masterauth <master-password>

當slave和master斷線,或是正在同步中,是否回應Client端要求
設定成no會回應一個SYNC with master in progress的錯誤
slave-serve-stale-data yes

設定slave是否唯讀
slave-read-only yes

slave對master實體ping的時間間隔,單位是秒數
# repl-ping-slave-period 10

master傳輸或是ping回應的時間間隔,單位是秒數
# repl-timeout 60

slave和master同步後,是否要延遲同步,讓master合併小封包再一回氣同步到slave
效能較佳,但資料可能不同步
repl-disable-tcp-nodelay no

slave優先權,當master無法服務時,數字低的優先被提升為master
slave-priority 100

################################## 安全 ###################################

Client連線時是否需要密碼
# requirepass foobared

重寫命令,設定成空字串來禁用命令
# rename-command CONFIG ""

################################### 限制 ####################################

最大連線數
# maxclients 10000

最大記憶體
# maxmemory <bytes>

當記憶體達到上限,使用那一種刪除演算法
# volatile-lru:使用LRU演算法刪除帶有過期標記的key
# allkeys-lru:使用LRU演算法刪除任何Key
# volatile-random:隨機移除一個帶有過期標記的Key
# allkeys-random:隨機移除一個Key
# volatile-ttl:移除快要過期的Key
# noeviction:不移除Key,回應一個錯誤給Client端
預設為volatile-lru
# maxmemory-policy volatile-lru

LRU演算法的樣本範圍
# maxmemory-samples 3

############################## AOF模式 ##########################

是否啟用AOF持久化模式
appendonly no

AOF模式的檔案名稱
# appendfilename appendonly.aof

AOF模式的寫入時機
no:由作業系統決定,性能最好,可靠性最低
everysec:每秒執行一次寫入
always:每次都寫入硬碟,效能最差
# appendfsync always
appendfsync everysec
# appendfsync no

在阻塞命令時阻止faync在主程序中被呼叫
no-appendfsync-on-rewrite no

AOF自動重寫設定,把重覆的命令合併以減少檔案大小
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb


################################ LUA 腳本  ###############################
lua腳本的最大執行時間,單位是毫秒
lua-time-limit 5000

################################## SLOW LOG ###################################
用來記錄超出執行時間的命令,單位為微秒,10000等於1秒
slowlog-log-slower-than 10000

slowlog的長度,超過設定長度後,最舊的會被移除
slowlog-max-len 128

############################### 進階設定 ###############################
設定hash的資料超過多少數量時,切換使用的數據結構
hash-max-ziplist-entries 512
hash-max-ziplist-value 64

設定list的資料超過多少數量時,切換使用的數據結構
list-max-ziplist-entries 512
list-max-ziplist-value 64

設定set的資料超過多少數量時,切換使用的數據結構
set-max-intset-entries 512

設定stored set的資料超過多少數量時,切換使用的數據結構
zset-max-ziplist-entries 128
zset-max-ziplist-value 64

hash是否使用延遲刷新機制,越多操作,越多刷新
activerehashing yes

第一個參數是強制限制,第二個參數是軟性限制,和軟性時間
當客戶輸出緩存達到限制時,會強制斷開連線
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60

背景任務執行頻率,範圍為1到500,預設為10
設定越大,CPU消耗越大,延遲越小
hz 10

啟用子行程重寫AOF檔案
aof-rewrite-incremental-fsync yes

Redis 安裝

在Linux環境上安裝Redis,最簡單的方式是用套件管理(apt or yum),但通常不是最新版本
如果要使用最新版本,需要到官網下載原始碼編譯
$ wget http://download.redis.io/releases/redis-2.8.19.tar.gz
$ tar xzf redis-2.8.19.tar.gz
$ cd redis-2.8.19
$ make

編譯如果碰到這個情況
make[1]: Entering directory '/tmp/redis-2.8.19/src'
    CC adlist.o
In file included from adlist.c:34:0:
zmalloc.h:50:31: fatal error: jemalloc/jemalloc.h: No such file or directory
 #include <jemalloc/jemalloc.h>
                               ^
compilation terminated.

可以到deps下面先行編譯
$ cd deps
$ make hiredis jemalloc linenoise lua

或是直接執行以下的命令
$ make MALLOC=libc

Windows下的安裝,可以參考MSOpenTech在github上面的文件
https://github.com/MSOpenTech/redis

可以直接下載編譯好的版本
https://github.com/MSOpenTech/redis/releases

更簡單的方式是透過nuget下載,連設定都有,套件名稱為redis-64
https://www.nuget.org/packages/Redis-64/

設定Service
redis-server --service-install redis.windows.conf --loglevel verbose

解除Service
redis-server --service-uninstall

2015年1月5日 星期一

設定負載測試

新增負載測試

建立新負載測試精靈歡迎畫面

輸入這個負載測試的名稱
考慮時間特性,指的是每個動作之間考慮時間的方式
使用記錄的考慮時間,會是設定好的固定時間
使用常態分佈,會動態加減時間,比較符合真實的使用者習慣

負載模式是用來設定連線的使用者數
常數負載是固定人數
逐步執行負載是設定初始人數在再幾秒內持續增加人數至最高人數

測試混合模型

測試混合是設定多個測試和各自的比例

混路混合是設定多個網路類型和各自的比例

瀏覽器混合是設定多個瀏覽器和各自的比例

計數器集合

回合設定是設定執行次數或是持續時間

設定Web效能測試

加入Web效能測試

如果看到這個錯誤訊息,是IE瀏覽器的安全性設定造成的

在伺服器管理員中,點擊設定IE ESC

把管理員關閉就行了

在瀏覽器中就會看到錄製工具列

在網址列隨便輸入網址,就會看到自動錄製操作

按下停止錄制後,會把錄製的結果帶回Visual Studio
可以在已錄制的項目上按屬性來修改,也可以手動插入要求

接下來介紹如果繫結資料,先準備一個XML檔案

隨便輸入一些資料
<?xml version="1.0" encoding="utf-8"?>
<customers>
  <customer account="aa" />
  <customer account="bb" />
  <customer account="cc" />
</customers>

點擊新增資料來源

選擇剛準備的XML檔案,可以看到解析出來的資料

選擇資料來源的資料表

資料來源就新增成功了,另外可以設定資料來源的讀取方式

在要繫結的項目上,直接選擇到要繫結的欄位就行了

開始執行測試

測試結果

設定測試代理環境

先到官網下載安裝程式

影像檔中包含Controller和Agent兩部份

先安裝Controller

這裡的執行帳號需要有管理員權限,如果沒有網域的話,那可以在其他電腦上建立一組相同的帳號密碼並加入管理群組

Controller設定成功

接下來安裝Agent

以服務啟動Agent

Agent的帳號需可以連接到Controller的管理員權限

Agent設定成功

建立一個Web效能和負載測試專案

調整測試設定

採用本機電腦或測試控器執行測試

測試執行方法改用遠端執行,再管理測試控制器

輸入控制器的位址,就可以看到所有Agent的狀態了