文章目錄
- redis回顧
- **redis_day01筆記**
-
- **安裝**
- **配置檔案詳解**
- 資料類型
-
- **字元串類型(string)**
- **清單資料類型(List)**
- **python互動redis**
- **redis_day02筆記**
-
- **位圖操作bitmap**
- **Hash散列資料類型**
- **集合資料類型(set)**
- **有序集合sortedset**
- redis_day02回顧
-
- **五大資料類型及應用場景**
- **redis_day03筆記**
-
-
- 事務
-
- pipeline 流水線
- watch - 樂觀鎖
- 資料持久化
-
- RDB模式(預設開啟)
- AOF(AppendOnlyFile)
- **Redis主從複制**
- **Sentinel哨兵**
-
- redis配置
- 3、啟動sentinel
- 發現提升6381為master,其他兩個為從
- 在6381上設定新值,6380檢視
- 啟動6379,觀察日志,發現變為了6381的從
- redis配置
redis回顧
redis01 回顧
1,redis基礎概念
1,記憶體型資料庫
2,資料結構特别多,kv型存儲
3,單程序單線程
2,通用指令
3,String 字元串類型
1,緩存
2,并發計數
點贊
秒殺
3,驗證碼時效
redis02回顧
1,List 重 兩邊操作 輕 中間操作
場景:
1,生産者消費者模型
2,周遊資料
2,hash
1, 壓縮特點 【字段數512, 任意value<64位元組】
2,按需擷取的特點
場景:
緩存
統計計數
3,位圖操作
set k1 ab 00000000 00000000
setbit key offset value
對完全不存在的key 直接執行 setbit
setbit k2 0 1 10000000
redis03回顧
1,集合 交集差集并集
2,有序集合 score 排行榜
3,事務 - 不保證原子性,報證一定的隔離性
開啟事務後,指令進入服務端的指令隊列,當服務端exec這個指令時,redis逐一執行指令隊列的redis指令
用戶端技術 - 流水線
樂觀鎖 - watch
4, 持久化
rdb
存儲:實實在在的資料
觸發:save 300 10
資料量:全量持久化
aof
存儲:執行的指令
觸發: 來一個寫入指令,就執行一次
資料量:增量備份
redis_day01筆記
Redis介紹
- 特點及優點
1、開源的,使用C編寫,基于記憶體且支援持久化
2、高性能的Key-Value的NoSQL資料庫
3、支援資料類型豐富,字元串strings,散列hashes,清單lists,集合sets,有序集合sorted sets 等等
4、支援多種程式設計語言(C C++ Python Java PHP ... )
5、單程序單線程
- 與其他資料庫對比
1、MySQL : 關系型資料庫,表格,基于磁盤,慢
2、MongoDB:鍵值對文檔型資料庫,值為類似JSON文檔,資料結構相對單一
3、Redis的誕生是為了解決什麼問題??
# 解決硬碟IO帶來的性能瓶頸
- 應用場景
1,緩存
2,并發計數
點贊 秒殺
3,排行榜
4,生産者消費者模型
...
- redis版本
1、最新版本:5.0
2、常用版本:2.4、2.6、2.8、3.0(裡程碑)、3.2、3.4、4.0(教學環境版本)、5.0
- Redis附加功能
1、持久化
将記憶體中資料儲存到磁盤中,保證資料安全,友善進行資料備份和恢複
2、過期鍵功能
為鍵設定一個過期時間,讓它在指定時間内自動删除
<節省記憶體空間>
# 音樂播放器,日播放排名,過期自動删除
3、事務功能
原子的執行多個操作
4、主從複制
5、Sentinel哨兵
安裝
- Ubuntu
# 安裝
sudo apt-get install redis-server
# 服務端啟動
sudo /etc/init.d/redis-server status | start | stop | restart
# 用戶端連接配接
redis-cli -h IP位址 -p 6379 -a 密碼
配置檔案詳解
- 配置檔案所在路徑
/etc/redis/redis.conf
mysql的配置檔案在哪裡? : /etc/mysql/mysql.conf.d/mysqld.cnf
- 設定連接配接密碼
1、# 500 requirepass 密碼
2、重新開機服務
sudo /etc/init.d/redis-server restart
3、用戶端連接配接
redis-cli -h 127.0.0.1 -p 6379 -a 123456
127.0.0.1:6379>ping
- 允許遠端連接配接
1、注釋掉本地IP位址綁定
69行: # bind 127.0.0.1 ::1
2、關閉保護模式(把yes改為no)
88行: protected-mode no
3、重新開機服務
sudo /etc/init.d/redis-server restart
- 通用指令 适用于所有資料類型
#檢視redis-server的資訊
info
# 切換庫(number的值在0-15之間,db0 ~ db15)
select number
# 檢視鍵
keys 表達式 # keys *
# 資料類型
type key
# 鍵是否存在
exists key
# 删除鍵
del key
# 鍵重命名
rename key newkey
# 清除目前庫中所有資料(慎用)
flushdb
# 清除所有庫中所有資料(慎用)
flushall
資料類型
字元串類型(string)
- 特點
1、字元串、數字,都會轉為字元串來存儲
2、以二進制的方式存儲在記憶體中
- 字元串常用指令-必須掌握
# 1. 設定一個key-value
set key value
# 2. 擷取key的值
get key
# 3. key不存在時再進行設定(nx)
set key value nx # not exists
# 4. 設定過期時間(ex)
set key value ex seconds
# 5. 同時設定多個key-value
mset key1 value1 key2 value2 key3 value3
# 6. 同時擷取多個key-value
mget key1 key2 key3
- 字元串常用指令-作為了解
# 1.擷取長度
strlen key
# 2.擷取指定範圍切片内容 [包含start stop]
getrange key start stop
# 3.從索引值開始,value替換原内容
setrange key index value
- 數值操作-字元串類型數字(必須掌握)
# 整數操作
incrby key 步長
decrby key 步長
incr key : +1操作
decr key : -1操作
# 應用場景: 抖音上有人關注你了,是不是可以用INCR呢,如果取消關注了是不是可以用DECR
# 浮點數操作: 自動先轉為數字類型,然後再進行相加減,不能使用append
incrbyfloat key step
- string指令彙總
# 字元串操作
1、set key value
2、set key value nx
3、get key
3、mset key1 value1 key2 value2
4、mget key1 key2 key3
5、set key value nx ex seconds
6、strlen key
# 傳回舊值并設定新值(如果鍵不存在,就建立并指派)
7、getset key value
# 數字操作
7、incrby key 步長
8、decrby key 步長
9、incr key
10、decr key
11、incrbyfloat key number#(可為正數或負數)
# 設定過期時間的兩種方式
# 方式一
1、set key value ex 3
# 方式二
1、set key value
2、expire key 5 # 秒
3、pexpire key 5 # 毫秒
# 檢視存活時間
ttl key
-1 : 目前key存在,沒有過期時間
-2 : 目前key不存在
>0 : key的剩餘時間
# 删除過期
persist key
- string資料類型注意
# key命名規範
可采用 - wang:email
# key命名原則
1、key名字不宜過長,消耗記憶體,且在資料中查找這類鍵值的計算成本高
2、不宜過短,可讀性較差
# 值
1、一個字元串類型的值最多能存儲512M内容
- 業務場景
- 緩存
- 将mysql中的資料存儲到redis字元串類型中
- 并發計數 - 點贊/秒殺
- 說明:通過redis單程序單線程的特點,由redis負責計數,并發問題轉為串行問題
- 帶有效期的驗證碼 - 短信驗證碼
- 借助過期時間,存放驗證碼;到期後,自動消亡
- 緩存
練習
1、檢視 db0 庫中所有的鍵
select 0
keys *
2、設定鍵 trill:username 對應的值為 user001,并檢視
set trill:username user001
3、擷取 trill:username 值的長度
strlen trill:username
4、一次性設定 trill:password 、trill:gender、trill:fansnumber 并檢視(值自定義)
mset trill:password 123 trill:gender M trill:fansnumber 500
5、檢視鍵 trill:score 是否存在
exists trill:score
6、增加10個粉絲
incrby trill:fansnumber 10
7、增加2個粉絲(一個一個加)
incr trill:fansnumber
incr trill:fansnumber
8、有3個粉絲取消關注你了
9、又有1個粉絲取消關注你了
10、思考、思考、思考...,清除目前庫
11、一萬個思考之後,清除所有庫
清單資料類型(List)
- 特點
1、元素是字元串類型 ['a', 'b', 'c']
2、清單頭尾增删快,中間增删慢,增删元素是常态
3、元素可重複
4、最多可包含2^32 -1個元素
5、索引同python清單
- 清單常用指令
# 增
1、從清單頭部壓入元素
LPUSH key value1 value2
傳回:list長度
2、從清單尾部壓入元素
RPUSH key value1 value2
傳回:list長度
3、從清單src尾部彈出1個元素,壓入到清單dst的頭部
RPOPLPUSH src dst
傳回:被彈出的元素
4、在清單指定元素後/前插入元素
LINSERT key after|before value newvalue
linsert l1 before a z
傳回:
1,如果指令執行成功,傳回清單的長度
2,如果沒有找到 pivot ,傳回 -1
3,如果 key 不存在或為空清單,傳回 0
# 查
5、檢視清單中元素
lrange
LRANGE key start stop
# 檢視清單中所有元素: LRANGE key 0 -1
6、擷取清單長度
LLEN key
# 删
7、從清單頭部彈出1個元素
LPOP key
8、從清單尾部彈出1個元素
RPOP key
9、清單頭部,阻塞彈出,清單為空時阻塞
BLPOP key timeout
10、清單尾部,阻塞彈出,清單為空時阻塞
BRPOP key timeout
# 關于BLPOP 和 BRPOP
1、如果彈出的清單不存在或者為空,就會阻塞
2、逾時時間設定為0,就是永久阻塞,直到有資料可以彈出
3、如果多個用戶端阻塞再同一個清單上,使用First In First Service原則,先到先服務
11、删除指定元素
LREM key count value
count>0:表示從頭部開始向表尾搜尋,移除與value相等的元素,數量為count
count<0:表示從尾部開始向表頭搜尋,移除與value相等的元素,數量為count
count=0:移除表中所有與value相等的值
傳回:被移除元素的數量
12、保留指定範圍内的元素
LTRIM key start stop
傳回:ok
樣例:
LTRIM mylist1 0 2 # 隻保留前3條
# 應用場景: 儲存微網誌評論最後500條
LTRIM weibo:comments 0 499
# 改
13、将清單 key 下标為 index 的元素的值設定為 value
LSET key index newvalue
練習
1、檢視所有的鍵
#keys *
2、向清單 spider:urls 中以RPUSH放入如下幾個元素:01_baidu.com、02_taobao.com、03_sina.com、04_jd.com、05_xxx.com
#rpush spider:urls 01_baidu.com 02_taobao.com 03_sina.com 04_jd.com 05_xxx.com
3、檢視清單中所有元素
#lrange spider:urls 0 -1
4、檢視清單長度
#llen spider:urls
5、将清單中01_baidu.com 改為 01_tmall.com
#lset spider:urls 0 01_tmall.com
6、在清單中04_jd.com之後再加1個元素 02_taobao.com
#linsert spider:urls after 04_jd.com 02_taobao.com
7、彈出清單中的最後一個元素
# rpop
8、删除清單中所有的 02_taobao.com
# lrem spider:urls 0 02_taobao.com
9、剔除清單中的其他元素,隻剩前3條
# ltrim spider:urls 0 2
python互動redis
- 子產品(redis)
Ubuntu
sudo pip3 install redis
- 使用流程
import redis
# 建立資料庫連接配接對象
r = redis.Redis(host='127.0.0.1',port=6379,db=0,password='123456')
- 通用指令代碼示例
import redis
#生成連接配接對象
r = redis.Redis(host='127.0.0.1', port=6379, db=0, password='123456')
#無密碼
#r = redis.Redis(host='127.0.0.1', port=6379, db=0)
#基礎通用指令
#key_list = r.keys('*')
#[b'u2', b'username', b'username5', b'l1', b'u1', b'u3', b'z4', b'u4']
#print(key_list)
#print(r.exists('u1'))
#print(r.delete('u1'))
- python操作list
#r.lpush('pyl1', 'a', 'b', 'c', 'd')
#[b'd', b'c', b'b', b'a']
#print(r.lrange('pyl1', 0, -1))
#print(r.rpop('pyl1'))
#print(r.ltrim('pyl1', 0, 1))
#print(r.lrange('pyl1',0, -1))
list案例: 一個程序負責生産任務,一個程序負責消費任務
程序1: 生産者
#生産者
import redis
r = redis.Redis(host='127.0.0.1', port=6379, db=0, password='123456')
# 任務類别/收件人/發件人/内容
s = '%s_%s_%s_%s'%('sendEmail', '[email protected]', '[email protected]','hahaha')
#任務發到redis的原則 先進先出[lpush, brpop]
r.lpush('pylt1', s)
程序2: 消費者
#消費者
import redis
r = redis.Redis(host='127.0.0.1', port=6379, db=0, password='123456')
while True:
task = r.brpop('pylt1', 10)
#task : (b'pylt1', b'[email protected][email protected]_hahaha')
print(task)
if task:
task_data = task[1]
task_str = task_data.decode()
task_list = task_str.split('_')
print('--receiver task, task type is %s'%(task_list[0]))
else:
print('--no task---')
- python操作string
# r.set('pys1', 'guoxiaonao')
# print(r.get('pys1'))
#r.mset({'pys2':'guo', 'pys3':'xiao'})
#[b'guo', b'xiao']
#print(r.mget('pys2','pys3'))
#print(r.incr('pys6'))
#print(r.incrby('pys6',10))
淘汰政策
1,主動出擊
1,将帶過期時間的key存到一個獨立的字典中
預設每100毫秒進行一次過期掃描
1,在過期字典中随機 20個 key
2,檢查過期時間,删除已過期的key
3, 如果過期key 比例 超過 1/4 重複 1-3
預設25ms 逾時時間, 避免掃描卡死
問題: 大量key同時過期,redis會有卡頓現象
解決方案: set key value ex 1000 + random.ranint(1,100)
2,惰性删除
1, get 【檢查key的過期時間, key過期,直接删除】
2, set maxmemory檢查
noeviction 拒接寫服務,可接受讀請求 - 預設配置
volatile-lru 嘗試淘汰設定了過期時間的key, [最少使用原則]
allkeys-lru 嘗試淘汰所有key [最少使用原則]
redis_day02筆記
位圖操作bitmap
定義
1、位圖不是真正的資料類型,它是定義在字元串類型中
2、一個字元串類型的值最多能存儲512M位元組的内容,位上限:2^32
# 1MB = 1024KB
# 1KB = 1024Byte(位元組)
# 1Byte = 8bit(位)
1_login_20200518 : 1
2_login_20200518 : 1
1_login: [20200518, 20200605]
1_login: 1100000000100
強勢點
可以實時的進行統計,極其節省空間。官方在模拟1億2千8百萬使用者的模拟環境下,在一台MacBookPro上,典型的統計如“日使用者數”的時間消耗小于50ms, 占用16MB記憶體
SETBIT 指令
- 說明:設定某位置上的二進制值
- 文法:SETBIT key offset value
-
參數:offset - 偏移量 從0開始
value - 0或者1
- 示例:
# 預設擴充位以0填充
127.0.0.1:6379> SET mykey ab
OK
127.0.0.1:6379> GET mykey
"ab"
127.0.0.1:6379> SETBIT mykey 0 1
(integer) 0
127.0.0.1:6379> GET mykey
"\xe1b"
127.0.0.1:6379>
GETBIT 指令
- 說明:擷取某一位上的值
- 文法:GETBIT key offset
- 示例:
127.0.0.1:6379> GETBIT mykey 3
(integer) 0
127.0.0.1:6379> GETBIT mykey 0
(integer) 1
127.0.0.1:6379>
BITCOUNT 指令
- 說明:統計鍵所對應的值中有多少個 1
- 文法:BITCOUNT key start end
- 參數:start/end 代表的是 位元組索引
- 示例:
127.0.0.1:6379> SET mykey1 ab
OK
127.0.0.1:6379[4]> BITCOUNT mykey
(integer) 6
127.0.0.1:6379[4]> BITCOUNT mykey 0 0
(integer) 3
應用場景案例
# 網站使用者的上線次數統計(尋找活躍使用者)
使用者名為key,上線的天作為offset,上線設定為1
# 示例
使用者名為 user1:login 的使用者,今年第1天上線,第30天上線
SETBIT user1:login 0 1
SETBIT user1:login 29 1
BITCOUNT user1:login
代碼實作
r.setbit('key', 索引位, 1/0)
登陸
r.setbit('1_login_2020', 4 ,1)
注冊:
r.lpush('users', '使用者id')
#篩選出 注冊使用者中, 2020年登入次數超過100次的玩家,發放獎品
for user_id in lrange('users', 0, -1):
key = '%s_login_2020'%(user_id)
login_count = r.bitcount(key)
if login_count > 1:
符号要求
Hash散列資料類型
- 定義
1、由field和關聯的value組成的鍵值對
2、field和value是字元串類型
3、一個hash中最多包含2^32-1個鍵值對 (約43億)
- 優點
1、節約記憶體空間 - 特定條件下 【1,字段小于512個,2:value不能超過64位元組】
2、可按需擷取字段的值
- 缺點(不适合hash情況)
1,使用過期鍵功能:鍵過期功能隻能對鍵進行過期操作,而不能對散列的字段進行過期操作
2,存儲消耗大于字元串結構
- 基本指令操作
# 1、設定單個字段
HSET key field value
HSETNX key field value
# 2、設定多個字段
HMSET key field1 value field2 value
# 3、傳回字段個數
HLEN key
# 4、判斷字段是否存在(不存在傳回0)
HEXISTS key field
# 5、傳回字段值
HGET key field
# 6、傳回多個字段值
HMGET key field filed
# 7、傳回所有的鍵值對
HGETALL key
# 8、傳回所有字段名
HKEYS key
# 9、傳回所有值
HVALS key
# 10、删除指定字段
HDEL key field
# 11、在字段對應值上進行整數增量運算
HINCRBY key filed increment
# 12、在字段對應值上進行浮點數增量運算
HINCRBYFLOAT key field increment
python操作hash
# 1、更新一條資料的屬性,沒有則建立
hset(name, key, value)
# 2、讀取這條資料的指定屬性, 傳回字元串類型
hget(name, key)
# 3、批量更新資料(沒有則建立)屬性,參數為字典
hmset(name, mapping)
# 4、批量讀取資料(沒有則建立)屬性
hmget(name, keys)
# 5、擷取這條資料的所有屬性和對應的值,傳回字典類型
hgetall(name)
# 6、擷取這條資料的所有屬性名,傳回清單類型
hkeys(name)
# 7、删除這條資料的指定屬性
hdel(name, *keys)
Python代碼hash散列
#r.hset('pyh8', 'uname', 'wangweichao')
#{b'uname': b'wangweichao'}
#print(r.hgetall('pyh8'))
#r.hmset('pyh8',{'age':22,'desc':'spider'})
#print(r.hgetall('pyh8'))
應用場景:使用者次元資料統計
使用者次元統計
統計數包括:關注數、粉絲數、喜歡商品數、發帖數
使用者為key,不同次元為field,value為統計數
比如關注了5人
HSET user:10000 fans 5
HINCRBY user:10000 fans 1
應用場景: 緩存 - redis+mysql+hash組合使用
- 原理
使用者想要查詢個人資訊 1、到redis緩存中查詢個人資訊 2、redis中查詢不到,到mysql查詢,并緩存到redis 3、再次查詢個人資訊
- 代碼實作
部落格 個人首頁 項目 amysite1 資料庫 amysite1 應用user class User username - char 使用者 age - int 個人首頁 /user/detail/1 緩存思想: 1,先找緩存中有沒有, 2,緩存沒有 - 去查資料庫/存儲緩存 ,3 緩存有資料則直接傳回 return 'username %s age %s' 更新請求 /user/update/<int:user_id> /user/update/1?age=20 更新mysql中的age 删除redis緩存資料 from django.http import HttpResponse from django.shortcuts import render from .models import User import redis # Create your views here. r = redis.Redis(host='127.0.0.1', port=6379, db=0, password='123456') def user_detail(request, user_id): #1,先查緩存 # 沒有: 資料庫 -> 資料回寫緩存 # 有: 傳回緩存内容 cache_key = 'user:%s'%(user_id) if r.exists(cache_key): data = r.hgetall(cache_key) #{b'username':b'guoxiaonao', b'age':b'20'} new_data = {k.decode():v.decode() for k,v in data.items()} username = new_data['username'] age = new_data['age'] html = 'Cache username is %s age is %s'%(username, age) return HttpResponse(html) #無緩存時 try: user = User.objects.get(id=user_id) except Exception as e: print(e) return HttpResponse('--no user') username = user.username age = user.age html = 'username is %s age is %s' % (username, age) #更新緩存 r.hmset(cache_key, {'username':username, 'age':age}) r.expire(cache_key, 60) return HttpResponse(html) def user_update(request, user_id): #/user/update/1?age=30 age = request.GET.get('age', 0) try: user = User.objects.get(id=user_id) except Exception as e: return HttpResponse('--no user') user.age = age user.save() #删除緩存 cache_key = 'user:%s'%(user_id) r.delete(cache_key) return HttpResponse('--update is ok--')
集合資料類型(set)
- 特點
1、無序、去重
2、元素是字元串類型
3、最多包含2^32-1個元素
- 基本指令
# 1、增加一個或者多個元素,自動去重;傳回值為成功插入到集合的元素個數
SADD key member1 member2
# 2、檢視集合中所有元素
SMEMBERS key
# 3、删除一個或者多個元素,元素不存在自動忽略
SREM key member1 member2
# 4、元素是否存在
SISMEMBER key member
# 5、随機傳回集合中指定個數的元素,預設為1個
SRANDMEMBER key [count]
# 6、彈出成員
SPOP key [count]
# 7、傳回集合中元素的個數,不會周遊整個集合,隻是存儲在鍵當中了
SCARD key
# 8、把元素從源集合移動到目标集合
SMOVE source destination member
# 9、差集(number1 1 2 3 number2 1 2 4 結果為3)
SDIFF key1 key2
# 10、差集儲存到另一個集合中
SDIFFSTORE destination key1 key2
# 11、交集
SINTER key1 key2
SINTERSTORE destination key1 key2
# 11、并集
SUNION key1 key2
SUNIONSTORE destination key1 key2
案例: 新浪微網誌的共同關注
# 需求: 當使用者通路另一個使用者的時候,會顯示出兩個使用者共同關注過哪些相同的使用者
# 設計: 将每個使用者關注的使用者放在集合中,求交集即可
# 實作:
user001 = {'peiqi','qiaozhi','danni'}
user002 = {'peiqi','qiaozhi','lingyang'}
user001和user002的共同關注為:
SINTER user001 user002
結果為: {'peiqi','qiaozhi'}
python操作set
#r.sadd('pyset1', 'tom', 'jack')
#{b'jack', b'tom'}
#print(r.smembers('pyset1'))
#r.sadd('pyset2', 'tom', 'lily', 'xixi')
#{b'tom'}
print(r.sinter('pyset1', 'pyset2'))
有序集合sortedset
- 特點
1、有序、去重
2、元素是字元串類型
3、每個元素都關聯着一個浮點數分值(score),并按照分值從小到大的順序排列集合中的元素(分值可以相同)
4、最多包含2^32-1元素
-
示例
一個儲存了水果價格的有序集合
分值 | 2.0 | 4.0 | 6.0 | 8.0 | 10.0 |
---|---|---|---|---|---|
元素 | 西瓜 | 葡萄 | 芒果 | 香蕉 | 蘋果 |
一個儲存了員工薪水的有序集合
分值 | 6000 | 8000 | 10000 | 12000 |
---|---|---|---|---|
元素 | lucy | tom | jim | jack |
一個儲存了正在閱讀某些技術書的人數
分值 | 300 | 400 | 555 | 666 | 777 |
---|---|---|---|---|---|
元素 | 核心程式設計 | 阿凡提 | 本拉登 | 阿姆斯特朗 | 比爾蓋茨 |
- 有序集合常用指令
# 在有序集合中添加一個成員 傳回值為 成功插入到集合中的元素個數
zadd key score member
# 檢視指定區間元素(升序)
zrange key start stop [withscores]
# 檢視指定區間元素(降序)
zrevrange key start stop [withscores]
# 檢視指定元素的分值
zscore key member
# 傳回指定區間元素
# offset : 跳過多少個元素
# count : 傳回幾個
# 小括号 : 開區間 zrangebyscore fruits (2.0 8.0
zrangebyscore key min max [withscores] [limit offset count]
# 每頁顯示10個成員,顯示第5頁的成員資訊:
# limit 40 10
# MySQL: 每頁顯示10條記錄,顯示第5頁的記錄
# limit 40,10
# limit 2,3 顯示: 第3 4 5條記錄
# 删除成員
zrem key member
# 增加或者減少分值
zincrby key increment member
閱讀量
文章id_read_count 普通集合 ip
文章_閱讀量 有序集合
# 傳回元素排名
zrank key member
# 傳回元素逆序排名
zrevrank key member
# 删除指定區間内的元素
zremrangebyscore key min max
# 傳回集合中元素個數
zcard key
# 傳回指定範圍中元素的個數
zcount key min max
zcount salary 6000 8000
zcount salary (6000 8000# 6000<salary<=8000
zcount salary (6000 (8000#6000<salary<8000
# 并集
zunionstore destination numkeys key [weights 權重值] [AGGREGATE SUM|MIN|MAX]
# zunionstore salary3 2 salary salary2 weights 1 0.5 AGGREGATE MAX
# 2代表集合數量,weights之後 權重1給salary,權重0.5給salary2集合,算完權重之後執行聚合AGGREGATE
# 交集:和并集類似,隻取相同的元素
zinterstore destination numkeys key1 key2 weights weight AGGREGATE SUM(預設)|MIN|MAX
python操作sorted set
#r.zadd('pyss1', {'tom':6000,'jim':5000})
#[(b'jim', 5000.0), (b'tom', 6000.0)]
#print(r.zrange('pyss1',0,-1, withscores=True))
#print(r.zrangebyscore('pyss1', '(5000', 7500, withscores=True))
#r.zadd('pyss2', {'tom': 8000})
#r.zinterstore('pyss3',('pyss1','pyss2'), aggregate='max')
#print(r.zrange('pyss3', 0, -1, withscores=True))
redis_day02回顧
五大資料類型及應用場景
類型 | 特點 | 使用場景 |
---|---|---|
string | 簡單key-value類型,value可為字元串和數字 | 正常計數(微網誌數, 粉絲數等功能) |
hash | 是一個string類型的field和value的映射表,hash特别适合用于存儲對象 | 存儲部分可能需要變更的資料(比如使用者資訊) |
list | 有序可重複清單 | 消息隊列等 |
set | 無序不可重複清單 | 存儲并計算關系(如微網誌,關注人或粉絲存放在集合,可通過交集、并集、差集等操作實作如共同關注、共同喜好等功能) |
sorted set | 每個元素帶有分值的集合 | 各種排行榜 |
redis_day03筆記
事務
定義:事務指 程式中一系列嚴密的操作邏輯【sql語句】,所有操作必須全部完成,或者 全部 不完成,不能出現中間狀态
轉賬: 小明轉賬 200 元 -> 小紅
事務的四大特性(ACID)
原子性(Atomicity): 事務中的操作,要麼全都執行成功, 要麼全都不執行
一緻性(Consistency):事務執行始得資料從一個狀态轉換為另一個狀态,這個過程保持完整性
隔離性(Isolation) : 當多個并發通路資料庫是,多個事務之間互相隔離,不能被其他事務操作所幹擾
持久性(Durability): 事務完成後,對于資料的改變 是永久的
特點
1. 單獨的隔離操作:事務中的所有指令會被序列化、按順序執行,在執行的過程中不會被其他用戶端發送來的指令打斷
2. 不保證原子性:redis中的一個事務中如果存在指令執行失敗,那麼其他指令依然會被執行,沒有復原機制
事務指令
1、MULTI # 開啟事務 mysql begin
2、指令1 # 執行指令
3、指令2 ... ...
4、EXEC # 送出到資料庫執行 mysql commit
4、DISCARD # 取消事務 mysql 'rollback'
使用步驟
# 開啟事務
127.0.0.1:6379> MULTI
OK
# 指令1入隊列
127.0.0.1:6379> INCR n1
QUEUED
# 指令2入隊列
127.0.0.1:6379> INCR n2
QUEUED
# 送出到資料庫執行
127.0.0.1:6379> EXEC
1) (integer) 1
2) (integer) 1
事務中指令錯誤處理
# 1、指令文法錯誤,指令入隊失敗,直接自動discard退出這個事務
這個在指令在執行調用之前會發生錯誤。例如,這個指令可能有文法錯誤(錯誤的參數數量,錯誤的指令名)
處理方案:文法錯誤則自動執行discard
案例:
127.0.0.1:6379[7]> MULTI
OK
127.0.0.1:6379[7]> get a
QUEUED
127.0.0.1:6379[7]> getsss a
(error) ERR unknown command 'getsss'
127.0.0.1:6379[7]>
127.0.0.1:6379[7]>
127.0.0.1:6379[7]> EXEC
(error) EXECABORT Transaction discarded because of previous errors.
# 2、指令文法沒錯,但類型操作有誤,則事務執行調用之後失敗,無法進行事務復原
我們執行了一個由于錯誤的value的key操作(例如對着String類型的value施行了List指令操作)
處理方案:發生在EXEC之後的是沒有特殊方式去處理的:即使某些指令在事務中失敗,其他指令都将會被執行。
案例
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set num 10
QUEUED
127.0.0.1:6379> LPOP num
QUEUED
127.0.0.1:6379> exec
1) OK
2) (error) WRONGTYPE Operation against a key holding the wrong kind of value
127.0.0.1:6379> get num
"10"
127.0.0.1:6379>
思考為什麼redis不支援復原?
pipeline 流水線
定義:批量執行redis指令,減少通信io
注意:此為用戶端技術
示例
import redis
# 建立連接配接池并連接配接到redis
pool = redis.ConnectionPool(host = '127.0.0.1',db=0,port=6379)
r = redis.Redis(connection_pool=pool)
pipe = r.pipeline()
pipe.set('fans',50)
pipe.incr('fans')
pipe.incrby('fans',100)
pipe.execute()
性能對比
# 建立連接配接池并連接配接到redis
pool = redis.ConnectionPool(host = '127.0.0.1',db=0,port=6379)
r = redis.Redis(connection_pool=pool)
def withpipeline(r):
p = r.pipeline()
for i in range(1000):
key = 'test1' + str(i)
value = i+1
p.set(key, value)
p.execute()
def withoutpipeline(r):
for i in range(1000):
key = 'test2' + str(i)
value = i+1
r.set(key, value)
python 操作 redis事務
with r.pipeline(transaction=true) as pipe
pipe.multi()
pipe.incr("books")
pipe.incr("books")
values = pipe.execute()
-> "multi incr books incr books exec"
watch - 樂觀鎖
作用: 事務過程中,可對指定key進行監聽,指令送出時,若被監聽key對應的值未被修改時,事務方可送出成功,否則失敗
> watch books
OK
> multi
OK
> incr books
QUEUED
> exec # 事務執行失敗
(nil)
watch之後,再開一個終端進入redis
> incr books # 修改book值
(integer) 1
python操作watch
#同時對一個賬戶進行操作, 目前餘額 * 2
import redis
import time
pool = redis.ConnectionPool(host='127.0.0.1', db=1, port=6379, password='123456')
r = redis.Redis(connection_pool=pool)
def double_account(user_id):
key = 'account_%s'%(user_id)
with r.pipeline(transaction=True) as pipe:
while True:
try:
#pipe.watch指令 調用後 即刻發給伺服器
pipe.watch(key)
value = int(r.get(key))
value *= 2
print('--new value is %s'%(value))
print('--sleep is start')
time.sleep(20)
print('--sleep is over')
pipe.multi()
pipe.set(key, value)
pipe.execute()
break
except redis.WatchError:
print('---value changed')
continue
return int(r.get(key))
if __name__ == '__main__':
#account_guoxiaonao
print(double_account('guoxiaonao'))
資料持久化
持久化定義
将資料從掉電易失的記憶體放到永久存儲的裝置上
為什麼需要持久化
因為所有的資料都在記憶體上,是以必須得持久化
RDB模式(預設開啟)
1、儲存真實的資料
2、将伺服器包含的所有資料庫資料以二進制檔案的形式儲存到硬碟裡面
3、預設檔案名 :/var/lib/redis/dump.rdb
建立rdb檔案的兩種方式
**方式一:**redis終端中使用SAVE或者BGSAVE指令
127.0.0.1:6379> SAVE
OK
# 特點
1、執行SAVE指令過程中,redis伺服器将被阻塞,無法處理用戶端發送的指令請求,在SAVE指令執行完畢後,伺服器才會重新開始處理用戶端發送的指令請求
2、如果RDB檔案已經存在,那麼伺服器将自動使用新的RDB檔案代替舊的RDB檔案
# 工作中定時持久化儲存一個檔案
127.0.0.1:6379> BGSAVE
Background saving started
# 執行過程如下
1、用戶端 發送 BGSAVE 給伺服器
2、伺服器馬上傳回 Background saving started 給用戶端
3、伺服器 fork() 子程序做這件事情
4、伺服器繼續提供服務
5、子程序建立完RDB檔案後再告知Redis伺服器
# 配置檔案相關
/etc/redis/redis.conf
263行: dir /var/lib/redis # 表示rdb檔案存放路徑
253行: dbfilename dump.rdb # 檔案名
# 兩個指令比較
SAVE比BGSAVE快,因為需要建立子程序,消耗額外的記憶體
# 補充:可以通過檢視日志檔案來檢視redis都做了哪些操作
# 日志檔案:配置檔案中搜尋 logfile
logfile /var/log/redis/redis-server.log
方式二:設定配置檔案條件滿足時自動儲存(使用最多)
# redis配置檔案預設
218行: save 900 1
219行: save 300 10
220行: save 60 10000
表示如果距離上一次建立RDB檔案已經過去了300秒,并且伺服器的所有資料庫總共已經發生了不少于10次修改,那麼自動執行BGSAVE指令
1、隻要三個條件中的任意一個被滿足時,伺服器就會自動執行BGSAVE
2、每次建立RDB檔案之後,伺服器為實作自動持久化而設定的時間計數器和次數計數器就會被清零,并重新開始計數,是以多個儲存條件的效果不會疊加
# 該配置項也可以在指令行執行 [不推薦]
redis>save 60 10000
RDB缺點
1、建立RDB檔案需要将伺服器所有的資料庫的資料都儲存起來,這是一個非常消耗資源和時間的操作,是以伺服器需要隔一段時間才建立一個新的RDB檔案,也就是說,建立RDB檔案不能執行的過于頻繁,否則會嚴重影響伺服器的性能
2、可能丢失資料
AOF(AppendOnlyFile)
1、存儲的是指令,而不是真實資料
2、預設不開啟
# 開啟方式(修改配置檔案)
1、sudo vim /etc/redis/redis.conf
672行: appendonly yes # 把 no 改為 yes
676行: appendfilename "appendonly.aof"
2、重新開機服務
sudo /etc/init.d/redis-server restart
AOF持久化原理及優點
# 原理
1、每當有修改資料庫的指令被執行時,
2、因為AOF檔案裡面存儲了伺服器執行過的所有資料庫修改的指令,是以給定一個AOF檔案,伺服器隻要重新執行一遍AOF檔案裡面包含的所有指令,就可以達到還原資料庫的目的
# 優點
使用者可以根據自己的需要對AOF持久化進行調整,讓Redis在遭遇意外停機時不丢失任何資料,或者隻丢失一秒鐘的資料,這比RDB持久化丢失的資料要少的多
特殊說明
# 因為
雖然伺服器執行一個修改資料庫的指令,就會把執行的指令寫入到AOF檔案,但這并不意味着AOF檔案持久化不會丢失任何資料,在目前常見的作業系統中,執行系統調用write函數,将一些内容寫入到某個檔案裡面時,為了提高效率,系統通常不會直接将内容寫入硬碟裡面,而是将内容放入一個記憶體緩存區(buffer)裡面,等到緩沖區被填滿時才将存儲在緩沖區裡面的内容真正寫入到硬碟裡
# 是以
1、AOF持久化:當一條指令真正的被寫入到硬碟裡面時,這條指令才不會因為停機而意外丢失
2、AOF持久化在遭遇停機時丢失指令的數量,取決于指令被寫入到硬碟的時間
3、越早将指令寫入到硬碟,發生意外停機時丢失的資料就越少,反之亦然
政策 - 配置檔案
# 打開配置檔案:/etc/redis/redis.conf,找到相關政策如下
1、701行: alwarys
伺服器每寫入一條指令,就将緩沖區裡面的指令寫入到硬碟裡面,伺服器就算意外停機,也不會丢失任何已經成功執行的指令資料
2、702行: everysec(# 預設)
伺服器每一秒将緩沖區裡面的指令寫入到硬碟裡面,這種模式下,伺服器即使遭遇意外停機,最多隻丢失1秒的資料
3、703行: no
伺服器不主動将指令寫入硬碟,由作業系統決定何時将緩沖區裡面的指令寫入到硬碟裡面,丢失指令數量不确定
# 運作速度比較
always:速度慢
everysec和no都很快,預設值為everysec
AOF重寫
思考:AOF檔案中是否會産生很多的備援指令?
為了讓AOF檔案的大小控制在合理範圍,避免胡亂增長,redis提供了AOF重寫功能,通過這個功能,伺服器可以産生一個新的AOF檔案
-- 新的AOF檔案記錄的資料庫資料和原由的AOF檔案記錄的資料庫資料完全一樣
-- 新的AOF檔案會使用盡可能少的指令來記錄資料庫資料,是以新的AOF檔案的提及通常會小很多
-- AOF重寫期間,伺服器不會被阻塞,可以正常處理用戶端發送的指令請求
示例
原有AOF檔案 | 重寫後的AOF檔案 |
---|---|
select 0 | SELECT 0 |
sadd myset peiqi | SADD myset peiqi qiaozhi danni lingyang |
sadd myset qiaozhi | SET msg ‘hello tarena’ |
sadd myset danni | RPUSH mylist 2 3 5 |
sadd myset lingyang | |
INCR number | |
INCR number | |
DEL number | |
SET message ‘hello world’ | |
SET message ‘hello tarena’ | |
RPUSH mylist 1 2 3 | |
RPUSH mylist 5 | |
LPOP mylist |
AOF重寫-觸發
1、用戶端向伺服器發送BGREWRITEAOF指令
127.0.0.1:6379> BGREWRITEAOF
Background append only file rewriting started
2、修改配置檔案讓伺服器自動執行BGREWRITEAOF指令
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
# 解釋
1、隻有當AOF檔案的增量大于100%時才進行重寫,也就是大一倍的時候才觸發
# 第一次重寫新增:64M
# 第二次重寫新增:128M
# 第三次重寫新增:256M(新增128M)
RDB和AOF持久化對比
RDB持久化 | AOF持久化 |
---|---|
全量備份,一次儲存整個資料庫 | 增量備份,一次儲存一個修改資料庫的指令 |
儲存的間隔較長 | 儲存的間隔預設為一秒鐘 |
資料還原速度快 | 資料還原速度一般,備援指令多,還原速度慢 |
執行SAVE指令時會阻塞伺服器,但手動或者自動觸發的BGSAVE不會阻塞伺服器 | 無論是平時還是進行AOF重寫時,都不會阻塞伺服器 |
資料恢複(無需手動操作)
既有dump.rdb,又有appendonly.aof,恢複時找誰?
先找appendonly.aof
配置檔案常用配置總結
# 設定密碼
1、requirepass password
# 開啟遠端連接配接
2、bind 127.0.0.1 ::1 注釋掉
3、protected-mode no 把預設的 yes 改為 no
# rdb持久化-預設配置
4、dbfilename 'dump.rdb'
5、dir /var/lib/redis
# rdb持久化-自動觸發(條件)
6、save 900 1
7、save 300 10
8、save 60 10000
# aof持久化開啟
9、appendonly yes
10、appendfilename 'appendonly.aof'
# aof持久化政策
11、appendfsync always
12、appendfsync everysec # 預設
13、appendfsync no
# aof重寫觸發
14、auto-aof-rewrite-percentage 100
15、auto-aof-rewrite-min-size 64mb
# 設定為從伺服器
16、salveof <master-ip> <master-port>
Redis相關檔案存放路徑
1、配置檔案: /etc/redis/redis.conf
2、備份檔案: /var/lib/redis/*.rdb|*.aof
3、日志檔案: /var/log/redis/redis-server.log
4、啟動檔案: /etc/init.d/redis-server
# /etc/下存放配置檔案
# /etc/init.d/下存放服務啟動檔案
Redis主從複制
- 定義
1、一個Redis服務可以有多個該服務的複制品,這個Redis服務成為master,其他複制品成為slaves
2、master會一直将自己的資料更新同步給slaves,保持主從同步
3、隻有master可以執行寫指令,slave隻能執行讀指令
- 作用
1,分擔了讀的壓力(高并發),提高服務能力
2,避免單點問題 【如果系統中 一個程序挂掉,整個系統挂掉,即為單點問題】
- 原理
從伺服器執行用戶端發送的讀指令,比如GET、LRANGE、SMEMMBERS、HGET、ZRANGE等等,用戶端可以連接配接slaves執行讀請求,來降低master的讀壓力
- 實作方式
-
方式一(Linux指令行實作)
redis-server --slaveof --masterauth
# 從服務端 redis-server --port 6300 --slaveof 127.0.0.1 6379 # 從用戶端 redis-cli -p 6300 127.0.0.1:6300> keys * # 發現是複制了原6379端口的redis中資料 127.0.0.1:6300> set mykey 123 (error) READONLY You can't write against a read only slave. 127.0.0.1:6300> # 從伺服器隻能讀資料,不能寫資料
- 方式二(Redis指令行實作)
# 兩條指令 1、>slaveof IP PORT 2、>slaveof no one # 服務端啟動 redis-server --port 6301 # 用戶端連接配接 [email protected]:~$ redis-cli -p 6301 127.0.0.1:6301> keys * 1) "myset" 2) "mylist" 127.0.0.1:6301> set mykey 123 OK # 切換為從 127.0.0.1:6301> slaveof 127.0.0.1 6379 OK 127.0.0.1:6301> set newkey 456 (error) READONLY You can't write against a read only slave. 127.0.0.1:6301> keys * 1) "myset" 2) "mylist" # 再切換為主 127.0.0.1:6301> slaveof no one OK 127.0.0.1:6301> set name hello OK
- 方式三(利用配置檔案)
# 每個redis服務,都有1個和他對應的配置檔案 # 兩個redis服務 1、6379 -> /etc/redis/redis.conf 2、6300 -> /home/tarena/redis_6300.conf # 修改配置檔案 vi redis_6300.conf slaveof 127.0.0.1 6379 port 6300 # 啟動redis服務 redis-server redis_6300.conf # 用戶端連接配接測試 redis-cli -p 6300 127.0.0.1:6300> hset user:1 username guods (error) READONLY You can't write against a read only slave.
-
問題:master挂了怎麼辦?
1、一個Master可以有多個Slaves
2、Slave下線,隻是讀請求的處理性能下降
3、Master下線,寫請求無法執行
4、其中一台Slave使用SLAVEOF no one指令成為Master,其他Slaves執行SLAVEOF指令指向這個新的Master,從它這裡同步資料
# 以上過程是手動的,能夠實作自動,這就需要Sentinel哨兵,實作故障轉移Failover操作
示範
1、啟動端口6400redis,設定為6379的slave
redis-server --port 6400
redis-cli -p 6400
redis>slaveof 127.0.0.1 6379
2、啟動端口6401redis,設定為6379的slave
redis-server --port 6401
redis-cli -p 6401
redis>slaveof 127.0.0.1 6379
3、關閉6379redis
sudo /etc/init.d/redis-server stop
4、把6400redis設定為master
redis-cli -p 6400
redis>slaveof no one
5、把6401的redis設定為6400redis的salve
redis-cli -p 6401
redis>slaveof 127.0.0.1 6400
# 這是手動操作,效率低,而且需要時間,有沒有自動的???
Sentinel哨兵
Redis之哨兵 - sentinel
1、Sentinel會不斷檢查Master和Slaves是否正常
2、每一個Sentinel可以監控任意多個Master和該Master下的Slaves
案例示範
**1、**環境搭建
# 共3個redis的服務
1、啟動6379的redis伺服器
sudo /etc/init.d/redis-server start
2、啟動6380的redis伺服器,設定為6379的從
redis-server --port 6380
[email protected]:~$ redis-cli -p 6380
127.0.0.1:6380> slaveof 127.0.0.1 6379
OK
3、啟動6381的redis伺服器,設定為6379的從
redis-server --port 6381
[email protected]:~$ redis-cli -p 6381
127.0.0.1:6381> slaveof 127.0.0.1 6379
**2、**安裝并搭建sentinel哨兵
# 1、安裝redis-sentinel
sudo apt install redis-sentinel
驗證: sudo /etc/init.d/redis-sentinel stop
# 2、建立配置檔案sentinel.conf
port 26379
sentinel monitor tedu 127.0.0.1 6379 1
# 3、啟動sentinel
方式一: redis-sentinel sentinel.conf
方式二: redis-server sentinel.conf --sentinel
#4、将master的redis服務終止,檢視從是否會提升為主
sudo /etc/init.d/redis-server stop
# 發現提升6381為master,其他兩個為從
# 在6381上設定新值,6380檢視
127.0.0.1:6381> set name tedu
OK
# 啟動6379,觀察日志,發現變為了6381的從
主從+哨兵基本就夠用了
sentinel.conf解釋
# sentinel監聽端口,預設是26379,可以修改
port 26379
# 告訴sentinel去監聽位址為ip:port的一個master,這裡的master-name可以自定義,quorum是一個數字,指明當有多少個sentinel認為一個master失效時,master才算真正失效
sentinel monitor <master-name> <ip> <redis-port> <quorum>
#如果master有密碼,則需要添加該配置
sentinel auth-pass <master-name> <password>
#master多久失聯才認為是不可用了,預設是30秒
sentinel down-after-milliseconds <master-name> <milliseconds>
python擷取master
from redis.sentinel import Sentinel
#生成哨兵連接配接
sentinel = Sentinel([('localhost', 26379)], socket_timeout=0.1)
#初始化master連接配接
master = sentinel.master_for('tedu', socket_timeout=0.1, db=1)
slave = sentinel.slave_for('tedu',socket_timeout=0.1, db=1)
#使用redis相關指令
master.set('mymaster', 'yes')
print(slave.get('mymaster'))
我司 以rdb形式 運作redis 1月有餘
這個月期間,由于采用rdb模式,且遇到了幾次伺服器當機【關機】,導緻資料發生了少面積丢失
接到上級訓示,我們要将rdb修改成aof
直接開啟了 redis.conf 配置中的 aof功能 且重新開機了redis
rdb 和 aof 均開啟時, 程序啟動預設找aof檔案 做資料恢複,由于剛啟動aof, aof檔案為空,啟動時以空檔案恢複資料,恢複資料時觸發rdb,回寫rdb
redis配置
【1】修改配置檔案
sudo gedit /etc/redis/redis.conf
修改如下2個内容後儲存退出:
# bind 127.0.0.1 ::1 把此行注釋掉
protected-mode no 把預設的yes改為no
【2】重新開機redis服務
sudo /etc/init.d/redis-server restart
【3】遠端連接配接測試(在遠端機器上)
redis-cli -h IP位址
[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-QBibF9tn-1623680257962)(redis.assets/redis.jpg)]
建立配置檔案sentinel.conf
port 26379
sentinel monitor tedu 127.0.0.1 6379 1
3、啟動sentinel
方式一: redis-sentinel sentinel.conf
方式二: redis-server sentinel.conf --sentinel
#4、将master的redis服務終止,檢視從是否會提升為主
sudo /etc/init.d/redis-server stop
發現提升6381為master,其他兩個為從
在6381上設定新值,6380檢視
127.0.0.1:6381> set name tedu
OK
啟動6379,觀察日志,發現變為了6381的從
主從+哨兵基本就夠用了
sentinel.conf解釋
```python
# sentinel監聽端口,預設是26379,可以修改
port 26379
# 告訴sentinel去監聽位址為ip:port的一個master,這裡的master-name可以自定義,quorum是一個數字,指明當有多少個sentinel認為一個master失效時,master才算真正失效
sentinel monitor <master-name> <ip> <redis-port> <quorum>
#如果master有密碼,則需要添加該配置
sentinel auth-pass <master-name> <password>
#master多久失聯才認為是不可用了,預設是30秒
sentinel down-after-milliseconds <master-name> <milliseconds>
python擷取master
from redis.sentinel import Sentinel
#生成哨兵連接配接
sentinel = Sentinel([('localhost', 26379)], socket_timeout=0.1)
#初始化master連接配接
master = sentinel.master_for('tedu', socket_timeout=0.1, db=1)
slave = sentinel.slave_for('tedu',socket_timeout=0.1, db=1)
#使用redis相關指令
master.set('mymaster', 'yes')
print(slave.get('mymaster'))
我司 以rdb形式 運作redis 1月有餘
這個月期間,由于采用rdb模式,且遇到了幾次伺服器當機【關機】,導緻資料發生了少面積丢失
接到上級訓示,我們要将rdb修改成aof
直接開啟了 redis.conf 配置中的 aof功能 且重新開機了redis
rdb 和 aof 均開啟時, 程序啟動預設找aof檔案 做資料恢複,由于剛啟動aof, aof檔案為空,啟動時以空檔案恢複資料,恢複資料時觸發rdb,回寫rdb
redis配置
【1】修改配置檔案
sudo gedit /etc/redis/redis.conf
修改如下2個内容後儲存退出:
# bind 127.0.0.1 ::1 把此行注釋掉
protected-mode no 把預設的yes改為no
【2】重新開機redis服務
sudo /etc/init.d/redis-server restart
【3】遠端連接配接測試(在遠端機器上)
redis-cli -h IP位址
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsICM38FdsYkRGZkRG9lcvx2bjxiNx8VZ6l2csgXUE1UeBpWTmB3MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZwpmLyYTN1ADOxIjM0EjNwEjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)