Redis基础
Nosql
NoSQL:即Not-OnlySQL(泛指非關(guān)系型的數(shù)據(jù)庫),作為關(guān)系型數(shù)據(jù)庫的補(bǔ)充。
作用:應(yīng)對基于海量用戶和海量數(shù)據(jù)前提下的數(shù)據(jù)處理問題。
Redis介紹
概念
Redis(REmote DlctionaryServer)是用C語言開發(fā)的一個開源的高性能鍵值對(key-value)數(shù)據(jù)庫
特征
1.數(shù)據(jù)間沒有必然的關(guān)聯(lián)關(guān)系
2.內(nèi)部采用單線程機(jī)制進(jìn)行工作
3.高性能
4.支持多種數(shù)據(jù)類型
5.支持持久化,可以存硬盤。
應(yīng)用
熱點信息,時效性信息,分布式數(shù)據(jù)共享,消息隊列,即使信息查詢。
在虛擬機(jī)上啟動redis服務(wù)
通過指定的配置文件啟動redis服務(wù),
- 查看進(jìn)程:ps -ef | grep redis
- 進(jìn)入配置文件的目錄cd /usr/local/redis/bin/
- 輸入 ./redis-server redis.conf
- 輸入 ./redis-cli
- 關(guān)閉服務(wù)并退出:shutdown 然后:exit
鍵值對
設(shè)置鍵值對
? 語法:set key value
獲取鍵值對
? 語法:get key
判斷鍵是否存在:exist key
設(shè)置過期時間: expire key 時間
查看過期時間: ttl key
查看當(dāng)前key的數(shù)據(jù)類型:> type key
刪除key:del key
庫
redis共有16個庫
選擇數(shù)據(jù)庫
語法:select 數(shù)字
查看
查看大小:dbsize
查看數(shù)據(jù)庫所有的鍵:keys *
清空
清空當(dāng)前數(shù)據(jù)庫:flushdb
清空所有:flushall
基本數(shù)據(jù)類型
String
追加字符串,不存在則新建:append key1 "hello"
獲取字符串長度:strlen key1
初始瀏覽量為0 :set views 0
設(shè)置自增1:incr views
設(shè)置自減1:decr views
可以設(shè)置步長。每次的增長值 : INCRBY views 10 #
獲取指定范圍的值: GETRANGE key 起始點 結(jié)束點
獲取所有長度的值: GETRANGE key 0 -1
設(shè)置多個值:
mset key value key value ……
mget key key key
msetnx 原子性操作設(shè)置多個值
設(shè)置過期時間和值:
設(shè)置key3 的值為 he11o,30秒后過期: setex key3 30 "he1lo"
先get然后在set: getset
List
LPuSH key value
LPUSH list one #將一個值或者多個值,插入到列表頭部(左)
RPUSH key value
Rpush list righr #將一個值或者多個值,插入到列表位部(右)
lrange key start end
LRANGE list 0 1 #通過區(qū)間獲取具體的值!
LROR key #移出并獲取列表的第一個元素
lindex list 1 #通過下標(biāo)獲得list 中的某一個值!
Llen list # 返回列表的長度
lrem key count value
lrem list 1 one # 移除list集合中指定個數(shù)的value,精確匹配
ltrim list 1 2 #截取指定的長度!
lset 將列表中指定下標(biāo)的值替換為另外一個值,更新操作
lset list 0 item #如果存在,更新當(dāng)前下標(biāo)的值
在指定元素前后插入指定的值
LINSERT mylist after world new
set
set集合中添加
sadd key value
sadd myset "hello"
查看指定set的所有值
smembers key
SMEMBERS myset
判斷某一個值是不是在set集合中!
sismember key value
SISMEMBER myset hello
查看個數(shù)
scard key
scard myset
移除set集合中的指定元素
srem key value
srem myset hello
獲取隨機(jī)
SRANDMEMBER myset
SRANDMEMBER myset 2
smove myset myset2 "kuangshen"# 將一個指定的值,移動到另外一個set集合!
SDIFF key1 key2 差集
SINTER key1 key2 交集
SUNION key1 key2 并集
hash
hset 集合名 key value
hset myhash field1 hello
# set一個具體key-vlaue
獲取一個字段值
hget 集合名 key鍵
hget myhash field1
添加多個 key-vlaue
hmset 集合 key鍵1 key鍵2
hmset myhash field1 hello field2 world
獲取多個字段值
hmget 集合名 key1 key2
hmget myhash field1 field2
獲取全部的數(shù)據(jù)
hget 集合名
hgetall myhash
刪除hash指定key字段!對應(yīng)的value值也就消失了!
hdel 集合名 key
hdel myhash field1
判斷hash中指定字段是否存在!
HEXISTS myhash field1
只獲得所有field
hkeys 集合名
hkeys myhash
只獲得所有value
hvals 集合名
hvals myhash
設(shè)置自動增長
HINCRBY myhash field3 1
HINCRBY myhash field3 -1
如果不存在則可以設(shè)置
hsetnx myhash field4 hello
如果存在則不能設(shè)置
hsetnx myhash field4 world
zset
zset在set的基礎(chǔ)上增加了一個值,set k1 v1 zset k1 score1 v1
添加一個值
zadd key score value
zadd myset 1 one
添加多個值
zadd myset 2 two 3 three
獲取范圍值
zrange key start end
zrange myset 0 -1
顯示全部內(nèi)容從小到大
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]
移除元素
zrem key value
特殊數(shù)據(jù)類型
地理位置geostital
創(chuàng)建一個元素
geoadd key 緯度 經(jīng)度 成員
geoadd city 116.40 39.90 beijing
獲取坐標(biāo)
geopos city beijing
獲取兩者之間的距離
geodist key value1 value2 單位
geodist city beijing shanghai km
相關(guān)范圍內(nèi)的城市
georadius key 緯度 經(jīng)度 距離 單位 withdist
找出指定位置內(nèi)的其他元素
georadiusbymember key value 距離 單位
bitmaps
位存儲
統(tǒng)計用戶信息,活躍,不活躍!登錄、未登錄!打卡,365打卡!兩個狀態(tài)的,都可以使用Bitmaps!
Bitmaps位圖,數(shù)據(jù)結(jié)構(gòu)!都是操作二進(jìn)制位來進(jìn)行記錄,就只有0和1兩個狀態(tài)!
365天=365 bit 1字節(jié)=8bit46個字節(jié)左右!
設(shè)置一個元素
setbit key offset value
查看
getbit sign offset
事務(wù)
Redis 事務(wù)本質(zhì):一組命令的集合!一個事務(wù)中的所有命令都會被序列化,在事務(wù)執(zhí)行過程的中,會按照順序執(zhí)行! 一次性、順序性、排他性!執(zhí)行一系列的命令!
Redis命令保證原子性,但是事務(wù)不保證原子性!
redis事務(wù):
1 開啟事務(wù):開啟一個事務(wù)
multi
2 命令入隊:將命令放入事務(wù)
set key value
3 執(zhí)行事務(wù):執(zhí)行事務(wù)中的命令
exec
4 取消事務(wù):事務(wù)中的命令都不會被執(zhí)行
discard
eg:
# 正常執(zhí)行
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379(TX)> set k1 v1
QUEUED
127.0.0.1:6379(TX)> set k2 2
QUEUED
127.0.0.1:6379(TX)> exec
1) OK
2) OK
#取消事務(wù)
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> set k1 v1
QUEUED
127.0.0.1:6379(TX)> DISCARD
OK
127.0.0.1:6379> get k1
"v1"
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> set k3 v3
QUEUED
127.0.0.1:6379(TX)> DISCARD
OK
127.0.0.1:6379> get k3
(nil)
如果在入隊的命令中有錯誤的命令,
如果是編譯時異常,那么所有命令都不會被執(zhí)行。
如果是運(yùn)行時異常,那么其他命令正常執(zhí)行,僅有錯誤的命令拋出錯誤信息。
鎖
悲觀鎖
很悲觀,什么時候都要加鎖。
樂觀鎖
很樂觀,認(rèn)為什么時候都不會出問題,所以不會上鎖!更新數(shù)據(jù)的時候去判斷一下,在此期間是否有人修改過這個數(shù)據(jù),
獲取version
更新的時候比較version
使用watch命令當(dāng)作redis的樂觀鎖操作
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> INCRBY money 10
QUEUED
127.0.0.1:6379(TX)> exec
1) (integer) 20
127.0.0.1:6379>
unwatch
如果發(fā)現(xiàn)事務(wù)執(zhí)行失敗,就先解鎖
jedis
Jedis是redis的java版本的客戶端實現(xiàn),使用Jedis提供的Java API對Redis進(jìn)行操作,是Redis官方推崇的方式;并且,使用Jedis提供的對Redis的支持也最為靈活、全面;不足之處,就是編碼復(fù)雜度較高。
導(dǎo)入依賴
簡單語法:
Jedis jedis = new Jedis( host: "127.0.0.1", port: 6379);
System.out.println("清空數(shù)據(jù):"+jedis.flushDB());
System.out.println("判斷某個鍵是否存在:"+jedis.exists( key: "username"));
System.out.println("新增<'username','haha'>的鍵值對:"+jedis.set("username","haha");
System.out.println("新增<'password','mima'>的鍵值對:"+jedis.set("password","mima");
System.out.print("系統(tǒng)中所有的鍵如下:");
Set<String> keys = jedis.keys( pattern:"*");
System.out.println(keys);
System.out.println("刪除鍵password:"+jedis.del( key:"password"));
System.out.println("判斷鍵password是否存在:"+jedis.exists( key: "password"));
System.out.println("查看鍵username所存儲的值的類型:"+jedis.type( key: "username"));
System.out.println("隨機(jī)返回key空間的一個:"+jedis.randomKey());
System.out.println("重命名key:"+jedis.rename( oldkey: "username", newkey: "name"));
System.out.println("取出改后的name: "+jedis.get("name"));
System.out.println("按索引查詢:"+jedis.select( index: 0));
System.out.println("刪除當(dāng)前選擇數(shù)據(jù)庫中的所有key:"+jedis.flushDB());
System.out.println("返回當(dāng)前數(shù)據(jù)庫中key的數(shù)目:"+jedis.dbSize());
System.out.println("刪除所有數(shù)據(jù)庫中的所有key:"+jedis.flushAll());
System.out.println(jedis.set("key1","value1"));
System.out.println(jedis.set("key2","value2"));
System.out.println(jedis.set("key3","value3"));
System.out.println("刪除鍵key2:"+jedis.del( key: "key2"));
System.out.println("獲取鍵key2:"+jedis.get("key2"));
System.out.println("修改key1:"+jedis.set("key1","value1Changed"));
System.out.println("獲取key1的值:"+jedis.get("key1"));
System.out.println("在key3后面加入值:"+jedis.append("key3", "End"));
System.out.println("key3的值:"+jedis.get("key3"));
system.out.println("增加多個鍵值對:"+jedis.mset( "key01","value01","key02","va2");//(keys,values)
system.out.println("獲取多個鍵值對:"+jedis .mget( "key01","key02","key03"));//(...keys: )
jedis.flushDB(); //清空數(shù)據(jù)庫
System.out.println("===========新增鍵值對防止覆蓋原先值============="):
System.out.println(jedis.setnk("key1","value1"));
System.out.println(jedis.setnx("key2","value2"));
System.out.println(jedis.setnx("key2","value2-new"));
System.out.println(jedis.get("key1"));
System.out.println(jedis.get("key2"));
System.out.println("===========新增鍵值對并設(shè)置有效時間=============");
System.out.print1n(jedis.setex("key3", 2,"value3")); //(key,seconds,val)
System.out.print1n(jedis.get("key3"));
//清空數(shù)據(jù)庫,setnx(key,value)
jedis.flushDB();
System.out.print1n("===========新增鍵值對防止覆蓋原先值=========");
System.out.println(jedis.setnx("key1","value1"));
System.out.println(jedis.setnx("key2","value2"));
System.out.println(jedis.setnx("key2","value2-new"));
System.out.println(jedis.get("key1"));
System.out.print1n(jedis.get("key2"));
System.out.println("===========新增鍵值對并設(shè)置有效時間:=========");
System.out.println(jedis.setex((key:"key3",seconds:2,Ivalue: "value3"));
System.out.println(jedis.get("key3"));
try {
TimeUnit.SECONDS.sleep(timeout: 3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(jedis.get("key3"));
//List集合
jedis.flushDB();//清空數(shù)據(jù)庫
System.out.print1n("===========添加一個1ist===========");
jedis.lpush(key:"collections",...strings:"ArrayList","Vector","Stack","HashMap","WeakHashMap","List");
jedis.lpush( key: "collections",...strings:"Hashset");
jedis.lpush( key: "collections",...strings: "TreeSet");
jedis.1push( key: "collections",...strings: "TreeMap");
System.out.println("collections的內(nèi)容:"+jedis.lrange( key: "collections",start: 0,stop:-1));//0,-1代表所有
System.out.println("collections區(qū)間0-3的元素:"+jedis.1range( key: "collections", start:0,stop:3));
System.out.println("刪除指定元素個數(shù):"+jedis.1rem( key: "collections", count: 2, value: "HashMap"));
System.out.print1n("collections的內(nèi)容:"+jedis.lrange( key: "collections",start: 0, stop: -1));
System.out.println("刪除下表0-3區(qū)間之外的元素:"+jedis.ltrim( key: "collections", start: 0, stop:3));
System.out.print1n("collections的內(nèi)容:"+jedis.lrange( key: "collections", start: 0, stop:-1));
system.out.println("collections列表出棧(左端):"+jedis.lpop( key:"collections"));
System.out.println("collections的內(nèi)容:"+jedis.lrange( key:"collections", start: 0, stop:-1));
System.out.println("collections添加元素,從列表右端,與lpush相對應(yīng):"+jedis.rpush( key: "collections", value:"list1");
System.out.println("collections的內(nèi)容:“+jedis.1range( key: "collections",start: 0, stop:-1));
System.out.print1n("collections列表出棧(右端):"+jedis.rpop( key: "collections"));
System.out.println("collections的內(nèi)容:"+jedis.lrange( key: "collections",start: 0, stop:-1));
System.out.println("修改collections指定下標(biāo)1的內(nèi)容:"+jedis.lset( key: "collections", index: 1, value:"list");
System.out.print1n("collections的內(nèi)容:"+jedis.lrange( key: "collections", start: e, stop:-1));
System.out.print1n("===================");
System.out.println("collections的長度:"+jedis.llen( key: "collections"));
System.out.print1n("獲取collections下標(biāo)為2的元素:"+jedis.lindex( key: "collections", index: 2));
System.out.println("===================");
jedis.lpush( key: "sortedList", ...strings: "3","6","2","0","7","4");
System.out.println("sortedList排序前:"+jedis.lrange( key: "sortedList", start: 0, stop:-1));
System.out.println(jedis.sort( key: "sortedList"));
//set集合
jedis.flushDB();//清空數(shù)據(jù)庫
System.out.println("============向集合中添加元素(不重復(fù))============");
System.out.println(jedis.sadd( key: "eleSet", ...members: "e1" ,"e2" ,"e4","e3","e0","e8","e7","e5"));
System.out.print1n(jedis.sadd( key: "eleSet", ...members: "e6"));
System.out.println(jedis.sadd( key: "eleset", ...members: "e6"));
System.out.println("eleSet的所有元素為:"+jedis.smembers( key: "eleSet"));
System.out.println("刪除一個元素e0:"+jedis.srem(key: "eleSet", ...members: "e0"));
System.out.println("eleSet的所有元素為:"+jedis.smembers( key: "eleSet"));
System.out.println("刪除兩個元素e7和e6:"+jedis.srem( key: "eleset", ...members: "e7","e6"));
System.out.println("eleSet的所有元素為:"+jedis.smembers( key: "eleSet"));
System.out.println("隨機(jī)的移除集合中的一個元素:"+jedis.spop( key: "eleSet"));
System.out.println("隨機(jī)的移除集合中的一個元素:"+jedis.spop( key: "eleset"));
System.out.println("eleSet的所有元素為:"+jedis.smembers( key: "eleSet"));
System.out.println("eleSet中包含元素的個數(shù):"+jedis.scard( key: "eleset"));
System.out.println("e3是否在eleset中:"+jedis.sismember( key: "eleset", member: "e3"));
System.out.println("e1是否在eleSet中:"+jedis.sismember( key: "eleSet", member: "e1"));
System.out.println("e1是否在eleSet中:"+jedis.sismember( key: "eleset", member: "e5"));
System.out.println(jedis.sadd(key:"eleSet1",...members:"e1","e2","e4","e3","e0","e8","e7","e5"));
System.out.println(jedis.sadd( key: "eleSet2",...members: "e1","e2","e4","e3","e0","e8"));
System.out.println("將eleSet1中刪除e1并存入eleSet3中:"+jedis.smove( srckey: "eleSet1", dstkey: "eleSet3",dstvalue:"");
System.out.println("將eleSet1中刪除e2并存入eleSet3中:"+jedis.smove( srckey: "eleSet1", dstkey: "eleSet3",dstvalue:"val");
System.out.println("eleSet1中的元素:"+jedis.smembers( key: "eleSet1"));
System.out.println("eleSet3中的元素:"+jedis. smembers ( key:"eleSet3"));
System.out.print1n("============集合運(yùn)算=================");
System.out.println("eleSet1中的元素:"+jedis.smembers ( key: "eleSet1"));
System.out.println("eleSet2中的元素:"+jedis.smembers( key:"eleSet2"));
//hashMap
jedis.flushDB();
Map<String,String> map = new HashMap<>();
map.put("key1","value1");
map.put("key2","value2");
map.put("key3","value3");
map.put("key4","value4");
//添加名稱為hash (key)的hash元素
jedis.hmset( key: "hash",map);
//向名稱為hash的hash中添加key為key5,value為value5元素
jedis.hset( key: "hash", field: "key5", value: "value5");
System.out.println("散列hash的所有鍵值對為:"+jedis.hgetA1l( key: "hash"));
System.out.println("散列hash的所有鍵為:"+jedis.hkeys("hash"));
System.out.println("散列hash的所有值為:"+jedis.hvals( key: "hash"));
System.out.println("將key6保存的值加上一個整數(shù),如果key6不存在則添加key6:"+jedis.r
System.out.println("散列hash的所有鍵值對為:"+jedis.hgetAl1( key: "hash"));
System.out.println("將key6保存的值加上一個整數(shù),如果key6不存在則添加key6:“+jedis.r
system.out.println("散列hash的所有鍵值對為:"+jedis.hgetAl1(key: "hash"));
System.out.println("刪除一個或者多個鍵值對:"+jedis.hdel( key: "hash", ...fields: "key2");
System.out.println("散列hash的所有鍵值對為:"+jedis.hgetA11( key: "hash"));
System.out.println("散列hash中鍵值對的個數(shù):"+jedis.hlen( key:"hash"));
System.out.println("判斷hash中是否存在key2:"+jedis.hexists(key: "hash",field: "key2");
System.out.println("判斷hash中是否存在key3:"+jedis.hexists(key: "hash", field: "key3");
System.out.println("獲取hash中的值:"+jedis.hmget( key: "hash",...fields: "key3"));
System.out.println("獲取hash中的值:"+jedis.hmget( key: "hash", ...fields: "key3","key4");
//事務(wù)
jedis.flushDB();|
JSONObject json0bject = new JSONObject();
json0bject.put("hello","world");
json0bject.put("name","kuangshen");
// 開啟事務(wù)
Transaction multi = jedis.multi();
String result= json0bject.toJSONString();
try{
multi.set("user1",result);
multi.set("user2",result);
int i = 1/0://代碼拋出異常事務(wù),執(zhí)行失敗!
}catch(Exception e){
e.printStackTrace();
}
SpringBoot整合
修改配置文件:
#redis的配置信息
spring.data.redis.host=192.168.80.128
spring.data.redis.port=6379
#最多獲取數(shù)
spring.data.redis.lettuce.pool.max-active=8
spring.data.redis.lettuce.pool.max-wait=-1ms
spring.data.redis.lettuce.pool.max-idle=8
spring.data.redis.lettuce.pool.min-idle=0
測試:
redisTemplate 操作不同的數(shù)據(jù)類型,api和我們的指令是一樣的
opsForValue 操作字符串 類似String
opsForList 操作List 類似List
opsForSet
opsForHash
opsForzset
opsForGeo
opsForHyperLogLog
除了基本的操作,我們常用的方法都可以直接通過redisTemplate操作,比如事務(wù),和基本的CRUD
獲取redis的連接對象
@Autowired
private RedisTemplateredisTemplate;
public void redis(){
RedisConnection connection = redisTemplate.getConnectionFactory().getConnection();
connection.fLushDb();
connection.flushAll();
redisTemplate.opsForValue().set("mykey","redis111");
System.out.println(redisTemplate.opsForValue().get("mykey"));
}
配置自己的序列化方式
@Configuration
public class RedisConfig {
// 自己定義了一個RedisTemplate
@Bean
@SuppressWarnings("al1")
public RedisTemplate<String, object> redisTemplate(RedisConnectionFactory factory){
// 我們?yōu)榱俗约洪_發(fā)方便,一般直接使用<String,Object>
RedisTemplate<String,Object> template = new RedisTemplate<String,0bject>();
template.setConnectionFactory(factory);
// Json序列化配置
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(0bject.cl
ObjectMapper om = new 0bjectMapper();
om.setVisibility(PropertyAccessor.ALL,JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(0bjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.set0bjectMapper(om);
// String 的序列化
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
// key采用string的序列化方式
template.setKeySerializer(stringRedisSerializer);
// hash的key也采用string的序列化方式
template.setHashKeySerializer(stringRedisSerializer);
// value序列化方式采用jackson
template.setValueSerializer(jackson2JsonRedisSerializer);
// hash的value序列化方式采用jackson
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
}
Redis配置文件
redis里的單位配置,忽略大小寫。
導(dǎo)入其他配置文件:
include /path/to/local.conf
include /path/to/other.conf
網(wǎng)絡(luò)
bind 127.0.0.1 #綁定的ip
protected-mode yes #保護(hù)模式
port 6379 #端口設(shè)置
通用 general
daemonize yes #以守護(hù)進(jìn)程的方式運(yùn)行,默認(rèn)是no,我們需要自己開啟為yes!
pidfile /var/run/redis_6379.pid #如果以后臺的方式運(yùn)行,我們就需要指定一個pid 文件!
#日志
#specify the server verbosity level.
#This can be one of:
#debug (a lot of information, useful for development/testing)
#verbose (many rarely useful info, but not a mess like the debug level)
#notice (moderately verbose, what you want in production probably) #生產(chǎn)環(huán)境
#warning (only very important / critical messages are 1ogged)
loglevel notice
logfile,"" #日志的文件位置名
databases 16 #數(shù)據(jù)庫的數(shù)量,默認(rèn)是16個數(shù)據(jù)庫
always-show-logo yes #是否總是顯示LOGO
持久化
持久化,在規(guī)定的時間內(nèi),執(zhí)行了多少次操作,則會持久化到文件.rdb.aof
redis是內(nèi)存數(shù)據(jù)庫,如果沒有持久化,那么數(shù)據(jù)斷電及失!
RDB配置:
#如果900s內(nèi),如果至少有一個1key進(jìn)行了修改,我們及進(jìn)行持久化操作
save 900 1
#如果300s內(nèi),如果至少10key進(jìn)行了修改,我們及進(jìn)行持久化操作
save 300 10
#如果60s內(nèi),如果至少10000 key進(jìn)行了修改,我們及進(jìn)行持久化操作
save 60 10000
#我們之后學(xué)習(xí)持久化,會自己定義這個測試!
stop-writes-on-bgsave-error yes
#持久化如果出錯,是否還需要繼續(xù)工作!
rdbcompression yes #是否壓縮rdb 文件,需要消耗一些cpu資源!
rdbchecksum yes #保存rdb文件的時候,進(jìn)行錯誤的檢查校驗!
dir ./ #rdb 文件保存的目錄!
設(shè)置密碼
獲取當(dāng)前的密碼:config get requirepass
設(shè)置redis的密碼:config set requirepass "123456"
使用密碼進(jìn)行登錄: auth 123456
客戶端
設(shè)置能連接上redis的最大客戶端的數(shù)量 : maxclients 10000
redis 配置最大的內(nèi)存容量: maxmemory <bytes>
maxmemory-policy noeviction #內(nèi)存到達(dá)上限之后的處理策略
1、volatile-lru:只對設(shè)置了過期時間的key進(jìn)行LRU(默認(rèn)值)
2、al1keys-lru:刪除1ru算法的key
3、volatile-random:隨機(jī)刪除即將過期key
4、a11keys-random:隨機(jī)刪除
5、volatile-ttl:刪除即將過期的
6、noeviction :永不過期,返回錯誤
觸發(fā)機(jī)制
1、save的規(guī)則滿足的情況下,會自動觸發(fā)rdb規(guī)則
2、執(zhí)行 flushall命令,也會觸發(fā)我們的rdb規(guī)則!
3、退出redis,也會產(chǎn)生rdb文件!
備份就自動生成一個dump
如何恢復(fù)rdb文件
1、只需要將rdb文件放在我們redis啟動目錄就可以,redis啟動的時候會自動檢查dump.rdb恢復(fù)其中的內(nèi)容
2、查看需要存在的位置
config get dir
1)"dir"
2)"/usr/local/bin" # 如果在這個目錄下存在dump.rdb 文件,啟動就會自動恢復(fù)其中的數(shù)據(jù)
優(yōu)點:
1、適合大規(guī)模的數(shù)據(jù)恢復(fù)!
2、對數(shù)據(jù)的完整性要不高!
缺點:
1、需要一定的時間間隔進(jìn)程操作!如果redis意外宕機(jī)了,這個最后一次修改數(shù)據(jù)就沒有的了
2、fork進(jìn)程的時候,會占用一定的內(nèi)容空間!!
AOF配置
appendonly no #默認(rèn)是不開啟aof模式的,默認(rèn)是使用rdb方式持久化的,在大部分所有的情況下,rdb完全夠用!
appendfilename "appendonly.aof" #持久化的文件的名字
appendfsync always #每次修改都會 sync。消耗性能
appendfsync everysec #每秒執(zhí)行一次sync,可能會丟失這1s的數(shù)據(jù)!
appendfsync no #不執(zhí)行 sync,這個時候操作系統(tǒng)自己同步數(shù)據(jù),速度最快!
搜索配置文件內(nèi)容:
vim 文件
:/搜索內(nèi)容 n下一個
如果這個 aof 文件有錯誤,這時候redis 是啟動不起來的嗎,我們需要修復(fù)這個aof文件redis 給我們提供了一個工具 redis-check-aof --fix
消息訂閱
關(guān)注消息后,消息發(fā)出者可以發(fā)出訂閱者都收到的消息。
發(fā)送端:
127.0.0.1:6379> PUBLISH hello nihao
(integer) 1
127.0.0.1:6379> PUBLISH hello haha
(integer) 1
127.0.0.1:6379>
接收端
127.0.0.1:6379> SUBSCRIBE hello
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "hello"
3) (integer) 1
1) "message"
2) "hello"
3) "nihao"
1) "message"
2) "hello"
3) "haha"
redis主從復(fù)制
主從復(fù)制,讀寫分離!80%的情況下都是在進(jìn)行讀操作!減緩服務(wù)器的壓力!架構(gòu)中經(jīng)常使用!一主二從!
主從復(fù)制,是指將一臺Redis服務(wù)器的數(shù)據(jù),復(fù)制到其他的Redis服務(wù)器。前者稱為主節(jié)點(master/leader),后者稱為從節(jié)點(slave/follower);數(shù)據(jù)的復(fù)制是單向的,只能由主節(jié)點到從節(jié)點。Master以寫為主,Slave以讀為主。
注意:只配從庫不配主庫
查看當(dāng)前庫的信息: info replication
127.0.0.1:6379> info replication
# Replication
role:master #角色
connected_slaves:0 #從機(jī)數(shù)量
master_failover_state:no-failover
master_replid:91336488202d1d08d9ddc463852f4c40d2950b7c
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
可以測試:
復(fù)制3個配置文件,然后修改對應(yīng)的信息
1、端口
2、pid 名字
3、log文件名字
4、dump.rdb 名字
默認(rèn)情況下,每臺Redis服務(wù)器都是主節(jié)點
配置從節(jié)點,認(rèn)老大:
Slaveof host port
真實的從主配置應(yīng)該在配置文件中配置,這樣的話是永久的,我們這里使用的是命令,暫時的!
主機(jī)負(fù)責(zé)寫,從機(jī)負(fù)責(zé)讀
Slave 啟動成功連接到master后會發(fā)送一個sync同步命令
Master 接到命令,啟動后臺的存盤進(jìn)程,同時收集所有接收到的用于修改數(shù)據(jù)集命令,在后臺進(jìn)程執(zhí)行完畢之后,master將傳送
整個數(shù)據(jù)文件到slave,并完成一次完全同步。
全量復(fù)制:而slave服務(wù)在接收到數(shù)據(jù)庫文件數(shù)據(jù)后,將其存盤并加載到內(nèi)存中。
增量復(fù)制:Master繼續(xù)將新的所有收集到的修改命令依次傳給slave,完成同步
但是只要是重新連接master,一次完全同步(全量復(fù)制)將被自動執(zhí)行
總結(jié)
- 上一篇: Django学习(一) 之 环境搭建
- 下一篇: Vite4+Typescript+Vue