Redis是一個開源舞蔽,高級的鍵值存儲和一個適用的解決方案,用于構(gòu)建高性能码撰,可擴(kuò)展的Web應(yīng)用程序渗柿。本文將概要介紹Redis的特性和語法,并以實(shí)例代碼的形式介紹如何通過Jedis在java語言環(huán)境下控制Redis脖岛,幫助各位讀者快速入門朵栖。
NoSQL概述
Redis是NoSQL數(shù)據(jù)庫的代表之一,那什么是NoSQL?
NoSQL = not only SQL柴梆,即非關(guān)系型數(shù)據(jù)庫陨溅。
Why NoSQL?
和傳統(tǒng)的關(guān)系型數(shù)據(jù)庫相比绍在,NoSQL具有以下的優(yōu)勢:
- High Performance:高并發(fā)讀寫门扇;
- Huge Storage: 海量數(shù)據(jù)的高效存儲和訪問;
- High Scalability & High Availability:高可擴(kuò)展和高可用性
NoSQL的分類:
- Key-Value偿渡,如Redis,快速查詢臼寄,但是數(shù)據(jù)存儲缺少結(jié)構(gòu)化;
- 列存儲溜宽,如HBase, 擴(kuò)展性強(qiáng)吉拳,查找速度快,但是功能局限坑质;
- 文檔數(shù)據(jù)庫合武,如MongoDB临梗,數(shù)據(jù)格式靈活,查詢性能不高稼跳,缺少統(tǒng)一的查詢語法盟庞;
- 圖形數(shù)據(jù)庫,如InfoGrid汤善,基于圖的算法什猖,但是不容易做分布式的查詢;
Redis概述
Redis是一個開源红淡,高性能的鍵值對數(shù)據(jù)庫不狮, 其優(yōu)點(diǎn)包括:
- 異常快 :Redis非吃诤担快摇零,每秒可執(zhí)行大約110000次的設(shè)置(SET)操作,每秒大約可執(zhí)行81000次的讀取/獲取(GET)操作桶蝎。
- 支持豐富的數(shù)據(jù)類型 :Redis支持開發(fā)人員常用的大多數(shù)數(shù)據(jù)類型驻仅,例如列表,集合登渣,排序集和散列等等噪服。這使得Redis很容易被用來解決各種問題,因為我們知道哪些問題可以更好使用地哪些數(shù)據(jù)類型來處理解決胜茧。
- 操作具有原子性 : 所有Redis操作都是原子操作粘优,這確保如果兩個客戶端并發(fā)訪問,Redis服務(wù)器能接收更新的值呻顽。
-
多實(shí)用工具 : Redis是一個多實(shí)用工具雹顺,可用于多種用例,如:
- 緩存芬位;
- 任務(wù)隊列无拗;
- 網(wǎng)站統(tǒng)計;
- 數(shù)據(jù)過期處理昧碉;
- 應(yīng)用排行榜英染;
- 分布式集群的Session分離;
Redis與其他鍵值存儲系統(tǒng)
Redis是鍵值數(shù)據(jù)庫系統(tǒng)的不同進(jìn)化路線被饿,它的值可以包含更復(fù)雜的數(shù)據(jù)類型四康,可在這些數(shù)據(jù)類型上定義原子操作。
Redis是一個內(nèi)存數(shù)據(jù)庫狭握,但在磁盤數(shù)據(jù)庫上是持久的闪金,因此它代表了一個不同的權(quán)衡,在這種情況下,在不能大于存儲器(內(nèi)存)的數(shù)據(jù)集的限制下實(shí)現(xiàn)非常高的寫和讀速度哎垦。
內(nèi)存數(shù)據(jù)庫的另一個優(yōu)點(diǎn)是囱嫩,它與磁盤上的相同數(shù)據(jù)結(jié)構(gòu)相比,復(fù)雜數(shù)據(jù)結(jié)構(gòu)在內(nèi)存中存儲表示更容易操作漏设。 因此墨闲,Redis可以做很少的內(nèi)部復(fù)雜性。
Redis的安裝和使用
Redis的安裝是否簡單郑口,在Ubuntu上安裝Redis鸳碧,打開終端并鍵入以下命令即可
sudo apt-get update
sudo apt-get install redis-server
啟動服務(wù)器:redis-server
啟動客戶端:redis-cli
如果是Windows環(huán)境下,則參照以下文章:
http://download.csdn.net/download/fengxinyixiao/9860813
http://blog.csdn.net/joyhen/article/details/47358999
Jedis入門
Jedis是Redis官網(wǎng)首選的Java客戶端開發(fā)包.
其GItHub地址為:
https://github.com/xetorthio/jedis
在Maven中犬性,添加如下依賴即可使用:
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
以下是官網(wǎng)是上給出的示例代碼瞻离,連接本地Redis,進(jìn)行操作.
@Test
public void ConnectionTest(){
//1. Connecting to Redis server on localhost
Jedis jedis = new Jedis("localhost");
System.out.println("Connection to server sucessfully");
//2. set the data in redis string
jedis.set("username", "Roxin");
//3. Get the stored data and print it
System.out.println("Stored string in redis:: "+ jedis.get("username"));
//4. Close the Redis connection;
jedis.close();
}
其中通過調(diào)用set
方法來設(shè)置鍵值對乒裆,通過get
方法獲取鍵值對套利。
除此之外,Jedis還提供連接池的方式控制連接
@Test
public void ConnectionPoolTest(){
//連接池設(shè)定
JedisPoolConfig config = new JedisPoolConfig();
//設(shè)定最大連接數(shù)
config.setMaxTotal(30);
//設(shè)置最大空閑連接數(shù)
config.setMaxIdle(10);
//創(chuàng)建連接池
JedisPool jedisPool = new JedisPool(config, "127.0.0.1");
//獲得服務(wù)資源
Jedis jedis = jedisPool.getResource();
jedis.select(1);
jedis.set("username", "Roxin By Jedis Pool");
System.out.println(jedis.get("username"));
jedis.close();
jedisPool.close();
}
Redis的數(shù)據(jù)類型
Redis中的數(shù)據(jù)類型有:
- 字符串(String)
- 列表(list)
- 有序集合(sorted set)
- 散列(hash)
- 集合(set)
無論哪種數(shù)據(jù)類型都需要為其設(shè)定鍵值Key缸兔,設(shè)置Key的注意點(diǎn):
- 不要太長(<1024字節(jié))日裙;
- 不要太短,有可讀性惰蜜;
- 統(tǒng)一命名規(guī)范;
String
Redis中的字符串是一個字節(jié)序列受神。Redis中的字符串是二進(jìn)制安全的抛猖,這意味著它們的長度不由任何特殊的終止字符決定。因此鼻听,可以在一個字符串中存儲高達(dá)512兆字節(jié)的任何內(nèi)容财著。
除了上面提到的set/get方法,還有其他命令如下表:
序號 | 命令 | 說明 |
---|---|---|
1 | SET key value | 此命令設(shè)置指定鍵的值撑碴。 |
2 | GET key | 獲取指定鍵的值撑教。 |
3 | GETRANGE key start end | 獲取存儲在鍵上的字符串的子字符串。 |
4 | GETSET key value | 設(shè)置鍵的字符串值并返回其舊值醉拓。 |
5 | GETBIT key offset | 返回在鍵處存儲的字符串值中偏移處的位值 |
6 | MGET key1 [key2..] | 獲取所有給定鍵的值 |
7 | SETBIT key offset value | 存儲在鍵上的字符串值中設(shè)置或清除偏移處的位 |
8 | SETEX key seconds value | 使用鍵和到期時間來設(shè)置值 |
9 | SETNX key value | 設(shè)置鍵的值伟姐,僅當(dāng)鍵不存在時 |
10 | SETRANGE key offset value | 在指定偏移處開始的鍵處覆蓋字符串的一部分 |
11 | STRLEN key | 獲取存儲在鍵中的值的長度 |
12 | MSET key value [key value …] | 為多個鍵分別設(shè)置它們的值 |
13 | MSETNX key value [key value …] | 為多個鍵分別設(shè)置它們的值,僅當(dāng)鍵不存在時 |
14 | PSETEX key milliseconds value | 設(shè)置鍵的值和到期時間(以毫秒為單位) |
15 | INCR key | 將鍵的整數(shù)值增加1 |
16 | INCRBY key increment | 將鍵的整數(shù)值按給定的數(shù)值增加 |
17 | INCRBYFLOAT key increment | 將鍵的浮點(diǎn)值按給定的數(shù)值增加 |
18 | DECR key | 將鍵的整數(shù)值減1 |
19 | DECRBY key decrement | 按給定數(shù)值減少鍵的整數(shù)值 |
20 | APPEND key value | 將指定值附加到鍵 |
Hash
相當(dāng)于Map亿卤,在Redis中愤兵,每個哈希(散列)可以存儲多達(dá)4億個鍵-值對。
Jedis示例代碼如下
@Test
public void HashTest(){
Jedis jedis = jedisPool.getResource();
String hashKey = "hashKey";
//hset設(shè)置一個鍵值對
jedis.hset(hashKey,"user","Roxin");
HashMap<String, String> map = new HashMap<>();
for (int i = 0; i < 10; i++) {
map.put("field"+i,"value"+i);
}
//設(shè)置多個鍵值對
jedis.hmset(hashKey,map);
//獲得鍵值對的個數(shù)
Long hlen = jedis.hlen(hashKey);
System.out.println("Hash Size in redis:: "+hlen);
assert hlen==11;
//得到全部鍵值對
List<String> user = jedis.hmget(hashKey, "user");
System.out.println("Stored string in redis:: "+ user);
assert user.get(0).equals("Roxin");
//刪除鍵值
jedis.del(hashKey);
jedis.close();
}
Redis關(guān)于Hash類型的常見命令如下表:
序號 | 命令 | 說明 |
---|---|---|
1 | HDEL key field2 [field2] | 刪除一個或多個哈希字段排吴。 |
2 | HEXISTS key field | 判斷是否存在散列字段秆乳。 |
3 | HGET key field | 獲取存儲在指定鍵的哈希字段的值。 |
4 | HGETALL key | 獲取存儲在指定鍵的哈希中的所有字段和值 |
5 | HINCRBY key field increment | 將哈希字段的整數(shù)值按給定數(shù)字增加 |
6 | HINCRBYFLOAT key field increment | 將哈希字段的浮點(diǎn)值按給定數(shù)值增加 |
7 | HKEYS key | 獲取哈希中的所有字段 |
8 | HLEN key | 獲取散列中的字段數(shù)量 |
9 | HMGET key field1 [field2] | 獲取所有給定哈希字段的值 |
10 | HMSET key field1 value1 [field2 value2 ] | 為多個哈希字段分別設(shè)置它們的值 |
11 | HSET key field value | 設(shè)置散列字段的字符串值 |
12 | HSETNX key field value | 僅當(dāng)字段不存在時,才設(shè)置散列字段的值 |
13 | HVALS key | 獲取哈希中的所有值 |
列表list
Redis列表只是字符串列表屹堰,按插入順序排序肛冶。可以在列表的頭部或尾部添加Redis列表中的元素扯键。
列表的最大長度為2^32 - 1個元素(即4294967295淑趾,每個列表可存儲超過40億個元素)。
Jedis中示例代碼如下
@Test
public void ListTest(){
Jedis jedis = jedisPool.getResource();
String listKey = "LISTKEY";
for (int i = 0; i < 10; i++) {
//從頭插入一個元素
jedis.lpush(listKey,"L-value");
}
List<String> list = jedis.lrange(listKey, 0, -1);//從第一個到最后一個,負(fù)數(shù)代表倒數(shù)第幾個
assert list.size() == 10;
assert "L-value".equals(jedis.rpop(listKey));//從尾部取出一個元素
assert 9==jedis.llen(listKey);
jedis.rpush(listKey,"R-valure");//從尾部加入一個元素
jedis.lrem(listKey,2,"L-value");//刪除從左數(shù)2兩個"L-value"元素
jedis.lrem(listKey,0,"L-value"); //0表示刪除全部"L-value"元素
assert "R-valure".equals(jedis.lpop(listKey));//從頭部加入一個元素
jedis.del(listKey);
jedis.close();
}
Redis中關(guān)于list的命令如下表:
序號 | 命令 | 說明 |
---|---|---|
1 | BLPOP key1 [key2 ] timeout | 刪除并獲取列表中的第一個元素忧陪,或阻塞扣泊,直到有一個元素可用 |
2 | BRPOP key1 [key2 ] timeout | 刪除并獲取列表中的最后一個元素,或阻塞嘶摊,直到有一個元素可用 |
3 | BRPOPLPUSH source destination timeout | 從列表中彈出值延蟹,將其推送到另一個列表并返回它; 或阻塞,直到一個可用 |
4 | LINDEX key index | 通過其索引從列表獲取元素 |
5 | LINSERT key BEFORE/AFTER pivot value | 在列表中的另一個元素之前或之后插入元素 |
6 | LLEN key | 獲取列表的長度 |
7 | LPOP key | 刪除并獲取列表中的第一個元素 |
8 | LPUSH key value1 [value2] | 將一個或多個值添加到列表 |
9 | LPUSHX key value | 僅當(dāng)列表存在時叶堆,才向列表添加值 |
10 | LRANGE key start stop | 從列表中獲取一系列元素 |
11 | LREM key count value | 從列表中刪除元素 |
12 | LSET key index value | 通過索引在列表中設(shè)置元素的值 |
13 | LTRIM key start stop | 修剪列表的指定范圍 |
14 | RPOP key | 刪除并獲取列表中的最后一個元素 |
15 | RPOPLPUSH source destination | 刪除列表中的最后一個元素阱飘,將其附加到另一個列表并返回 |
16 | RPUSH key value1 [value2] | 將一個或多個值附加到列表 |
17 | RPUSHX key value | 僅當(dāng)列表存在時才將值附加到列表 |
需要特別說明下:
rpoplpush source destination
刪除列表中的最后一個元素,將其附加到另一個列表并返回虱颗,在消息隊列中沥匈,可以用于消息備份:當(dāng)消息被發(fā)布后,一個消息從主消息隊列中被取出忘渔,被放入到緩存隊列中高帖,當(dāng)確認(rèn)發(fā)生成功之后,再將其徹底刪除畦粮,如果發(fā)送不成功散址,就恢復(fù)該消息。
Set
Redis集合是唯一字符串的無序集合宣赔。 唯一值表示集合中不允許鍵中有重復(fù)的數(shù)據(jù)预麸。
在Redis中設(shè)置添加,刪除和測試成員的存在(恒定時間O(1)儒将,而不考慮集合中包含的元素數(shù)量)吏祸。列表的最大長度為2^32 - 1個元素(即4294967295,每組集合超過40億個元素)钩蚊。
存儲Set的使用場景:
- 跟蹤唯一性數(shù)據(jù)
- 用于維護(hù)數(shù)據(jù)對象之間的關(guān)聯(lián)關(guān)系贡翘;
Jedis的代碼示例:
@Test
public void SetTest(){
Jedis jedis = jedisPool.getResource();
String setKey1 = "SETKEY-1";
for (int i = 0; i < 10; i++) {
//添加一個元素
jedis.sadd(setKey1,"value-"+i);
}
assert 10 == jedis.scard(setKey1); //獲得元素個數(shù)
jedis.sadd(setKey1,"value-1");//添加重復(fù)的元素將失效
assert 10 == jedis.scard(setKey1);
String s= jedis.srandmember(setKey1);//隨機(jī)獲取一個元素
assert jedis.sismember(setKey1,s);//是否為集合成員
String setKey2 = "SETKEY-2";
for (int i = 1; i < 11; i++) {
jedis.sadd(setKey2,"value-"+i);
}
assert jedis.sdiff(setKey1,setKey2).size() == 1;//補(bǔ)集
assert jedis.sinter(setKey1,setKey2).size() == 9;//交集
assert jedis.sunion(setKey1,setKey2).size() == 11;//并集
jedis.del(setKey1,setKey2);
jedis.close();
}
Redis中關(guān)于Set的命令如下表:
序號 | 命令 | 說明 |
---|---|---|
1 | SADD key member1 [member2] | 將一個或多個成員添加到集合 |
2 | SCARD key | 獲取集合中的成員數(shù) |
3 | SDIFF key1 [key2] | 減去多個集合 |
4 | SDIFFSTORE destination key1 [key2] | 減去多個集并將結(jié)果集存儲在鍵中 |
5 | SINTER key1 [key2] | 相交多個集合 |
6 | SINTERSTORE destination key1 [key2] | 交叉多個集合并將結(jié)果集存儲在鍵中 |
7 | SISMEMBER key member | 判斷確定給定值是否是集合的成員 |
8 | SMOVE source destination member | 將成員從一個集合移動到另一個集合 |
9 | SPOP key | 從集合中刪除并返回隨機(jī)成員 |
10 | SRANDMEMBER key [count] | 從集合中獲取一個或多個隨機(jī)成員 |
11 | SREM key member1 [member2] | 從集合中刪除一個或多個成員 |
12 | SUNION key1 [key2] | 添加多個集合 |
13 | SUNIONSTORE destination key1 [key2] | 添加多個集并將結(jié)果集存儲在鍵中 |
14 | SSCAN key cursor [MATCH pattern] [COUNT count] | 遞增地迭代集合中的元素 |
Sorted-Set
Redis可排序集合類似于Redis集合,是不重復(fù)的字符集合两疚。 不同之處在于床估,排序集合的每個成員都與分?jǐn)?shù)相關(guān)聯(lián),這個分?jǐn)?shù)用于按最小分?jǐn)?shù)到最大分?jǐn)?shù)來排序的排序集合诱渤。雖然成員是唯一的丐巫,但分?jǐn)?shù)值可以重復(fù)。
Sorted-Set的使用場景:
- 大型在線游戲的積分排名;
- 構(gòu)建索引數(shù)據(jù)递胧;
Jedis中的示例:
@Test
public void SortedSetTest(){
Jedis jedis = jedisPool.getResource();
String sortedSetKey = "SORTEDSETKEY";
for (int i = 0; i < 10; i++) {
//添加一個元素
jedis.zadd(sortedSetKey,i*10,"v-"+i);
}
assert 10 == jedis.zcard(sortedSetKey);//獲得集合中元素個數(shù)
assert 20 == (jedis.zscore(sortedSetKey,"v-2"));//獲得集合中元素對應(yīng)的分?jǐn)?shù)
Set<String> set = jedis.zrange(sortedSetKey, 0, -2);//從第一個到倒數(shù)第二個
assert 9 == set.size() ;
assert !set.contains("v-9");
jedis.zincrby(sortedSetKey,20,"v-1");//讓元素的分?jǐn)?shù)增長20
assert 30 == jedis.zscore(sortedSetKey,"v-1");
assert 3 == jedis.zcount(sortedSetKey,20,30);//獲得分?jǐn)?shù)段中元素個數(shù)
jedis.del(sortedSetKey);
jedis.close();
}
Keys的通用操作
Jedis中關(guān)于鍵值操作的實(shí)例:
@Test
public void KeyTest(){
Jedis jedis = jedisPool.getResource();
String key = "TESTKEY-1";
String key2 = "TESTKEY-2";
jedis.set(key2,"");//設(shè)置鍵值
jedis.rename(key2,key);//鍵值重命名
System.out.println("Key Type:"+jedis.type(key));//鍵值的類型
assert jedis.exists(key);//鍵值是否存在
jedis.expire(key,1);//設(shè)置鍵值過期時間
assert 1 == jedis.ttl(key);//查看鍵值過期時間
try {
Thread.sleep(2000);//睡眠2s
} catch (InterruptedException e) {
e.printStackTrace();
}
assert !jedis.exists(key);//鍵值已過期碑韵,不存在
}
Redis中關(guān)于鍵值的其他命令:
編號 | 命令 | 描述 |
---|---|---|
1 | DEL key | 此命令刪除一個指定鍵(如果存在) |
2 | DUMP key | 此命令返回存儲在指定鍵的值的序列化版本 |
3 | EXISTS key | 此命令檢查鍵是否存在 |
4 | EXPIRE key seconds | 設(shè)置鍵在指定時間秒數(shù)之后到期/過期 |
5 | EXPIREAT key timestamp | 設(shè)置在指定時間戳之后鍵到期/過期。這里的時間是Unix時間戳格式 |
6 | PEXPIRE key milliseconds | 設(shè)置鍵的到期時間(以毫秒為單位) |
7 | PEXPIREAT key milliseconds-timestamp | 以Unix時間戳形式來設(shè)置鍵的到期時間(以毫秒為單位) |
8 | KEYS pattern | 查找與指定模式匹配的所有鍵 |
9 | MOVE key db | 將鍵移動到另一個數(shù)據(jù)庫 |
10 | PERSIST key | 刪除指定鍵的過期時間缎脾,得永生 |
11 | PTTL key | 獲取鍵的剩余到期時間 |
12 | RANDOMKEY | 從Redis返回一個隨機(jī)的鍵 |
13 | RENAME key newkey | 更改鍵的名稱 |
14 | PTTL key | 獲取鍵到期的剩余時間(以毫秒為單位) |
15 | RENAMENX key newkey | 如果新鍵不存在祝闻,重命名鍵 |
16 | TYPE key | 返回存儲在鍵中的值的數(shù)據(jù)類型 |
KEYS pattern
查找與指定模式匹配的所有鍵:
- keys * 查看所有的key;
- keys xx? 模糊匹配key;
Redis的特性
多數(shù)據(jù)
提供16個數(shù)據(jù)庫(0-15),默認(rèn)為0號數(shù)據(jù)庫遗菠,可是通過select index
選擇联喘。
事務(wù)
和關(guān)系型數(shù)據(jù)庫一樣,Redis也提供事務(wù)性操作:
DISCARD 丟棄在MULTI之后發(fā)出的所有命令(放棄事務(wù)辙纬,回滾)
- EXEC 執(zhí)行MULTI后發(fā)出的所有命令(提交事務(wù))
- MULTI 標(biāo)記事務(wù)塊的開始(開始事務(wù))
- UNWATCH 取消 WATCH 命令對所有 key 的監(jiān)視豁遭。
- WATCH key [key …] 監(jiān)視給定的鍵以確定MULTI / EXEC塊的執(zhí)行
Redis中示例代碼如下:
@Test
public void TransactionTest(){
//獲得服務(wù)資源
Jedis jedis = jedisPool.getResource();
jedis.select(1);
Transaction transaction = jedis.multi();//開啟事務(wù)
transaction.set("username", "Roxin in transaction1");
System.out.println(transaction.get("username"));
transaction.exec();//提交事務(wù)
System.out.println(jedis.get("username"));
transaction = jedis.multi();//開啟事務(wù)
transaction.set("username", "Roxin in transaction2");
System.out.println(transaction.get("username"));
transaction.discard();//撤銷事務(wù)
System.out.println(jedis.get("username"));
jedis.close();
}
Redis持久化
Redis是一個內(nèi)存數(shù)據(jù)庫,但在磁盤數(shù)據(jù)庫上是持久化的贺拣,持久化的方式分為兩種:
- RDB:默認(rèn)方式蓖谢,定時將內(nèi)存數(shù)據(jù)集快照寫入磁盤;
- AOF:以日志的方式譬涡,記錄所有操作闪幽;
RDB
優(yōu)勢
- 數(shù)據(jù)只存在一個文件中,便于數(shù)據(jù)歸檔和整理涡匀;
- 多線程啟動盯腌,性能好;
劣勢
- 如果在兩次快照寫操作之間出現(xiàn)問題渊跋,將無法回復(fù)期間的數(shù)據(jù)腊嗡;
- 多線程啟動的時候,可能會有停頓拾酝;
配置文件為Redis按照目錄下的 redis.conf:
這是配置文件設(shè)置內(nèi)存快照寫入磁盤的條件
# In the example below the behaviour will be to save:
# after 900 sec (15 min) if at least 1 key changed
# after 300 sec (5 min) if at least 10 keys changed
# after 60 sec if at least 10000 keys changed
save 900 1
save 300 10
save 60 10000
數(shù)據(jù)文件被定義為dump.rdb
,保存路徑為Redis的按照路徑卡者。
# The filename where to dump the DB
dbfilename dump.rdb
# The working directory.
#
# The DB will be written inside this directory, with the filename specified
# above using the 'dbfilename' configuration directive.
#
# The Append Only File will also be created inside this directory.
#
# Note that you must specify a directory here, not a file name.
dir ./
AOF
優(yōu)勢:
-
更高的數(shù)據(jù)安全性,有三種數(shù)據(jù)同步策略:
- 每秒同步崇决,效率高材诽,但是在一秒間隔內(nèi)斷電,未同步的數(shù)據(jù)會丟失恒傻;
- 每次修改同步脸侥,性能低,但是安全盈厘;
- 不同步睁枕;
日志是追加(append)模式,即使有宕機(jī),也不會用問題外遇。 如果是數(shù)據(jù)寫入一半出現(xiàn)問題注簿,可以使用redis-check-aof,恢復(fù)數(shù)據(jù)一致跳仿;
日志自動重寫诡渴,以防止日志過大;
日志格式清楚明了菲语,可用于數(shù)據(jù)重建妄辩;
劣勢:
- 文件要更大;
- 運(yùn)行效率更低山上;
配置文件中關(guān)于AOF的配置:
默認(rèn)不使用眼耀;
日志文件為 appendonly.aof
# The name of the append only file (default: "appendonly.aof")
appendfilename "appendonly.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.
#
# The default is "everysec",If unsure, use "everysec".
# appendfsync always
appendfsync everysec
# appendfsync no