Redis NoSQL數(shù)據(jù)庫(version 3.0)

  • NOSQL類型簡介

    • 鍵值對:會使用到一個哈希表,表中有一個特定的鍵和一個指針指向特定的數(shù)據(jù),如redis,voldemort,oracle bdb
    • 列存儲數(shù)據(jù)庫,應(yīng)對分布式存儲的海量數(shù)據(jù),鍵仍然在,但是指向了多個列,如HBase,Riak
    • 文檔型數(shù)據(jù)庫:數(shù)據(jù)模型是版本化的文檔,半結(jié)構(gòu)化的文檔以特定的格式存儲,如json,文檔型數(shù)據(jù)庫可以看成是鍵值型數(shù)據(jù)的升級版,允許之間嵌套鍵值,而且文檔型數(shù)據(jù)庫比鍵值數(shù)據(jù)庫的查詢效率更高,如CouchDB,MongoDb
    • 圖形數(shù)據(jù)庫,使用靈活的圖形模型,并且能擴展到多個服務(wù)器上,Neo4J,InfoGrid,InfiniteGraph
  • NOSQL特點

    • 數(shù)據(jù)模型簡單
    • 性能較高
    • 不需要高度的數(shù)據(jù)一致性
  • 優(yōu)缺點

    • 優(yōu)點
      • 對數(shù)據(jù)的高并發(fā)讀寫
      • 對海量數(shù)據(jù)的高效率存儲和訪問
      • 對數(shù)據(jù)的高擴展性和高可用性
    • 缺點
      • redis的acid關(guān)系非常簡單,無法做到太復雜的關(guān)系數(shù)據(jù)庫模型
  • 可擴展性和可用性

    • 可擴展性
      • 垂直擴展(容量不夠了加內(nèi)存)
      • 水平擴展(容量不夠了往集群里加機器)
    • 可用性
      • 單節(jié)點掛了,節(jié)點之間迅速切換
    • 可靠性
      • 只要刷盤了,數(shù)據(jù)不丟失
  • redis以key-value形式存儲,data structure service 數(shù)據(jù)結(jié)構(gòu)服務(wù)器,支持各種不同方式的排序,數(shù)據(jù)都是緩存在內(nèi)存中,它也可以周期性的將更新的數(shù)據(jù)寫入到磁盤或者把修改操作寫入追加到文件。redis的數(shù)據(jù)持久化主要是rdb和aof

    • rdb,周期性的將數(shù)據(jù)刷入到磁盤(默認開啟rdb)
    • aof,將更改操作寫入到日志文件,相當于數(shù)據(jù)庫的undo日志,開aof,多線程并發(fā)的去訪問redis集群,redis的寫的性能大大降低,怎么解決呢?
      • 1.多幾個主節(jié)點,分擔寫壓力
      • 2.使用ssdb(寫性能高)寫,用redis讀,技術(shù)的合并
  • redis的三種集群方式

    • 主從模式
      • 主節(jié)點可寫,其他節(jié)點均高并發(fā)可讀,如果主節(jié)點掛了,那么整個redis服務(wù)不可用,主從節(jié)點數(shù)據(jù)完全一致
    • 哨兵模式
      • 主從模式上另加一個哨兵進行監(jiān)控,如果主節(jié)點掛了,哨兵服務(wù)會對從節(jié)點之間進行選舉出一個主節(jié)點 實現(xiàn)高可用,自動切換主從,如果主節(jié)點再次加入進來,成為一個從節(jié)點。也就是說任意時間內(nèi),只有一個主節(jié)點,主從節(jié)點數(shù)據(jù)完全一致
    • 集群模式
      • 多主節(jié)點,并對數(shù)據(jù)進行分布式存儲,主從節(jié)點數(shù)據(jù)不一樣
  • reids和memcache

    • redis多實例化是串行化執(zhí)行,多實例化性能比較高,群狼戰(zhàn)猛虎
    • memcache多實例是并行化執(zhí)行,單節(jié)點性能比較高
  • 簡單安裝

    • 編譯安裝make && make install(請先安裝gcc,如果出現(xiàn)jemalloc/jemalloc.h: No such file or directory,請使用make MALLOC=libc && make install)
    • mkdir -p /usr/local/redis/etc
    • mkdir -p /usr/local/redis/bin
    • cp redis源碼目錄/redis.conf /usr/localredis/etc
    • cp redis源碼目錄/src mkreleasehdr.sh redis-cli redis-server /usr/local/redis/bin
    • 修改/usr/local/reids/etc/redis.conf里 daemonize改為 yes
    • 啟動 /usr/local/redis/bin/redis-server /usr/local/reids/etc/redis.conf
    • netstat -tunpl | grep 6379
    • 停止redis:/usr/local/redis/bin/redis-cli shutdown 或者pkill redis-server,或者直接kill redis 進程號
    • 只要dump.rdb文件不刪,關(guān)閉操作之前的數(shù)據(jù)還存在
  • 基礎(chǔ)數(shù)據(jù)類型

    • String
      • 鍵和值都是字符串
      • set key value 不用加雙引號
      • get key 獲取值
      • 多次設(shè)置同key的value會覆蓋
      • setnx key value 不存在則設(shè)置值
      • del key 刪除鍵值
      • setex key 有效期時間(單位:秒) value,鍵值有效期之后自動失效
      • setrange key 第幾個位置開始替換(索引從0開始) 替換字符串,從索引位開始替換成替換字符串長度的替換字符串
      • mset key1 key1value key2 keyn valuen 多次 設(shè)置值
      • mget key1 key2 keyn 多次獲取值
      • getset key value 返回key的舊值并將該key設(shè)置為新值
      • incr | decr key 對一個值進行自增和遞減
      • incrby | decrby key 步長 對一個值進行步長自增和遞減
      • append key val 給key的value追加val的字符串
      • strlen key 返回key對于的字符串長度
    • Hash
      • 非常常用適合存儲對象,將一個對象類型存儲在hash要比存儲在string類型里占用更小的內(nèi)存空間
      • hset hash_name key value 存一個鍵值對到名為hash_name的Hash里
      • hget hash_name key 從hash_name的hash里取key的value
      • hmget | hmset hash_name key1 key1value key2 keyn valuen 多次 獲取或設(shè)置值
      • hsetnx hash_name key val 不存在則設(shè)置為val值
      • hincrby | hdecrby hash_name 步長 集合的步長遞增和遞減
      • hexists hash_name key 集合里是否存在key,不存在返回0
      • hlen hash_name 集合里的所有鍵的數(shù)量
      • hdel hash_name key 刪除名稱為hash_name 的hash里的key對應(yīng)的鍵值
      • hkeys hash_name 獲取hash里的所有key
      • hvals hash_name 獲取hash里的所有value
      • hgetall hash_name 獲取hash里的所有key,value
    • List
      • 鏈表結(jié)構(gòu),雙端鏈表,既可以成為棧,也可以成為隊列,元素可以重復
      • lpush 從頭部加入元素,先進后出,lpush list_name value
      • rpush 從尾部加入元素,先進先出,rpush list_name value
      • Irange list_name 0 -1 到名為list_name的list里從0開始,取出所有元素,-1為取出所有,即到直到?jīng)]有元素位置
      • linsert list_name before "value" "insert_value" 在value值之前插入insert_value
      • lset list_name 下標 "value" 將指定下標的值替換為value
      • lrem list_name 刪除個數(shù) "value" 從指定下標開始,刪除n個 值為value的元素
      • ltrim list_name 下標 上標 保留從下標到上標的元素
      • lpop list_name 從list的頭部刪除元素,并返回刪除元素
      • rpop list_name 從list的尾部刪除元素,并返回刪除元素
      • rpoplpush list_name_1 list_name_2 value 先從list_name_1中移除元素,再往list_name_2中的頭部添加元素
      • lindex list_name index 返回index處的元素、
      • llen list_name 返回元素的個數(shù)
    • Set
      • 元素不能重復,string類型的無序集合,通過hashtable實現(xiàn),集合我們可以取交集并集和差集
      • sadd set_name value 向set_name的set中添加value元素
      • srem set_name value 移除set_name中的value元素
      • spop set_name 移除并返回集合中的一個隨機元素
      • smembers set_name 查看set里的所有元素
      • sdiff set_name1 set_name2 取倆個集合的差集,那個集合在前面就以那個為標準
      • sdiffstore set_name3 set_name1 set_name2 取set1和set2的差集并存儲到set3
      • sinter key1 [key2] 返回給定所有集合的交集
      • sinterstore set_name3 set_name1 set_name2 取set1和set2的交集并存儲到set3
      • sunion key1 [key2] 返回給定所有集合的并集
      • sunionstore set_name3 set_name1 set_name2 取set1和set2的并集并存儲到set3
      • smove set_name1 set_name2 value 將set_name1中的元素value移動到set_name2中
      • scard set_name 查看集合的元素個數(shù)
      • sismember set_name value 查看value 是否在set中
      • srandmember set_name 隨機返回一個set中的元素
    • ZSet
      • 有序的集合,
      • zadd zset_name n value 向zset中的索引n中添加元素(value)
      • zrange zset_name 0 -1 withscores 列出所有元素,索引從0開始到-1(所有),并顯示索引
      • zrem set_name value 刪除zset中的元素value
      • zincrby set_name 步長,以指定步長去自動遞增或遞減
      • zrangebyscore set_name (1 5 返回所有符合條件 1 < score <= 5 的成員
      • zremrangebyrank key start stop 移除有序集key中,指定排名(rank)區(qū)間內(nèi)的所有成員。下標參數(shù)start和stop都以0為底,0處是分數(shù)最小的那個元素。這些索引也可是負數(shù),表示位移從最高分處開始數(shù)。例如,-1是分數(shù)最高的元素,-2是分數(shù)第二高的,依次類推。
      • zremrangebyscore set_name (start stop 刪除所有符合條件 start< score <= stop 的成員
      • zrank set_name value 如果成員在有序集合存在,返回整數(shù):成員的權(quán)重。如果成員在有序集合不存在或鍵不存在,字符串返回nil。
      • zrevrank set_name value 返回有序集key中成員member的排名,其中有序集成員按score值從大到小排列。排名以0為底,也就是說,score值最大的成員排名為0。
        使用ZRANK命令可以獲得成員按score值遞增(從小到大)排列的排名(順序)。
      • zcard set_name 返回集合里所有元素的個數(shù)
      • zcount set_name (1 5 返回所有符合條件 1 < score <= 5 的成員個數(shù)
  • redis高級命令

    • 所有的鍵: keys * 支持模糊查詢
    • 是否存在指定鍵 exists key
    • expire key time_out 設(shè)置某個key的過期時間,單位為秒,使用ttl key查看剩余時間,-2代表過期
    • persist key 取消過期時間,執(zhí)行之后再執(zhí)行ttl返回-1
    • select 選擇數(shù)據(jù)庫,數(shù)據(jù)庫為0-15(默認共16個庫),默認進入0庫,早期16個庫是為了安全,可以使用8個庫用作備份,看你怎么拆分,或者不同的數(shù)據(jù)類型放到不同的數(shù)據(jù)庫,現(xiàn)在已經(jīng)不考慮,redis已經(jīng)有集群實現(xiàn)
      +move [key] [數(shù)據(jù)庫下標] 移動數(shù)據(jù)到其他庫
    • randomkey隨機返回數(shù)據(jù)庫里的一個key
    • rename key newkey 重命名key
    • echo 打印命令
    • dbsize 查看數(shù)據(jù)庫的key數(shù)量
    • info 獲取數(shù)據(jù)庫信息
    • config get key 實時傳儲收到的請求,返回相關(guān)的配置信息,
    • config get * 返回所有配置
    • flushdb 清空當前數(shù)據(jù)庫,
    • flushall 清空所有數(shù)據(jù)庫
  • 安全性
    requirepass password 設(shè)置密碼后能登陸redis,但是訪問不了任何數(shù)據(jù),登陸redis后如果要使用密碼,使用auth password,才能正常操作數(shù)據(jù),或者使用redis-cli加上參數(shù)-a password 登陸

  • redis主從復制

    • 概念
      • 一個Master可以擁有多個slave
      • 多個slave可以連接同一個master,還可以連接其他slave,子節(jié)點的子節(jié)點
      • 主從復制不會阻塞master,在同步數(shù)據(jù)時,master可以繼續(xù)處理client請求
      • 提供系統(tǒng)的伸縮性
    • 主從復制過程
      • slave 與master建立連接之后,發(fā)送sync同步命令
      • master會開啟一個后臺進程,將數(shù)據(jù)庫快照保存到文件中,同時master主進程會開始收集新的寫命令并緩存
      • 后臺完成保存后,將文件發(fā)送給slave
      • slave將文件保存到磁盤上
    • 主從復制配置
      • 如果機器架構(gòu)一致,可以clone master上的redis
      • 修改從服務(wù)器的redis配置文件/usr/local/redis/etc/redis.conf
        • slaveof <masterip> <mastport>
        • 如果主服務(wù)器有密碼:masterauth <master-password>
      • 啟動master和slave
      • 使用info查看role角色即可知道誰是主服務(wù)或從服務(wù)
      • slave是不能執(zhí)行寫操作的(set 操作),他是readonly的,slave的數(shù)據(jù)和master一致,在應(yīng)用中,你只要創(chuàng)建一個master redis連接,寫在master,讀操作會自動負載到從節(jié)點
      • 主節(jié)點掛了,整個集群不可用
  • redis 哨兵模式

    • 功能有倆點
      • 監(jiān)控主數(shù)據(jù)庫和從數(shù)據(jù)庫是否正常運行
      • 主數(shù)據(jù)庫出現(xiàn)故障時,自動選舉一個從數(shù)據(jù)庫為主數(shù)據(jù)庫,實現(xiàn)自動切換
      • 實現(xiàn)高可用性,沒有單點問題,掛了就掛了,可以自動切換
    • 實現(xiàn)步驟
      • copy redis源碼中的sentinel.conf 到一臺從數(shù)據(jù)庫服務(wù)器的/usr/local/redis/etc中
      • 修改sentinel.conf
        • sentinel monitor master_name ip port n 設(shè)置master的名稱,ip,端口,投票選舉次數(shù),n票通過之后選舉為主節(jié)點
        • sentinel down-after-milliseconds master_name 5000 默認是1s檢測一次,這里配置超時5000ms為宕機
        • sentinel failover-timeout master_name 900000
        • sentinel parallel-syncs master_name n 從節(jié)點數(shù)量
        • sentinel can-failover master_name yes
      • 啟動sentinel哨兵 /usr/local/redis/bin/redis-server /usr/local/redis/etc/sentinel.conf --sentinel &
      • 查看哨兵相關(guān)信息 /usr/local/redis/bin/redis-cli -h sentinel_ip -p sentinel_port info Sentinel
      • 哨兵服務(wù)可以放到主或從中,或者一臺單獨的機器,或者多個機器,避免單點故障
      • 可以通過redis-cli shutdown將主節(jié)點down掉,再查看哨兵相關(guān)信息,可以查看到主節(jié)點已近切換了
      • 將down掉的主節(jié)點重新啟動,連接redis-cli,執(zhí)行info命令,可以看到角色已經(jīng)變成了slave
  • redis的簡單事務(wù) (一般不使用)

    • 使用multi 命令打開事務(wù)
    • 執(zhí)行crud操作
    • exec命令執(zhí)行,存儲到redis
    • discard 命令回滾
    • 注意reids事務(wù)里的操作如果出錯了,并不會自動回滾
  • 持久化機制

    • 默認是快照方式
      • 將內(nèi)存中的數(shù)據(jù)以快照的方式寫入到二進制文件中,默認為dump.rdb,可以通過配置設(shè)置自動做快照持久化的方式,我們可以配置redis在n秒內(nèi)如果超過m個key被修改就自動做快照
        • 快照設(shè)置
        • save 900 1 900秒內(nèi)如果有超過1個key被修改,則發(fā)起快照保存
        • save 300 10 300秒內(nèi)如果有超過10個key被修改,則發(fā)起快照保存
    • append-only file (aof)
      • 由于快照方式是在一定時間間隔之后做一次,所以有可能redis意外down掉之后,有可能會丟失一部分數(shù)據(jù),aof方式有點像oracle 數(shù)據(jù)庫的undo日志,aof比快照方式有更好的持久化性,在使用aof的時候,redis會將每一次寫操作(除了查詢,其他有更改數(shù)據(jù)的操作)都通過write函數(shù)追加到命令中,當redis重新啟動的時候會重新執(zhí)行aof文件中的寫命令重建數(shù)據(jù)庫內(nèi)容,appendonly.aof,aof并不是立即寫在硬盤上,可以通過配置文件修改強制寫到硬盤中
      • aof設(shè)置(生產(chǎn)環(huán)境推薦使用)
        • appendonly yes //啟動aof持久化方式有三種方式
        • # appendfsync always//收到寫命令就立即寫入磁盤,效率最慢,但是保證完全的持久化(生產(chǎn)使用)
        • # appendfsync everysec //每秒鐘寫入磁盤一次
        • # appendfsync no //完全依賴os,性能最好,持久化沒保證
  • redis 發(fā)布與訂閱信息

    • redis提供了簡單的發(fā)布訂閱功能
    • 使用subscribe [頻道] 進行訂閱監(jiān)聽
    • 使用publish [頻道] [發(fā)布內(nèi)容] 進行發(fā)布消息廣播
  • redis與java的使用

    • 在jedis的jar中,有Jedis對象,
    • Jedis對象
          import java.util.HashMap;
          import java.util.Iterator;
          import java.util.List;
          import java.util.Map;
          
          import org.junit.Test;
          
          import redis.clients.jedis.Jedis;
          
          public class testRedis {
          
          private static Jedis jedis = new Jedis("192.168.1.101",6379);
          
          /**
           * @param args
           */
          @Test
          public void test() {
              // TODO Auto-generated method stub
          //      jedis.set("sex","man");
          //      System.out.println(jedis);
          //      
          //      List<String> list = jedis.mget("name","age","sex");
          //        for (Iterator iterator = list.iterator(); iterator.hasNext();) {
          //          String string = (String) iterator.next();
          //          System.out.println(string);
          //      }
          //        
          //        Map<String, String> user = new HashMap<String, String>();
          //        user.put("name","huangyuxuan");
          //        user.put("age", "0.5");
          //        user.put("sex","男");
          //        jedis.hmset("user",user);
          
              //
          //        List<String> rsmap = jedis.hmget("user", "name", "age","sex");
          //        System.out.println(rsmap);  
              //
          //        jedis.hdel("user","age");
          //        System.out.println(jedis.hmget("user", "age")); //因為刪除了,所以返回的是null  
          //        System.out.println(jedis.hlen("user")); //返回key為user的鍵中存放的值的個數(shù)2 
          //        System.out.println(jedis.exists("user"));//是否存在key為user的記錄 返回true  
          //        System.out.println(jedis.hkeys("user"));//返回map對象中的所有key  
          //        System.out.println(jedis.hvals("user"));//返回map對象中的所有value 
              //
              //testStr();
              //testList();
              testSet();
          
          
          //        Iterator<String> iter=jedis.hkeys("user").iterator();  
          //        while (iter.hasNext()){  
          //            String key = iter.next();  
          //            System.out.println(key+":"+jedis.hmget("user",key));  
          //        }  
          }
          
          public static void testStr(){
              //-----添加數(shù)據(jù)----------  
              jedis.set("name","bhz");//向key-->name中放入了value-->xinxin  
              System.out.println(jedis.get("name"));//執(zhí)行結(jié)果:xinxin  
          
              jedis.append("name", " is my lover"); //拼接
              System.out.println(jedis.get("name"));
          
              jedis.del("name");  //刪除某個鍵
              System.out.println(jedis.get("name"));
              //設(shè)置多個鍵值對
              jedis.mset("name","bhz","age","27","qq","174754613");
              jedis.incr("age"); //進行加1操作
              System.out.println(jedis.get("name") + "-" + jedis.get("age") + "-" + jedis.get("qq"));
          
          }
          
          public static void testList(){
              //開始前,先移除所有的內(nèi)容  
              jedis.del("java framework");
              System.out.println(jedis.lrange("java framework",0,-1));
              //先向key java framework中存放三條數(shù)據(jù)  
              jedis.lpush("java framework","spring");
              jedis.lpush("java framework","struts");
              jedis.lpush("java framework","hibernate");
              //再取出所有數(shù)據(jù)jedis.lrange是按范圍取出,  
              // 第一個是key,第二個是起始位置,第三個是結(jié)束位置,jedis.llen獲取長度 -1表示取得所有  
              System.out.println(jedis.lrange("java framework",0,-1));
          
              jedis.del("java framework");
              jedis.rpush("java framework","spring");
              jedis.rpush("java framework","struts");
              jedis.rpush("java framework","hibernate");
              System.out.println(jedis.lrange("java framework",0,-1));
          }
          
          
          public static void testSet(){
              //添加  
              jedis.sadd("user1","liuling");
              jedis.sadd("user1","xinxin");
              jedis.sadd("user1","ling");
              jedis.sadd("user1","zhangxinxin");
              jedis.sadd("user1","who");
              //移除noname  
              jedis.srem("user1","who");
              System.out.println(jedis.smembers("user1"));//獲取所有加入的value  
              System.out.println(jedis.sismember("user1", "who"));//判斷 who 是否是user集合的元素  
              System.out.println(jedis.srandmember("user1"));
              System.out.println(jedis.scard("user1"));//返回集合的元素個數(shù)  
          }
          
          }
      
  • redis 集群搭建(哨兵模式的問題是在選舉程序執(zhí)行時,redis不可寫)

    • redis3.0開始支持集群容錯功能,集群至少要三個master,3個slave
    • 此處是同一臺機器開6個redis,模擬集群
    • 創(chuàng)建文件夾:mkdir -p /usr/local/redis-cluster
    • cd /usr/local/redis-cluster
    • mkdir 7001,mkdir 7002,mkdir 7003,mkdir 7004,mkdir 7005,mkdir 7006,
    • 拷貝redis配置文件到7001到7006文件夾,修改配置:
      • daemonize yes
      • port 700*
      • bind 當前機器ip
      • dir /usr/local/redis-cluster/700* 必須指定,分布式的數(shù)據(jù)每臺機器存的數(shù)據(jù)都不一樣的
      • cluster-enabled yes
      • cluster-config-file nodes-700*.conf
      • cluster-node-timeout 5000
      • appendonly yes
    • 由于redis集群需要使用ruby命令,所以要安裝ruby,yum install ruby
    • yum install rubygems
    • gem install redis 安裝redis和ruby的接口
    • 啟動redis實例,/usr/local/redis/bin/redis-server /usr/local/redis-cluster/700*/redis.conf
    • ps -ef | grep redis 看6個redis是否啟動成功
    • 切換到redis源碼目錄,拷貝redis源碼目錄下的redis-trib.rb到/usr/local/redis/bin/,cp redis-trib.rb /usr/local/redis/bin/
    • /usr/local/redis/bin/redis-trib.rb create --replicas 1 ip:7001 ip:7002 ip:7003 ip:7004 ip:7005 ip:7006
    • redis-trib.rb的更多信息請執(zhí)行/usr/local/redis/bin/redis-trib.rb --help ,--replicas參數(shù)后面跟的1是指主節(jié)點數(shù)/從節(jié)點數(shù)的比值,比如6個master,12個slave,這個值就應(yīng)該是0.5,假設(shè)有m個節(jié)點,比值為k,a為master的個數(shù),b為slave的個數(shù),即a/b = k, a+b= m,所以a=bk,bk+b=m,(k+1)b=m,所以b=m/(k+1),a=m-b,則命令行參數(shù)中的前a個為master,后m-a個為slave,slave依據(jù)比值,比如0.5,那么就先給第一個master分配倆臺slave,剩余的分配給下面的master,集群中每個master都有slots(槽),slave沒有,說明不可寫
    • 至此集群環(huán)境已經(jīng)搭建好了,如何驗證?連接任意一客戶端:/usr/local/redis/bin/redis-cli -c -h ip -p port (-c 代表集群模式,指定ip和端口),驗證命令:cluster info (查看集群信息) cluster nodes(查看節(jié)點列表)
    • 數(shù)據(jù)操作驗證,往redis集群中的一個節(jié)點放一條數(shù)據(jù),數(shù)據(jù)放的地方不一定redis-cli是登陸的機器,具體存放在哪,在你set的時候,會有信息提示被定向到哪了,讀數(shù)據(jù)會自動定向到所在的節(jié)點,但是你在執(zhí)行flushall的時候要去每個主節(jié)點執(zhí)行該命令,集群中所有的數(shù)據(jù)才會刪除
    • 關(guān)閉集群需要逐個進行關(guān)閉,使用命令:/usr/local/redis/bin/redis-cli -c -h ip -p port shutdown ,如果要重新啟動集群,將redis逐個啟動就好
    • 如果出現(xiàn)集群無法啟動時,刪除cluster-config-file文件(集群配置文件),注意redis.conf,.rdb,.aof不能刪,再次重新啟動每一個redis 服務(wù),重新構(gòu)建集群環(huán)境
    • 更多參考redis-trib.rb,推薦博客
  • redis-trib 命令詳解

    • /usr/local/redis/bin/redis-trib.rb create --replicas 1 ip:port ip:port ... 命令會創(chuàng)建集群信息,并將集群信息存儲到cluster-config-file
    • 關(guān)閉集群需要逐個進行關(guān)閉,使用命令:/usr/local/redis/bin/redis-cli -c -h ip -p port shutdown ,如果要重新啟動集群,將redis逐個啟動就好
    • 查看集群節(jié)點信息:/usr/local/redis/bin/redis-cli cluster nodes
    • 查看集群信息:/usr/local/redis/bin/redis-cli cluster info
    • redis-trib 添加節(jié)點
      • 我們新建倆個服務(wù),按照之前搭建的集群方式新增倆個節(jié)點:(一主一從 master、slave) Master:7007,Slave:7008
      • cd /usr/local/redis-cluster
      • mkdir 7007,mkdir 7008
      • 拷貝redis配置文件到7007到7008文件夾,修改配置:
      • daemonize yes
      • port 700*
      • bind 當前機器ip
      • dir /usr/local/redis-cluster/700* 必須指定,分布式的數(shù)據(jù)每臺機器存的數(shù)據(jù)都不一樣的
      • cluster-enabled yes
      • cluster-config-file nodes-700*.conf
      • cluster-node-timeout 5000
      • appendonly yes
      • 啟動7007和7008,/usr/local/redis/bin/redis-server /usr/local/redis-cluster/700*(7和8)/redis.conf
      • redis-trib 命令:
        • create:創(chuàng)建一個集群環(huán)境host1:port1 ... hostN:portN(集群中的主從節(jié)點比例)
        • call:可以執(zhí)行redis命令
        • add-node:將一個節(jié)點添加到集群里,第一個參數(shù)為新節(jié)點的ip:port,第二個參數(shù)為集群中任意一個已經(jīng)存在的節(jié)點的ip:port
        • del-node:移除一個節(jié)點
        • reshard:重新分片
        • check:檢查集群狀態(tài)
      • 新增一個主節(jié)點7007(master)
        • /usr/local/redis3.0/src/redis-trib.rb add-node 192.168.1.171:7007(要加的master的ip:port) 192.168.1.171:7001(集群內(nèi)已知的任意一master的ip:port)
        • 查看集群信息:/usr/local/redis/bin/redis-cli cluster nodes,記錄下新的節(jié)點的node id
        • 新增的節(jié)點不會有任何數(shù)據(jù),因為它沒有分配任何的slots,槽,需要手工分配
        • 分配槽,/usr/local/redis3.0/src/redis-trib.rb reshard 192.168.1.171:7001(集群內(nèi)的任意一master),命令執(zhí)行時會詢問要分配多少個槽到新的master:How many slots do you want to move (from 1 to 16384)?可以自己設(shè)置,比如200,或者更多,接下來會詢問What is the receiving node ID?,輸入上個命令記錄下的新節(jié)點的node id,下面會要求輸入source node,可以輸入all,意思是從所有的主節(jié)點中抽取相應(yīng)的槽數(shù)到指定的新節(jié)點中,Do you want to proceed with the proposed reshard plan (yes/no)?直接輸入yes,執(zhí)行分片計劃
        • 查看集群信息:/usr/local/redis/bin/redis-cli cluster nodes,可以看見新的master已經(jīng)有槽數(shù)了
      • 添加從節(jié)點(7008)
        • /usr/local/redis3.0/src/redis-trib.rb add-node 192.168.1.171:7008(要加的slave) 192.168.1.171:7001(集群內(nèi)的任意一master)
        • 查看集群信息:/usr/local/redis/bin/redis-cli cluster nodes,記錄下7008要slave的節(jié)點的node id,即7008的master 節(jié)點(7007)的節(jié)點id,另外還可以看到這還是一個master,沒有分配任何的槽,
        • 主節(jié)點轉(zhuǎn)換為從節(jié)點:
            首先需要登錄新加的7008節(jié)點的客戶端,然后使用集群命令進行操作,把當前的
          7008(slave)節(jié)點指定到一個主節(jié)點下(這里使用之前創(chuàng)建的7007主節(jié)點)
          
          [root@micocube ~]# /usr/local/redis/bin/redis-cli -c -h 192.168.1.171 -p 7008
          192.168.1.171:7008> cluster replicate master(7007)節(jié)點id
          192.168.1.171:7008> OK(提示OK則操作成功)
          
        • 查看集群信息:/usr/local/redis/bin/redis-cli cluster nodes,可以看到7008已經(jīng)變成slave了,我們可以對集群進行操作,來驗證下是否可以進行讀寫(當然可以)。
    • redis-trib 刪除節(jié)點
      • 移除從節(jié)點
        • /usr/local/redis3.0/src/redis-trib.rb
          del-node 192.168.1.171:7008 node_id(7008的節(jié)點id),執(zhí)行命令之后,7008會從集群中移除,7008的服務(wù)也會被銷毀,ps -ef | grep redis是看不到7008的redis的
      • 移除主節(jié)點
        • 主節(jié)點稍微麻煩一點,因為我們給它分配了slots(槽),所以我們這里必須先把7007里的slot槽放入到其他的可用主節(jié)點中去,然后再進行移除節(jié)點操作才行,不然會出現(xiàn)數(shù)據(jù)丟失問題.
        • 刪除7007(master)節(jié)點之前,我們需要先把其全部的數(shù)據(jù)(slot槽)移動到其他節(jié)點上去(目前只能把master的數(shù)據(jù)遷移到一個節(jié)點上,暫時做不了平均分配功能),/usr/local/redis3.0/src/redis-trib.rb reshard 192.168.1.171:7007輸出如下
        [root@micocube 7001]# /usr/local/redis3.0/src/redis-trib.rb reshard 192.168.1.171:7007
        
        >>> Performing Cluster Check (using node 192.168.1.171:7007)
        M: 382634a4025778c040b7213453fd42a709f79e28 192.168.1.171:7007
           slots:0-65,5461-5527,10923-10988 (199 slots)[注意這里,7007只有199個槽] master
           0 additional replica(s)
        S: fa299e41c173fa807ba04684c2f5e5e185d5f7d0 192.168.1.171:7006
           slots: (0 slots) slave
           replicates 83df08875c7707878756364039df0a4c8658f272
        S: a69b98937844c6050ee5885266ccccb185a3f36a 192.168.1.171:7004
           slots: (0 slots) slave
           replicates 614d0def75663f2620b6402a017014b57c912dad
        M: 614d0def75663f2620b6402a017014b57c912dad 192.168.1.171:7001
           slots:66-5460 (5395 slots) master
           1 additional replica(s)
        M: 8aac82b63d42a1989528cd3906579863a5774e77 192.168.1.171:7002
           slots:5528-10922 (5395 slots) master
           1 additional replica(s)
        S: adb99506ddccad332e09258565f2e5f4f456a150 192.168.1.171:7005
           slots: (0 slots) slave
           replicates 8aac82b63d42a1989528cd3906579863a5774e77
        M: 83df08875c7707878756364039df0a4c8658f272 192.168.1.171:7003
           slots:10989-16383 (5395 slots) master
           1 additional replica(s)
        [OK] All nodes agree about slots configuration.
        >>> Check for open slots...
        >>> Check slots coverage...
        [OK] All 16384 slots covered.
        How many slots do you want to move (from 1 to 16384)? 199
        (注釋:這里不會是正好200個槽)
        What is the receiving node ID? 614d0def75663f2620b6402a017014b57c912dad
        (注釋:這里是需要把數(shù)據(jù)移動到哪?7001的主節(jié)點id)
        Please enter all the source node IDs.
          Type 'all' to use all the nodes as source nodes for the hash slots.
          Type 'done' once you entered all the source nodes IDs.
        Source node #1:382634a4025778c040b7213453fd42a709f79e28
        (注釋:這里是需要數(shù)據(jù)源,也就是我們的7007節(jié)點id)
        Source node #2:done
        (注釋:這里直接輸入done 開始生成遷移計劃)
        
        Ready to move 199 slots.
          Source nodes:
            M: 382634a4025778c040b7213453fd42a709f79e28 192.168.1.171:7007
           slots:0-65,5461-5527,10923-10988 (199 slots) master
           0 additional replica(s)
          Destination node:
            M: 614d0def75663f2620b6402a017014b57c912dad 192.168.1.171:7001
           slots:66-5460 (5395 slots) master
           1 additional replica(s)
          Resharding plan:
        Moving slot 0 from 382634a4025778c040b7213453fd42a709f79e28
        ...
        Do you want to proceed with the proposed reshard plan (yes/no)? Yes
        (注釋:這里輸入yes開始遷移)
        Moving slot 0 from 192.168.1.171:7007 to 192.168.1.171:7001: 
        ...
        
        • 到此為止我們已經(jīng)成功的把7007主節(jié)點的數(shù)據(jù)遷移到7001上去了,我們可以看一下現(xiàn)在的集群狀態(tài)如下圖,你會發(fā)現(xiàn)7007下面已經(jīng)沒有任何數(shù)據(jù)(slot)槽了,證明遷移成功!
        • 最后我們直接使用del-node命令刪除7007主節(jié)點即可。
          [root@micocube 7001]# /usr/local/redis3.0/src/redis-trib.rb del-node
          192.168.1.171:7007 382634a4025778c040b7213453fd42a709f79e28(7007的node id)
  • java 操作redis集群
      import java.util.HashSet;
      import java.util.Set;
    
      import redis.clients.jedis.HostAndPort;
      import redis.clients.jedis.JedisCluster;
      import redis.clients.jedis.JedisPoolConfig;
    
      public class TestClusterRedis {
    
          public static void main(String[] args) {
              
              Set<HostAndPort> jedisClusterNode = new HashSet<HostAndPort>();
                          //下面是集群中各個節(jié)點的ip和端口,如果連不上關(guān)閉redis服務(wù)器的防火墻
              jedisClusterNode.add(new HostAndPort("192.168.1.171", 7001));
              jedisClusterNode.add(new HostAndPort("192.168.1.171", 7002));
              jedisClusterNode.add(new HostAndPort("192.168.1.171", 7003));
              jedisClusterNode.add(new HostAndPort("192.168.1.171", 7004));
              jedisClusterNode.add(new HostAndPort("192.168.1.171", 7005));
              jedisClusterNode.add(new HostAndPort("192.168.1.171", 7006));
              //GenericObjectPoolConfig goConfig = new GenericObjectPoolConfig();
              //JedisCluster jc = new JedisCluster(jedisClusterNode,2000,100, goConfig);
              JedisPoolConfig cfg = new JedisPoolConfig();
              cfg.setMaxTotal(100);
              cfg.setMaxIdle(20);
              cfg.setMaxWaitMillis(-1);
              cfg.setTestOnBorrow(true); 
              JedisCluster jc = new JedisCluster(jedisClusterNode,6000,1000,cfg);     
              
              System.out.println(jc.set("age","20"));
              System.out.println(jc.set("sex","男"));
              System.out.println(jc.get("name"));
              System.out.println(jc.get("name"));
              System.out.println(jc.get("name"));
              System.out.println(jc.get("name"));
              System.out.println(jc.get("name"));
              System.out.println(jc.get("name"));
              System.out.println(jc.get("name"));
              System.out.println(jc.get("name"));
              System.out.println(jc.get("age"));
              System.out.println(jc.get("sex"));
              jc.close();
              
              
          }
          
      }
    
  • redis與spring的整合(applicationContext-cluster.xml)
      <?xml version="1.0" encoding="UTF-8"?>
      <beans xmlns="http://www.springframework.org/schema/beans"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
          xmlns:context="http://www.springframework.org/schema/context"
          xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
          xmlns:aop="http://www.springframework.org/schema/aop"
          xsi:schemaLocation="  
                  http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd  
                  http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    
          <context:property-placeholder location="classpath:redis.properties" />
          <context:component-scan base-package="com.x.redis.dao">
          </context:component-scan>
          <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
              <property name="maxIdle" value="${redis.maxIdle}" />
              <property name="maxTotal" value="${redis.maxActive}" />
              <property name="maxWaitMillis" value="${redis.maxWait}" />
              <property name="testOnBorrow" value="${redis.testOnBorrow}" />
          </bean>
    
          <bean id="hostport1" class="redis.clients.jedis.HostAndPort">
              <constructor-arg name="host" value="10.16.68.92" />
              <constructor-arg name="port" value="7770" />
          </bean>
          <bean id="hostport2" class="redis.clients.jedis.HostAndPort">
              <constructor-arg name="host" value="10.16.68.92" />
              <constructor-arg name="port" value="7771" />
          </bean>
          <bean id="hostport3" class="redis.clients.jedis.HostAndPort">
              <constructor-arg name="host" value="10.16.68.92" />
              <constructor-arg name="port" value="7772" />
          </bean>
          <bean id="hostport4" class="redis.clients.jedis.HostAndPort">
              <constructor-arg name="host" value="10.16.68.92" />
              <constructor-arg name="port" value="7773" />
          </bean>
          <bean id="hostport5" class="redis.clients.jedis.HostAndPort">
              <constructor-arg name="host" value="10.16.68.92" />
              <constructor-arg name="port" value="7774" />
          </bean>
          <bean id="hostport6" class="redis.clients.jedis.HostAndPort">
              <constructor-arg name="host" value="10.16.68.92" />
              <constructor-arg name="port" value="7775" />
          </bean>
    
          <bean id="redisCluster" class="redis.clients.jedis.JedisCluster">
              <constructor-arg name="nodes">
                  <set>
                      <ref bean="hostport1" />
                      <ref bean="hostport2" />
                      <ref bean="hostport3" />
                      <ref bean="hostport4" />
                      <ref bean="hostport5" />
                      <ref bean="hostport6" />
                  </set>
              </constructor-arg>
              <constructor-arg name="timeout" value="6000" />
              <constructor-arg name="poolConfig">
                  <ref bean="jedisPoolConfig" />
              </constructor-arg>
          </bean>
      </beans>
    
  • Redis配置文件詳解
      # Redis 配置文件
    
      # 當配置中需要配置內(nèi)存大小時,可以使用 1k, 5GB, 4M 等類似的格式,其轉(zhuǎn)換方式如下(不區(qū)分大小寫)
      #
      # 1k =>
      1000 bytes
      # 1kb => 1024 bytes
      # 1m => 1000000 bytes
      # 1mb =>
      1024*1024 bytes
      # 1g => 1000000000 bytes
      # 1gb => 1024*1024*1024
      bytes
      #
      # 內(nèi)存配置大小寫是一樣的.比如 1gb 1Gb 1GB 1gB
    
      # daemonize no 默認情況下,redis不是在后臺運行的,如果需要在后臺運行,把該項的值更改為yes
      daemonize
      yes
    
      # 當redis在后臺運行的時候,Redis默認會把pid文件放在/var/run/redis.pid,你可以配置到其他地址。
      #
      當運行多個redis服務(wù)時,需要指定不同的pid文件和端口
      pidfile /var/run/redis.pid
    
      # 指定redis運行的端口,默認是6379
      port 6379
    
      # 指定redis只接收來自于該IP地址的請求,如果不進行設(shè)置,那么將處理所有請求,
      # 在生產(chǎn)環(huán)境中最好設(shè)置該項
      # bind
      127.0.0.1
    
      # Specify the path for the unix socket that will be used to listen for
      #
      incoming connections. There is no default, so Redis will not listen
      # on a
      unix socket when not specified.
      #
      # unixsocket /tmp/redis.sock
      #
      unixsocketperm 755
    
      # 設(shè)置客戶端連接時的超時時間,單位為秒。當客戶端在這段時間內(nèi)沒有發(fā)出任何指令,那么關(guān)閉該連接
      # 0是關(guān)閉此設(shè)置
      timeout
      0
    
      # 指定日志記錄級別
      # Redis總共支持四個級別:debug、verbose、notice、warning,默認為verbose
      #
      debug  記錄很多信息,用于開發(fā)和測試
      # varbose 有用的信息,不像debug會記錄那么多
      #
      notice 普通的verbose,常用于生產(chǎn)環(huán)境
      # warning 只有非常重要或者嚴重的信息會記錄到日志
      loglevel
      debug
    
      # 配置log文件地址
      # 默認值為stdout,標準輸出,若后臺模式會輸出到/dev/null
      #logfile
      stdout
      logfile /var/log/redis/redis.log
    
      # To enable logging to the system logger, just set 'syslog-enabled' to
      yes,
      # and optionally update the other syslog parameters to suit your
      needs.
      # syslog-enabled no
    
      # Specify the syslog identity.
      # syslog-ident redis
    
      # Specify the syslog facility.  Must be USER or between LOCAL0-LOCAL7.
      #
      syslog-facility local0
    
      # 可用數(shù)據(jù)庫數(shù)
      # 默認值為16,默認數(shù)據(jù)庫為0,數(shù)據(jù)庫范圍在0-(database-1)之間
      databases 16
    
      ################################ 快照  
      #################################
      #
      # 保存數(shù)據(jù)到磁盤,格式如下:
      #
      #   save
      <seconds> <changes>
      #
      #   
      指出在多長時間內(nèi),有多少次更新操作,就將數(shù)據(jù)同步到數(shù)據(jù)文件rdb。
      #   相當于條件觸發(fā)抓取快照,這個可以多個條件配合
      #   
      #   
      比如默認配置文件中的設(shè)置,就設(shè)置了三個條件
      #
      #   save 900 1  900秒內(nèi)至少有1個key被改變
      #   save 300
      10  300秒內(nèi)至少有300個key被改變
      #   save 60 10000  60秒內(nèi)至少有10000個key被改變
    
      save 900 1
      save 300 10
      save 60 10000
    
      # 存儲至本地數(shù)據(jù)庫時(持久化到rdb文件)是否壓縮數(shù)據(jù),默認為yes
      rdbcompression yes
    
      # 本地持久化數(shù)據(jù)庫文件名,默認值為dump.rdb
      dbfilename dump.rdb
    
      # 工作目錄
      #
      # 數(shù)據(jù)庫鏡像備份的文件放置的路徑。
      #
      這里的路徑跟文件名要分開配置是因為redis在進行備份時,先會將當前數(shù)據(jù)庫的狀態(tài)寫入到一個臨時文件中,等備份完成時,
      #
      再把該該臨時文件替換為上面所指定的文件,而這里的臨時文件和上面所配置的備份文件都會放在這個指定的路徑當中。
      #
      #
      AOF文件也會存放在這個目錄下面
      #
      # 注意這里必須制定一個目錄而不是文件
      dir ./
    
      ################################# 復制
      #################################
    
      # 主從復制. 設(shè)置該數(shù)據(jù)庫為其他數(shù)據(jù)庫的從數(shù)據(jù)庫.
      #
      設(shè)置當本機為slav服務(wù)時,設(shè)置master服務(wù)的IP地址及端口,在Redis啟動時,它會自動從master進行數(shù)據(jù)同步
      #
      # slaveof
      <masterip> <masterport>
    
      # 當master服務(wù)設(shè)置了密碼保護時(用requirepass制定的密碼)
      # slav服務(wù)連接master的密碼
      #
      #
      masterauth <master-password>
    
    
      # 當從庫同主機失去連接或者復制正在進行,從機庫有兩種運行方式:
      #
      # 1)
      如果slave-serve-stale-data設(shè)置為yes(默認設(shè)置),從庫會繼續(xù)相應(yīng)客戶端的請求
      #
      # 2)
      如果slave-serve-stale-data是指為no,出去INFO和SLAVOF命令之外的任何請求都會返回一個
      #    錯誤"SYNC with
      master in progress"
      #
      slave-serve-stale-data yes
    
      # 從庫會按照一個時間間隔向主庫發(fā)送PINGs.可以通過repl-ping-slave-period設(shè)置這個時間間隔,默認是10秒
      #
      #
      repl-ping-slave-period 10
    
      # repl-timeout 設(shè)置主庫批量數(shù)據(jù)傳輸時間或者ping回復時間間隔,默認值是60秒
      #
      一定要確保repl-timeout大于repl-ping-slave-period
      # repl-timeout 60
    
      ################################## 安全
      ###################################
    
      # 設(shè)置客戶端連接后進行任何其他指定前需要使用的密碼。
      #
      警告:因為redis速度相當快,所以在一臺比較好的服務(wù)器下,一個外部的用戶可以在一秒鐘進行150K次的密碼嘗試,這意味著你需要指定非常非常強大的密碼來防止暴力破解
      #
      #
      requirepass foobared
    
      # 命令重命名.
      #
      # 在一個共享環(huán)境下可以重命名相對危險的命令。比如把CONFIG重名為一個不容易猜測的字符。
      #
      #
      舉例:
      #
      # rename-command CONFIG
      b840fc02d524045429941cc15f59e41cb7be6c52
      #
      #
      如果想刪除一個命令,直接把它重命名為一個空字符""即可,如下:
      #
      # rename-command CONFIG ""
    
      ################################### 約束
      ####################################
    
      # 設(shè)置同一時間最大客戶端連接數(shù),默認無限制,Redis可以同時打開的客戶端連接數(shù)為Redis進程可以打開的最大文件描述符數(shù),
      # 如果設(shè)置
      maxclients 0,表示不作限制。
      # 當客戶端連接數(shù)到達限制時,Redis會關(guān)閉新的連接并向客戶端返回max number of clients
      reached錯誤信息
      #
      # maxclients 128
    
      # 指定Redis最大內(nèi)存限制,Redis在啟動時會把數(shù)據(jù)加載到內(nèi)存中,達到最大內(nèi)存后,Redis會先嘗試清除已到期或即將到期的Key
      #
      Redis同時也會移除空的list對象
      #
      #
      當此方法處理后,仍然到達最大內(nèi)存設(shè)置,將無法再進行寫入操作,但仍然可以進行讀取操作
      #
      #
      注意:Redis新的vm機制,會把Key存放內(nèi)存,Value會存放在swap區(qū)
      #
      #
      maxmemory的設(shè)置比較適合于把redis當作于類似memcached的緩存來使用,而不適合當做一個真實的DB。
      #
      當把Redis當做一個真實的數(shù)據(jù)庫使用的時候,內(nèi)存使用將是一個很大的開銷
      # maxmemory <bytes>
    
      # 當內(nèi)存達到最大值的時候Redis會選擇刪除哪些數(shù)據(jù)?有五種方式可供選擇
      #
      # volatile-lru ->
      利用LRU算法移除設(shè)置過過期時間的key (LRU:最近使用 Least Recently Used )
      # allkeys-lru ->
      利用LRU算法移除任何key
      # volatile-random -> 移除設(shè)置過過期時間的隨機key
      #
      allkeys->random -> remove a random key, any key
      # volatile-ttl ->
      移除即將過期的key(minor TTL)
      # noeviction -> 不移除任何可以,只是返回一個寫錯誤
      #
      #
      注意:對于上面的策略,如果沒有合適的key可以移除,當寫的時候Redis會返回一個錯誤
      #
      #       寫命令包括: set setnx
      setex append
      #       incr decr rpush lpush rpushx lpushx linsert lset
      rpoplpush sadd
      #       sinter sinterstore sunion sunionstore sdiff sdiffstore
      zadd zincrby
      #       zunionstore zinterstore hset hsetnx hmset hincrby incrby
      decrby
      #       getset mset msetnx exec sort
      #
      # 默認是:
      #
      #
      maxmemory-policy volatile-lru
    
      # LRU 和 minimal TTL 算法都不是精準的算法,但是相對精確的算法(為了節(jié)省內(nèi)存),隨意你可以選擇樣本大小進行檢測。
      #
      Redis默認的灰選擇3個樣本進行檢測,你可以通過maxmemory-samples進行設(shè)置
      #
      # maxmemory-samples
      3
    
      ############################## AOF ###############################
    
    
      #
      默認情況下,redis會在后臺異步的把數(shù)據(jù)庫鏡像備份到磁盤,但是該備份是非常耗時的,而且備份也不能很頻繁,如果發(fā)生諸如拉閘限電、拔插頭等狀況,那么將造成比較大范圍的數(shù)據(jù)丟失。
      #
      所以redis提供了另外一種更加高效的數(shù)據(jù)庫備份及災(zāi)難恢復方式。
      # 開啟append
      only模式之后,redis會把所接收到的每一次寫操作請求都追加到appendonly.aof文件中,當redis重新啟動時,會從該文件恢復出之前的狀態(tài)。
      #
      但是這樣會造成appendonly.aof文件過大,所以redis還支持了BGREWRITEAOF指令,對appendonly.aof 進行重新整理。
      #
      你可以同時開啟asynchronous dumps 和 AOF
    
      appendonly no
    
      # AOF文件名稱 (默認: "appendonly.aof")
      # appendfilename appendonly.aof
    
      # Redis支持三種同步AOF文件的策略:
      #
      # no: 不進行同步,系統(tǒng)去操作 . Faster.
      # always:
      always表示每次有寫操作都進行同步. Slow, Safest.
      # everysec: 表示對寫操作進行累積,每秒同步一次.
      Compromise.
      #
      # 默認是"everysec",按照速度和安全折中這是最好的。
      #
      如果想讓Redis能更高效的運行,你也可以設(shè)置為"no",讓操作系統(tǒng)決定什么時候去執(zhí)行
      #
      或者相反想讓數(shù)據(jù)更安全你也可以設(shè)置為"always"
      #
      # 如果不確定就用 "everysec".
    
      # appendfsync always
      appendfsync everysec
      # appendfsync no
    
      # AOF策略設(shè)置為always或者everysec時,后臺處理進程(后臺保存或者AOF日志重寫)會執(zhí)行大量的I/O操作
      #
      在某些Linux配置中會阻止過長的fsync()請求。注意現(xiàn)在沒有任何修復,即使fsync在另外一個線程進行處理
      #
      #
      為了減緩這個問題,可以設(shè)置下面這個參數(shù)no-appendfsync-on-rewrite
      #
      # This means that while
      another child is saving the durability of Redis is
      # the same as "appendfsync
      none", that in pratical terms means that it is
      # possible to lost up to 30
      seconds of log in the worst scenario (with the
      # default Linux
      settings).
      #
      # If you have latency problems turn this to "yes". Otherwise
      leave it as
      # "no" that is the safest pick from the point of view of
      durability.
      no-appendfsync-on-rewrite no
    
      # Automatic rewrite of the append only file.
      # AOF 自動重寫
      #
      當AOF文件增長到一定大小的時候Redis能夠調(diào)用 BGREWRITEAOF 對日志文件進行重寫
      #
      #
      它是這樣工作的:Redis會記住上次進行些日志后文件的大小(如果從開機以來還沒進行過重寫,那日子大小在開機的時候確定)
      #
      #
      基礎(chǔ)大小會同現(xiàn)在的大小進行比較。如果現(xiàn)在的大小比基礎(chǔ)大小大制定的百分比,重寫功能將啟動
      #
      同時需要指定一個最小大小用于AOF重寫,這個用于阻止即使文件很小但是增長幅度很大也去重寫AOF文件的情況
      # 設(shè)置 percentage
      為0就關(guān)閉這個特性
    
      auto-aof-rewrite-percentage 100
      auto-aof-rewrite-min-size 64mb
    
      ################################## SLOW LOG
      ###################################
    
      # Redis Slow Log 記錄超過特定執(zhí)行時間的命令。執(zhí)行時間不包括I/O計算比如連接客戶端,返回結(jié)果等,只是命令執(zhí)行時間
      #
      #
      可以通過兩個參數(shù)設(shè)置slow log:一個是告訴Redis執(zhí)行超過多少時間被記錄的參數(shù)slowlog-log-slower-than(微妙),
      #
      另一個是slow log 的長度。當一個新命令被記錄的時候最早的命令將被從隊列中移除
    
      # 下面的時間以微妙微單位,因此1000000代表一分鐘。
      #
      注意制定一個負數(shù)將關(guān)閉慢日志,而設(shè)置為0將強制每個命令都會記錄
      slowlog-log-slower-than 10000
    
      # 對日志長度沒有限制,只是要注意它會消耗內(nèi)存
      # 可以通過 SLOWLOG RESET
      回收被慢日志消耗的內(nèi)存
      slowlog-max-len 1024
    
      ################################ VM ###############################
    
      ### WARNING! Virtual Memory is deprecated in Redis 2.4
      ### The use of
      Virtual Memory is strongly discouraged.
    
      # Virtual Memory allows Redis to work with datasets bigger than the
      actual
      # amount of RAM needed to hold the whole dataset in memory.
      # In
      order to do so very used keys are taken in memory while the other keys
      # are
      swapped into a swap file, similarly to what operating systems do
      # with
      memory pages.
      #
      # To enable VM just set 'vm-enabled' to yes, and set the
      following three
      # VM parameters accordingly to your needs.
    
      vm-enabled no
      # vm-enabled yes
    
      # This is the path of the Redis swap file. As you can guess, swap
      files
      # can't be shared by different Redis instances, so make sure to use a
      swap
      # file for every redis process you are running. Redis will complain if
      the
      # swap file is already in use.
      #
      # The best kind of storage for the
      Redis swap file (that's accessed at random)
      # is a Solid State Disk
      (SSD).
      #
      # *** WARNING *** if you are using a shared hosting the default
      of putting
      # the swap file under /tmp is not secure. Create a dir with access
      granted
      # only to Redis user and configure Redis to create the swap file
      there.
      vm-swap-file /tmp/redis.swap
    
      # vm-max-memory configures the VM to use at max the specified amount
      of
      # RAM. Everything that deos not fit will be swapped on disk *if* possible,
      that
      # is, if there is still enough contiguous space in the swap
      file.
      #
      # With vm-max-memory 0 the system will swap everything it can. Not
      a good
      # default, just specify the max amount of RAM you can in bytes, but
      it's
      # better to leave some margin. For instance specify an amount of
      RAM
      # that's more or less between 60 and 80% of your free
      RAM.
      vm-max-memory 0
    
      # Redis swap files is split into pages. An object can be saved using
      multiple
      # contiguous pages, but pages can't be shared between different
      objects.
      # So if your page is too big, small objects swapped out on disk will
      waste
      # a lot of space. If you page is too small, there is less space in the
      swap
      # file (assuming you configured the same number of total swap file
      pages).
      #
      # If you use a lot of small objects, use a page size of 64 or 32
      bytes.
      # If you use a lot of big objects, use a bigger page size.
      # If
      unsure, use the default :)
      vm-page-size 32
    
      # Number of total memory pages in the swap file.
      # Given that the page
      table (a bitmap of free/used pages) is taken in memory,
      # every 8 pages on
      disk will consume 1 byte of RAM.
      #
      # The total swap size is vm-page-size *
      vm-pages
      #
      # With the default of 32-bytes memory pages and 134217728 pages
      Redis will
      # use a 4 GB swap file, that will use 16 MB of RAM for the page
      table.
      #
      # It's better to use the smallest acceptable value for your
      application,
      # but the default is large in order to work in most
      conditions.
      vm-pages 134217728
    
      # Max number of VM I/O threads running at the same time.
      # This threads
      are used to read/write data from/to swap file, since they
      # also encode and
      decode objects from disk to memory or the reverse, a bigger
      # number of
      threads can help with big objects even if they can't help with
      # I/O itself
      as the physical device may not be able to couple with many
      # reads/writes
      operations at the same time.
      #
      # The special value of 0 turn off threaded
      I/O and enables the blocking
      # Virtual Memory
      implementation.
      vm-max-threads 4
    
      ############################### ADVANCED CONFIG
      ###############################
    
      # 當hash中包含超過指定元素個數(shù)并且最大的元素沒有超過臨界時,
      #
      hash將以一種特殊的編碼方式(大大減少內(nèi)存使用)來存儲,這里可以設(shè)置這兩個臨界值
      # Redis
      Hash對應(yīng)Value內(nèi)部實際就是一個HashMap,實際這里會有2種不同實現(xiàn),
      #
      這個Hash的成員比較少時Redis為了節(jié)省內(nèi)存會采用類似一維數(shù)組的方式來緊湊存儲,而不會采用真正的HashMap結(jié)構(gòu),對應(yīng)的value
      redisObject的encoding為zipmap,
      #
      當成員數(shù)量增大時會自動轉(zhuǎn)成真正的HashMap,此時encoding為ht。
      hash-max-zipmap-entries
      512
      hash-max-zipmap-value 64
    
      # list數(shù)據(jù)類型多少節(jié)點以下會采用去指針的緊湊存儲格式。
      #
      list數(shù)據(jù)類型節(jié)點值大小小于多少字節(jié)會采用緊湊存儲格式。
      list-max-ziplist-entries
      512
      list-max-ziplist-value 64
    
      # set數(shù)據(jù)類型內(nèi)部數(shù)據(jù)如果全部是數(shù)值型,且包含多少節(jié)點以下會采用緊湊格式存儲。
      set-max-intset-entries
      512
    
      # zsort數(shù)據(jù)類型多少節(jié)點以下會采用去指針的緊湊存儲格式。
      #
      zsort數(shù)據(jù)類型節(jié)點值大小小于多少字節(jié)會采用緊湊存儲格式。
      zset-max-ziplist-entries
      128
      zset-max-ziplist-value 64
    
      # Redis將在每100毫秒時使用1毫秒的CPU時間來對redis的hash表進行重新hash,可以降低內(nèi)存的使用
      #
      #
      當你的使用場景中,有非常嚴格的實時性需要,不能夠接受Redis時不時的對請求有2毫秒的延遲的話,把這項配置為no。
      #
      #
      如果沒有這么嚴格的實時性要求,可以設(shè)置為yes,以便能夠盡可能快的釋放內(nèi)存
      activerehashing yes
    
      ################################## INCLUDES 
      ###################################
    
      # 指定包含其它的配置文件,可以在同一主機上多個Redis實例之間使用同一份配置文件,而同時各個實例又擁有自己的特定配置文件
      #
      include /path/to/local.conf
      # include /path/to/other.conf
    
  • TomcatRedis 的session共享,一般不使用,只作為知識擴展,一般都會使用cas,而不是redis的session共享
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。