Redis-基礎(chǔ)

Redis介紹

  • 特點(diǎn)及優(yōu)點(diǎn)
1、開源的,使用C編寫,基于內(nèi)存且支持持久化
2、高性能的Key-Value的NoSQL數(shù)據(jù)庫
3、支持?jǐn)?shù)據(jù)類型豐富,字符串strings,散列hashes,列表lists,集合sets,有序集合sorted sets 等等
4、支持多種編程語言(C C++ Python Java PHP ... )
5、單進(jìn)程單線程
  • 與其他數(shù)據(jù)庫對比
1、MySQL : 關(guān)系型數(shù)據(jù)庫,表格,基于磁盤,慢
2、MongoDB:鍵值對文檔型數(shù)據(jù)庫,值為類似JSON文檔,數(shù)據(jù)結(jié)構(gòu)相對單一
3、Redis的誕生是為了解決什么問題??
   # 解決硬盤IO帶來的性能瓶頸
  • 應(yīng)用場景
1,緩存
2,并發(fā)計(jì)數(shù)
3,排行榜
4,生產(chǎn)者消費(fèi)者模型
...
  • redis版本
1、最新版本:6
2、常用版本:2.4、2.6、2.8、3.0(里程碑)、3.2、3.4、4.0(教學(xué)環(huán)境版本)、5.0
  • Redis附加功能
1、持久化
  將內(nèi)存中數(shù)據(jù)保存到磁盤中,保證數(shù)據(jù)安全,方便進(jìn)行數(shù)據(jù)備份和恢復(fù)
2、過期鍵功能
   為鍵設(shè)置一個(gè)過期時(shí)間,讓它在指定時(shí)間內(nèi)自動刪除
   <節(jié)省內(nèi)存空間>
   # 音樂播放器,日播放排名,過期自動刪除
3、事務(wù)功能
   原子的執(zhí)行多個(gè)操作
4、主從復(fù)制
5、Sentinel哨兵

安裝

  • Ubuntu
# 安裝
sudo apt-get install redis-server
# 服務(wù)端啟動
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
  • 設(shè)置連接密碼
1、requirepass 密碼
2、重啟服務(wù)
   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
  • 允許遠(yuǎn)程連接
1、注釋掉本地IP地址綁定
  69行: # bind 127.0.0.1 ::1
2、關(guān)閉保護(hù)模式(把yes改為no)
  88行: protected-mode no
3、重啟服務(wù)
  sudo /etc/init.d/redis-server restart
  • 通用命令 ==適用于所有數(shù)據(jù)類型==
# 切換庫(number的值在0-15之間,db0 ~ db15)
select number
# 查看鍵
keys 表達(dá)式  # keys *
# 數(shù)據(jù)類型
type key
# 鍵是否存在
exists key
# 刪除鍵
del key
# 鍵重命名
rename key newkey
# 清除當(dāng)前庫中所有數(shù)據(jù)(慎用)
flushdb
# 清除所有庫中所有數(shù)據(jù)(慎用)
flushall

數(shù)據(jù)類型

字符串類型(string)

  • 特點(diǎn)
1、字符串、數(shù)字,都會轉(zhuǎn)為字符串來存儲
2、以二進(jìn)制的方式存儲在內(nèi)存中
  • 字符串常用命令-==必須掌握==
# 1. 設(shè)置一個(gè)key-value
set key value
# 2. 獲取key的值
get key
# 3. key不存在時(shí)再進(jìn)行設(shè)置(nx)
set key value nx  # not exists
# 4. 設(shè)置過期時(shí)間(ex)
set key value ex seconds

# 5. 同時(shí)設(shè)置多個(gè)key-value
mset key1 value1 key2 value2 key3 value3
# 6. 同時(shí)獲取多個(gè)key-value
mget key1 key2 key3 
  • 字符串常用命令-==作為了解==
# 1.獲取長度
strlen key
# 2.獲取指定范圍切片內(nèi)容 [包含start stop]
getrange key start stop
# 3.從索引值開始,value替換原內(nèi)容
setrange key index value
  • 數(shù)值操作-==字符串類型數(shù)字(必須掌握)==
# 整數(shù)操作
incrby key 步長
decrby key 步長
incr key : +1操作
decr key : -1操作
# 應(yīng)用場景: 抖音上有人關(guān)注你了,是不是可以用INCR呢,如果取消關(guān)注了是不是可以用DECR
# 浮點(diǎn)數(shù)操作: 自動先轉(zhuǎn)為數(shù)字類型,然后再進(jìn)行相加減,不能使用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 
# 返回舊值并設(shè)置新值(如果鍵不存在,就創(chuàng)建并賦值)
7、getset key value
# 數(shù)字操作
7、incrby key 步長
8、decrby key 步長
9、incr key
10、decr key
11、incrbyfloat key number#(可為正數(shù)或負(fù)數(shù))

# 設(shè)置過期時(shí)間的兩種方式
# 方式一
1、set key value ex 3
# 方式二
1、set key value
2、expire key 5 # 秒
3、pexpire key 5 # 毫秒
# 查看存活時(shí)間
ttl key
# 刪除過期
persist key
  • string數(shù)據(jù)類型注意
# key命名規(guī)范
可采用 - wang:email
# key命名原則
1、key值不宜過長,消耗內(nèi)存,且在數(shù)據(jù)中查找這類鍵值的計(jì)算成本高
2、不宜過短,可讀性較差
# 值
1、一個(gè)字符串類型的值最多能存儲512M內(nèi)容
  • 業(yè)務(wù)場景
    • 緩存
      • 將mysql中的數(shù)據(jù)存儲到redis字符串類型中
    • 并發(fā)計(jì)數(shù) - 點(diǎn)贊/秒殺
      • 說明:通過redis單進(jìn)程單線程的特點(diǎn),由redis負(fù)責(zé)計(jì)數(shù),并發(fā)問題轉(zhuǎn)為串行問題
    • 帶有效期的驗(yàn)證碼 - 短信驗(yàn)證碼
      • 借助過期時(shí)間,存放驗(yàn)證碼;到期后,自動消亡

練習(xí)

1、查看 db0 庫中所有的鍵
2、設(shè)置鍵 trill:username 對應(yīng)的值為 user001,并查看
3、獲取 trill:username 值的長度
4、一次性設(shè)置 trill:password 、trill:gender、trill:fansnumber 并查看(值自定義)                 
5、查看鍵 trill:score 是否存在
6、增加10個(gè)粉絲
7、增加2個(gè)粉絲(一個(gè)一個(gè)加)
8、有3個(gè)粉絲取消關(guān)注你了
9、又有1個(gè)粉絲取消關(guān)注你了
10、思考、思考、思考...,清除當(dāng)前庫
11、一萬個(gè)思考之后,清除所有庫

答案

1、select 0
   keys *
2、set trill:username  user001
   get  trill:username
3、strlen  trill:username
4、mset trill:password 123 trill:gender m trill:fansnumber 1000
   mget trill:password  trill:gender  trill:fansnumber           
5、exists trill:score
6、incrby  trill:fansnumber 10
7、incr trill:fansnumber 
   incr trill:fansnumber 
8、decrby trill:fansnumber 3
9、decr trill:fansnumber
10、flushdb
11、flushall

列表數(shù)據(jù)類型(List)

  • 特點(diǎn)
1、元素是字符串類型
2、列表頭尾增刪快,中間增刪慢,增刪元素是常態(tài)
3、元素可重復(fù)
4、最多可包含2^32 -1個(gè)元素
5、索引同python列表
  • 列表常用命令
# 增
1、從列表頭部壓入元素
    LPUSH key value1 value2 
    返回:list長度
2、從列表尾部壓入元素
    RPUSH key value1 value2
    返回:list長度
3、從列表src尾部彈出1個(gè)元素,壓入到列表dst的頭部
    RPOPLPUSH src dst
    返回:被彈出的元素
4、在列表指定元素后/前插入元素
    LINSERT key after|before value newvalue
    返回:
        1,如果命令執(zhí)行成功,返回列表的長度
        2,如果沒有找到 pivot ,返回 -1
        3,如果 key 不存在或?yàn)榭樟斜?,返?0 

# 查
5、查看列表中元素
    LRANGE key start stop
  # 查看列表中所有元素: LRANGE key 0 -1
6、獲取列表長度
    LLEN key

# 刪
7、從列表頭部彈出1個(gè)元素
    LPOP key
8、從列表尾部彈出1個(gè)元素
    RPOP key
9、列表頭部,阻塞彈出,列表為空時(shí)阻塞
    BLPOP key timeout
10、列表尾部,阻塞彈出,列表為空時(shí)阻塞
    BRPOP key timeout
  # 關(guān)于BLPOP 和 BRPOP
    1、如果彈出的列表不存在或者為空,就會阻塞
    2、超時(shí)時(shí)間設(shè)置為0,就是永久阻塞,直到有數(shù)據(jù)可以彈出
    3、如果多個(gè)客戶端阻塞再同一個(gè)列表上,使用First In First Service原則,先到先服務(wù)
11、刪除指定元素
    LREM key count value
    count>0:表示從頭部開始向表尾搜索,移除與value相等的元素,數(shù)量為count
    count<0:表示從尾部開始向表頭搜索,移除與value相等的元素,數(shù)量為count
    count=0:移除表中所有與value相等的值
    返回:被移除元素的數(shù)量
    
12、保留指定范圍內(nèi)的元素
    LTRIM key start stop
    返回:ok
    樣例:
        LTRIM mylist1 0 2 # 只保留前3條
        # 應(yīng)用場景: 保存微博評論最后500條
        LTRIM weibo:comments 0 499
    # 改
13、將列表 key 下標(biāo)為 index 的元素的值設(shè)置為 value
    LSET key index newvalue

練習(xí)

1、查看所有的鍵
2、向列表 spider:urls 中以RPUSH放入如下幾個(gè)元素:01_baidu.com、02_taobao.com、03_sina.com、04_jd.com、05_xxx.com
3、查看列表中所有元素
4、查看列表長度
5、將列表中01_baidu.com 改為 01_tmall.com
6、在列表中04_jd.com之后再加1個(gè)元素 02_taobao.com
7、彈出列表中的最后一個(gè)元素
8、刪除列表中所有的 02_taobao.com
9、剔除列表中的其他元素,只剩前3條

python交互redis

  • 模塊(redis)

Ubuntu

sudo pip3 install redis
  • 使用流程
import redis
# 創(chuàng)建數(shù)據(jù)庫連接對象
r = redis.Redis(host='127.0.0.1',port=6379,db=0,password='123456')
  • 代碼示例
import redis

# 1 創(chuàng)建redis數(shù)據(jù)庫連接對象
r = redis.Redis(host='127.0.0.1',port=6379,db=0)
# 2 使用,很多命令的返回值是字節(jié)串,需要用字符串表示時(shí),調(diào)用decode方法.
# 3.1 通用命令...
print(r.keys('*'))
print(r.exists('name'))
# 3.2 字符串類型的操作
r.set('uname', 'aid2108', 60)
print(r.get('uname').decode())
r.mset({'a': 100, 'b': 200, 'c': 300})
print(r.mget(['a', 'b', 'c']))
# 3.3 列表類型的操作
r.lpush('pylk1',100,200,300)
print(r.lrange('pylk1',0,-1))

list案例: 一個(gè)進(jìn)程負(fù)責(zé)生產(chǎn)任務(wù),一個(gè)進(jìn)程負(fù)責(zé)消費(fèi)任務(wù)

進(jìn)程1: 生產(chǎn)者,product.py

import redis
# 1 創(chuàng)建redis數(shù)據(jù)庫連接對象
r = redis.Redis(password='123456')
# 2.向任務(wù)隊(duì)列中添加任務(wù),使用列表類型
# 任務(wù)格式: 任務(wù)類別_發(fā)送者_(dá)接收者_(dá)內(nèi)容
task = 'sendMail_aid2108_cgg_helloworld'
r.lpush('lst:tasks',task)

進(jìn)程2: 消費(fèi)者,consumer.py

import redis

r = redis.Redis(password='123456')

while True:
    task = r.brpop('lst:tasks',3)
    if task:
        print(task)
        # (b'lst:tasks', b'sendMail_aid2102_mzg_helloworld')
        # 處理任務(wù)
        task_data = task[1].decode()
        print(task_data)
        # sendMail_aid2102_mzg_helloworld
        lst_data = task_data.split('_')
        if lst_data[0] == 'sendMail':
            print('執(zhí)行發(fā)送郵件的任務(wù)...')
    else:
        print('-no task!-')


位圖操作bitmap

定義

1、位圖不是真正的數(shù)據(jù)類型,它是定義在字符串類型中
2、一個(gè)字符串類型的值最多能存儲512M字節(jié)的內(nèi)容,位上限:2^32
# 1MB = 1024KB
# 1KB = 1024Byte(字節(jié))
# 1Byte = 8bit(位)

強(qiáng)勢點(diǎn)

可以實(shí)時(shí)的進(jìn)行統(tǒng)計(jì),極其節(jié)省空間。官方在模擬1億2千8百萬用戶的模擬環(huán)境下,在一臺MacBookPro上,典型的統(tǒng)計(jì)如“日用戶數(shù)”的時(shí)間消耗小于50ms, 占用16MB內(nèi)存

SETBIT 命令

  • 說明:設(shè)置某位置上的二進(jìn)制值

  • 語法:SETBIT key offset value

  • 參數(shù):offset - 偏移量 從0開始

          value - 0或者1
    
  • 示例:

# 默認(rèn)擴(kuò)展位以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 命令

  • 說明:統(tǒng)計(jì)鍵所對應(yīng)的值中有多少個(gè) 1
  • 語法:BITCOUNT key start end
  • 參數(shù):start/end 代表的是 字節(jié)索引
  • 示例:
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

應(yīng)用場景案例

# 網(wǎng)站用戶的上線次數(shù)統(tǒng)計(jì)(尋找活躍用戶)
    用戶名為key,上線的天作為offset,上線設(shè)置為1
# 示例
    用戶名為 user1:login 的用戶,今年第1天上線,第30天上線
    SETBIT user1:login 0 1 
    SETBIT user1:login 29 1
    BITCOUNT user1:login

Hash散列數(shù)據(jù)類型

  • 定義
1、由field和關(guān)聯(lián)的value組成的鍵值對
2、field和value是字符串類型
3、一個(gè)hash中最多包含2^32-1個(gè)鍵值對
  • 優(yōu)點(diǎn)
1、節(jié)約內(nèi)存空間 - 特定條件下 【1,字段小于512個(gè),2:value不能超過64字節(jié)】
2、可按需獲取字段的值
  • 缺點(diǎn)(不適合hash情況)
1,使用過期鍵功能:鍵過期功能只能對鍵進(jìn)行過期操作,而不能對散列的字段進(jìn)行過期操作
2,存儲消耗大于字符串結(jié)構(gòu)
  • 基本命令操作
# 1、設(shè)置單個(gè)字段
HSET key field value
HSETNX key field value
# 2、設(shè)置多個(gè)字段
HMSET key field value field value
# 3、返回字段個(gè)數(shù)
HLEN key
# 4、判斷字段是否存在(不存在返回0)
HEXISTS key field
# 5、返回字段值
HGET key field
# 6、返回多個(gè)字段值
HMGET key field filed
# 7、返回所有的鍵值對
HGETALL key
# 8、返回所有字段名
HKEYS key
# 9、返回所有值
HVALS key
# 10、刪除指定字段
HDEL key field 
# 11、在字段對應(yīng)值上進(jìn)行整數(shù)增量運(yùn)算
HINCRBY key field increment
# 12、在字段對應(yīng)值上進(jìn)行浮點(diǎn)數(shù)增量運(yùn)算
HINCRBYFLOAT key field increment

python操作hash

# 1、更新一條數(shù)據(jù)的屬性,沒有則新建
hset(name, key, value) 
# 2、讀取這條數(shù)據(jù)的指定屬性, 返回字符串類型
hget(name, key)
# 3、批量更新數(shù)據(jù)(沒有則新建)屬性,參數(shù)為字典
hmset(name, mapping)
# 4、批量讀取數(shù)據(jù)(沒有則新建)屬性
hmget(name, keys)
# 5、獲取這條數(shù)據(jù)的所有屬性和對應(yīng)的值,返回字典類型
hgetall(name)
# 6、獲取這條數(shù)據(jù)的所有屬性名,返回列表類型
hkeys(name)
# 7、刪除這條數(shù)據(jù)的指定屬性
hdel(name, *keys)

應(yīng)用場景:用戶維度數(shù)據(jù)統(tǒng)計(jì)

用戶維度統(tǒng)計(jì)
   統(tǒng)計(jì)數(shù)包括:關(guān)注數(shù)、粉絲數(shù)、喜歡商品數(shù)、發(fā)帖數(shù)
   用戶為key,不同維度為field,value為統(tǒng)計(jì)數(shù)
   比如關(guān)注了5人
     HSET user:10000 fans 5
     HINCRBY user:10000 fans 1

python操作hash

import redis

# 創(chuàng)建redis數(shù)據(jù)庫的連接對象
r = redis.Redis(password='123456')

# 操作hash
r.hset('pyhk1', 'username', 'aid2108')
r.hmset('pyhk1', {'age': 18, 'major': 'python'})
print(r.hget('pyhk1', 'username').decode())
print(r.hmget('pyhk1', ['username', 'age']))
print(r.hgetall('pyhk1'))
# 字典推導(dǎo)式
data = {k.decode(): v.decode() for k, v in r.hgetall('pyhk1').items()}
print(data)
r.hdel('pyhk1','age')
print(r.hgetall('pyhk1'))
# 刪除鍵
r.delete('pyhk1')

集合數(shù)據(jù)類型(set)

  • 特點(diǎn)
1、無序、去重
2、元素是字符串類型
3、最多包含2^32-1個(gè)元素
  • 基本命令
# 1、增加一個(gè)或者多個(gè)元素,自動去重;返回值為成功插入到集合的元素個(gè)數(shù)
SADD key member1 member2
# 2、查看集合中所有元素
SMEMBERS key
# 3、刪除一個(gè)或者多個(gè)元素,元素不存在自動忽略
SREM key member1 member2
# 4、元素是否存在
SISMEMBER key member
# 5、隨機(jī)返回集合中指定個(gè)數(shù)的元素,默認(rèn)為1個(gè)
SRANDMEMBER key [count]
# 6、彈出成員
SPOP key [count]
# 7、返回集合中元素的個(gè)數(shù),不會遍歷整個(gè)集合,只是存儲在鍵當(dāng)中了
SCARD key
# 8、把元素從源集合移動到目標(biāo)集合
SMOVE source destination member

# 9、差集(number1 1 2 3 number2 1 2 4 結(jié)果為3)
SDIFF key1 key2 
# 10、差集保存到另一個(gè)集合中
SDIFFSTORE destination key1 key2

# 11、交集
SINTER key1 key2
SINTERSTORE destination key1 key2

# 11、并集
SUNION key1 key2
SUNIONSTORE destination key1 key2

案例: 新浪微博的共同關(guān)注

# 需求: 當(dāng)用戶訪問另一個(gè)用戶的時(shí)候,會顯示出兩個(gè)用戶共同關(guān)注過哪些相同的用戶
# 設(shè)計(jì): 將每個(gè)用戶關(guān)注的用戶放在集合中,求交集即可
# 實(shí)現(xiàn):
    user001 = {'peiqi','qiaozhi','danni'}
    user002 = {'peiqi','qiaozhi','lingyang'}
  
user001和user002的共同關(guān)注為:
    SINTER user001 user002
    結(jié)果為: {'peiqi','qiaozhi'}

python操作set

import redis

r = redis.Redis(password='123456')
'''
   武將: 張飛 許褚 趙云 馬超 周瑜
   文臣: 諸葛亮 周瑜 司馬懿
   結(jié)果: 1.純武將 2.純文臣  3.文武雙全  4.文臣武將
'''
# set集合類型的操作
r.sadd('武將', '張飛', '許褚', '趙云', '馬超', '周瑜')
r.sadd('文臣', '諸葛亮', '周瑜', '司馬懿')
data1 = r.sdiff('武將', '文臣')
result = []
for item in data1:
    result.append(item.decode())
print('純武將:', result)

data2 = r.sdiff('文臣', '武將')
result = []
for item in data2:
    result.append(item.decode())
print('純文臣:', result)

data3 = r.sinter('文臣', '武將')
result = []
for item in data3:
    result.append(item.decode())
print('文武雙全:', result)

data4 = r.sunion('文臣', '武將')
result = []
for item in data4:
    result.append(item.decode())
print('文臣武將:', result)

有序集合sortedset

  • 特點(diǎn)
1、有序、去重
2、元素是字符串類型
3、每個(gè)元素都關(guān)聯(lián)著一個(gè)浮點(diǎn)數(shù)分值(score),并按照分值從小到大的順序排列集合中的元素(分值可以相同)
4、最多包含2^32-1元素
  • 示例

    一個(gè)保存了水果價(jià)格的有序集合

分值 2.0 4.0 6.0 8.0 10.0
元素 西瓜 葡萄 芒果 香蕉 蘋果
**一個(gè)保存了員工薪水的有序集合**
分值 6000 8000 10000 12000
元素 lucy tom jim jack
**一個(gè)保存了正在閱讀某些技術(shù)書的人數(shù)**
分值 300 400 555 666 777
元素 核心編程 阿凡提 本拉登 阿姆斯特朗 比爾蓋茨
  • 有序集合常用命令
# 在有序集合中添加一個(gè)成員 返回值為 成功插入到集合中的元素個(gè)數(shù)
zadd key score member
# 查看指定區(qū)間元素(升序)
zrange key start stop [withscores]
# 查看指定區(qū)間元素(降序)
zrevrange key start stop [withscores]
# 查看指定元素的分值
zscore key member

# 返回指定區(qū)間元素
# offset : 跳過多少個(gè)元素
# count : 返回幾個(gè)
# 小括號 : 開區(qū)間  zrangebyscore fruits (2.0 8.0
zrangebyscore key min max [withscores] [limit offset count]
# 每頁顯示10個(gè)成員,顯示第5頁的成員信息: 
# limit 40 10
# MySQL: 每頁顯示10條記錄,顯示第5頁的記錄
# limit 40,10
# limit 2,3   顯示: 第3 4 5條記錄

# 刪除成員
zrem key member
# 增加或者減少分值
zincrby key increment member
# 返回元素排名
zrank key member
# 返回元素逆序排名
zrevrank key member
# 刪除指定區(qū)間內(nèi)的元素
zremrangebyscore key min max
# 返回集合中元素個(gè)數(shù)
zcard key
# 返回指定范圍中元素的個(gè)數(shù)
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 權(quán)重值] [AGGREGATE SUM|MIN|MAX]
# zunionstore salary3 2 salary salary2 weights 1 0.5 AGGREGATE MAX
# 2代表集合數(shù)量,weights之后 權(quán)重1給salary,權(quán)重0.5給salary2集合,算完權(quán)重之后執(zhí)行聚合AGGREGATE
                     
# 交集:和并集類似,只取相同的元素
zinterstore destination numkeys key1 key2 weights weight AGGREGATE SUM(默認(rèn))|MIN|MAX

python操作sorted set

import redis

r = redis.Redis(password='123456')

# 有序集合類型的操作
r.zadd('pyzk1', {'tedu': 100, 'tedu2': 200})
print(r.zrange('pyzk1', 0, -1, withscores=True))
r.zadd('pyzk2', {'tedu2': 200, 'tedu3': 200})
# 并集運(yùn)算
r.zunionstore('pyzk3',['pyzk1','pyzk2'],aggregate='sum')
print(r.zrange('pyzk3', 0, -1, withscores=True))
# 并集運(yùn)算(帶權(quán)重)
r.zunionstore('pyzk4',{'pyzk1':0.8,'pyzk2':0.2},
              aggregate='sum')
print(r.zrange('pyzk4', 0, -1, withscores=True))


五大數(shù)據(jù)類型及應(yīng)用場景

類型 特點(diǎn) 使用場景
string 簡單key-value類型,value可為字符串和數(shù)字 常規(guī)計(jì)數(shù)(微博數(shù), 粉絲數(shù)等功能)
hash 是一個(gè)string類型的field和value的映射表,hash特別適合用于存儲對象 存儲部分可能需要變更的數(shù)據(jù)(比如用戶信息)
list 有序可重復(fù)列表 消息隊(duì)列等
set 無序不可重復(fù)列表 存儲并計(jì)算關(guān)系(如微博,關(guān)注人或粉絲存放在集合,可通過交集、并集、差集等操作實(shí)現(xiàn)如共同關(guān)注、共同喜好等功能)
sorted set 每個(gè)元素帶有分值的集合 各種排行榜


事務(wù)

特點(diǎn)

1. 單獨(dú)的隔離操作:事務(wù)中的所有命令會被序列化、按順序執(zhí)行,在執(zhí)行的過程中不會被其他客戶端發(fā)送來的命令打斷
2. 不保證原子性:redis中的一個(gè)事務(wù)中如果存在命令執(zhí)行失敗,那么其他命令依然會被執(zhí)行,沒有回滾機(jī)制

事務(wù)命令

1、MULTI  # 開啟事務(wù)          mysql   begin
2、命令1  # 執(zhí)行命令          
3、命令2 ... ...
4、EXEC  # 提交到數(shù)據(jù)庫執(zhí)行    mysql   commit
4、DISCARD # 取消事務(wù)         mysql  'rollback'

使用步驟

# 開啟事務(wù)
127.0.0.1:6379> MULTI
OK
# 命令1入隊(duì)列
127.0.0.1:6379> INCR n1
QUEUED
# 命令2入隊(duì)列
127.0.0.1:6379> INCR n2
QUEUED
# 提交到數(shù)據(jù)庫執(zhí)行
127.0.0.1:6379> EXEC
1) (integer) 1
2) (integer) 1

事務(wù)中命令錯(cuò)誤處理

# 1、命令語法錯(cuò)誤,命令入隊(duì)失敗,直接自動discard退出這個(gè)事務(wù)
  這個(gè)在命令在執(zhí)行調(diào)用之前會發(fā)生錯(cuò)誤。例如,這個(gè)命令可能有語法錯(cuò)誤(錯(cuò)誤的參數(shù)數(shù)量,錯(cuò)誤的命令名)
  處理方案:語法錯(cuò)誤則自動執(zhí)行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、命令語法沒錯(cuò),但類型操作有誤,則事務(wù)執(zhí)行調(diào)用之后失敗,無法進(jìn)行事務(wù)回滾
   我們執(zhí)行了一個(gè)由于錯(cuò)誤的value的key操作(例如對著String類型的value施行了List命令操作) 
   處理方案:發(fā)生在EXEC之后的是沒有特殊方式去處理的:即使某些命令在事務(wù)中失敗,其他命令都將會被執(zhí)行。

案例
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 流水線

定義:批量執(zhí)行redis命令,減少通信io

注意:此為客戶端技術(shù)

示例

import redis
# 創(chuàng)建連接池并連接到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()

性能對比

# 創(chuàng)建連接池并連接到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事務(wù)

with r.pipeline(transaction=true) as pipe
    pipe.multi()
    pipe.incr("books")
    pipe.incr("books")
    values = pipe.execute()

watch - 樂觀鎖

作用: 事務(wù)過程中,可對指定key進(jìn)行監(jiān)聽,命令提交時(shí),若被監(jiān)聽key對應(yīng)的值未被修改時(shí),事務(wù)方可提交成功,否則失敗

> watch books
OK
> multi
OK
> incr books
QUEUED
> exec  # 事務(wù)執(zhí)行失敗
(nil)


watch之后,再開一個(gè)終端進(jìn)入redis
> incr books  # 修改book值
(integer) 1


python操作watch

#同時(shí)對一個(gè)賬戶進(jìn)行操作, 當(dāng)前余額 * 2

數(shù)據(jù)持久化

持久化定義

將數(shù)據(jù)從掉電易失的內(nèi)存放到永久存儲的設(shè)備上

為什么需要持久化

因?yàn)樗械臄?shù)據(jù)都在內(nèi)存上,所以必須得持久化

RDB模式(默認(rèn)開啟)

1、保存真實(shí)的數(shù)據(jù)
2、將服務(wù)器包含的所有數(shù)據(jù)庫數(shù)據(jù)以二進(jìn)制文件的形式保存到硬盤里面
3、默認(rèn)文件名 :/var/lib/redis/dump.rdb

創(chuàng)建rdb文件的兩種方式

方式一:redis終端中使用SAVE或者BGSAVE命令

127.0.0.1:6379> SAVE
OK
# 特點(diǎn)
1、執(zhí)行SAVE命令過程中,redis服務(wù)器將被阻塞,無法處理客戶端發(fā)送的命令請求,在SAVE命令執(zhí)行完畢后,服務(wù)器才會重新開始處理客戶端發(fā)送的命令請求
2、如果RDB文件已經(jīng)存在,那么服務(wù)器將自動使用新的RDB文件代替舊的RDB文件
# 工作中定時(shí)持久化保存一個(gè)文件

127.0.0.1:6379> BGSAVE
Background saving started
# 執(zhí)行過程如下
1、客戶端 發(fā)送 BGSAVE 給服務(wù)器
2、服務(wù)器馬上返回 Background saving started 給客戶端
3、服務(wù)器 fork() 子進(jìn)程做這件事情
4、服務(wù)器繼續(xù)提供服務(wù)
5、子進(jìn)程創(chuàng)建完RDB文件后再告知Redis服務(wù)器

# 配置文件相關(guān)
/etc/redis/redis.conf
263行: dir /var/lib/redis # 表示rdb文件存放路徑
253行: dbfilename dump.rdb  # 文件名

# 兩個(gè)命令比較
SAVE比BGSAVE快,因?yàn)樾枰獎(jiǎng)?chuàng)建子進(jìn)程,消耗額外的內(nèi)存

# 補(bǔ)充:可以通過查看日志文件來查看redis都做了哪些操作
# 日志文件:配置文件中搜索 logfile
logfile /var/log/redis/redis-server.log

方式二:設(shè)置配置文件條件滿足時(shí)自動保存(使用最多)

# redis配置文件默認(rèn)
218行: save 900 1
219行: save 300 10
    表示如果距離上一次創(chuàng)建RDB文件已經(jīng)過去了300秒,并且服務(wù)器的所有數(shù)據(jù)庫總共已經(jīng)發(fā)生了不少于10次修改,那么自動執(zhí)行BGSAVE命令
220行: save 60 10000
  1、只要三個(gè)條件中的任意一個(gè)被滿足時(shí),服務(wù)器就會自動執(zhí)行BGSAVE
  2、每次創(chuàng)建RDB文件之后,服務(wù)器為實(shí)現(xiàn)自動持久化而設(shè)置的時(shí)間計(jì)數(shù)器和次數(shù)計(jì)數(shù)器就會被清零,并重新開始計(jì)數(shù),所以多個(gè)保存條件的效果不會疊加
    
# 該配置項(xiàng)也可以在命令行執(zhí)行 [不推薦] 
redis>save 60 10000

RDB缺點(diǎn)

1、創(chuàng)建RDB文件需要將服務(wù)器所有的數(shù)據(jù)庫的數(shù)據(jù)都保存起來,這是一個(gè)非常消耗資源和時(shí)間的操作,所以服務(wù)器需要隔一段時(shí)間才創(chuàng)建一個(gè)新的RDB文件,也就是說,創(chuàng)建RDB文件不能執(zhí)行的過于頻繁,否則會嚴(yán)重影響服務(wù)器的性能
2、可能丟失數(shù)據(jù)

AOF(AppendOnlyFile)

1、存儲的是命令,而不是真實(shí)數(shù)據(jù)
2、默認(rèn)不開啟
# 開啟方式(修改配置文件)
1、/etc/redis/redis.conf
  672行: appendonly yes # 把 no 改為 yes
  676行: appendfilename "appendonly.aof"
2、重啟服務(wù)
  sudo /etc/init.d/redis-server restart

AOF持久化原理及優(yōu)點(diǎn)

# 原理
   1、每當(dāng)有修改數(shù)據(jù)庫的命令被執(zhí)行時(shí), 
   2、因?yàn)锳OF文件里面存儲了服務(wù)器執(zhí)行過的所有數(shù)據(jù)庫修改的命令,所以給定一個(gè)AOF文件,服務(wù)器只要重新執(zhí)行一遍AOF文件里面包含的所有命令,就可以達(dá)到還原數(shù)據(jù)庫的目的

# 優(yōu)點(diǎn)
  用戶可以根據(jù)自己的需要對AOF持久化進(jìn)行調(diào)整,讓Redis在遭遇意外停機(jī)時(shí)不丟失任何數(shù)據(jù),或者只丟失一秒鐘的數(shù)據(jù),這比RDB持久化丟失的數(shù)據(jù)要少的多

特殊說明

# 因?yàn)?  雖然服務(wù)器執(zhí)行一個(gè)修改數(shù)據(jù)庫的命令,就會把執(zhí)行的命令寫入到AOF文件,但這并不意味著AOF文件持久化不會丟失任何數(shù)據(jù),在目前常見的操作系統(tǒng)中,執(zhí)行系統(tǒng)調(diào)用write函數(shù),將一些內(nèi)容寫入到某個(gè)文件里面時(shí),為了提高效率,系統(tǒng)通常不會直接將內(nèi)容寫入硬盤里面,而是將內(nèi)容放入一個(gè)內(nèi)存緩存區(qū)(buffer)里面,等到緩沖區(qū)被填滿時(shí)才將存儲在緩沖區(qū)里面的內(nèi)容真正寫入到硬盤里

# 所以
  1、AOF持久化:當(dāng)一條命令真正的被寫入到硬盤里面時(shí),這條命令才不會因?yàn)橥C(jī)而意外丟失
  2、AOF持久化在遭遇停機(jī)時(shí)丟失命令的數(shù)量,取決于命令被寫入到硬盤的時(shí)間
  3、越早將命令寫入到硬盤,發(fā)生意外停機(jī)時(shí)丟失的數(shù)據(jù)就越少,反之亦然

策略 - 配置文件

# 打開配置文件:/etc/redis/redis.conf,找到相關(guān)策略如下
1、701行: alwarys
   服務(wù)器每寫入一條命令,就將緩沖區(qū)里面的命令寫入到硬盤里面,服務(wù)器就算意外停機(jī),也不會丟失任何已經(jīng)成功執(zhí)行的命令數(shù)據(jù)
2、702行: everysec(# 默認(rèn))
   服務(wù)器每一秒將緩沖區(qū)里面的命令寫入到硬盤里面,這種模式下,服務(wù)器即使遭遇意外停機(jī),最多只丟失1秒的數(shù)據(jù)
3、703行: no
   服務(wù)器不主動將命令寫入硬盤,由操作系統(tǒng)決定何時(shí)將緩沖區(qū)里面的命令寫入到硬盤里面,丟失命令數(shù)量不確定

# 運(yùn)行速度比較
always:速度慢
everysec和no都很快,默認(rèn)值為everysec

AOF重寫

思考:AOF文件中是否會產(chǎn)生很多的冗余命令?

為了讓AOF文件的大小控制在合理范圍,避免胡亂增長,redis提供了AOF重寫功能,通過這個(gè)功能,服務(wù)器可以產(chǎn)生一個(gè)新的AOF文件
  -- 新的AOF文件記錄的數(shù)據(jù)庫數(shù)據(jù)和原由的AOF文件記錄的數(shù)據(jù)庫數(shù)據(jù)完全一樣
  -- 新的AOF文件會使用盡可能少的命令來記錄數(shù)據(jù)庫數(shù)據(jù),因此新的AOF文件的提及通常會小很多
  -- AOF重寫期間,服務(wù)器不會被阻塞,可以正常處理客戶端發(fā)送的命令請求

示例

原有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重寫-觸發(fā)

1、客戶端向服務(wù)器發(fā)送BGREWRITEAOF命令
   127.0.0.1:6379> BGREWRITEAOF
   Background append only file rewriting started

2、修改配置文件讓服務(wù)器自動執(zhí)行BGREWRITEAOF命令
  auto-aof-rewrite-percentage 100
  auto-aof-rewrite-min-size 64mb
  # 解釋
    1、只有當(dāng)AOF文件的增量大于100%時(shí)才進(jìn)行重寫,也就是大一倍的時(shí)候才觸發(fā)
        # 第一次重寫新增:64M
        # 第二次重寫新增:128M
        # 第三次重寫新增:256M(新增128M)

RDB和AOF持久化對比

RDB持久化 AOF持久化
全量備份,一次保存整個(gè)數(shù)據(jù)庫 增量備份,一次保存一個(gè)修改數(shù)據(jù)庫的命令
保存的間隔較長 保存的間隔默認(rèn)為一秒鐘
數(shù)據(jù)還原速度快 數(shù)據(jù)還原速度一般,冗余命令多,還原速度慢
執(zhí)行SAVE命令時(shí)會阻塞服務(wù)器,但手動或者自動觸發(fā)的BGSAVE不會阻塞服務(wù)器 無論是平時(shí)還是進(jìn)行AOF重寫時(shí),都不會阻塞服務(wù)器
# 用redis用來存儲真正數(shù)據(jù),每一條都不能丟失,都要用always,有的做緩存,有的保存真數(shù)據(jù),我可以開多個(gè)redis服務(wù),不同業(yè)務(wù)使用不同的持久化,新浪每個(gè)服務(wù)器上有4個(gè)redis服務(wù),整個(gè)業(yè)務(wù)中有上千個(gè)redis服務(wù),分不同的業(yè)務(wù),每個(gè)持久化的級別都是不一樣的。

數(shù)據(jù)恢復(fù)(無需手動操作)

既有dump.rdb,又有appendonly.aof,恢復(fù)時(shí)找誰?
先找appendonly.aof

配置文件常用配置總結(jié)

# 設(shè)置密碼
1、requirepass password
# 開啟遠(yuǎn)程連接
2、bind 127.0.0.1 ::1 注釋掉
3、protected-mode no  把默認(rèn)的 yes 改為 no
# rdb持久化-默認(rèn)配置
4、dbfilename 'dump.rdb'
5、dir /var/lib/redis
# rdb持久化-自動觸發(fā)(條件)
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 # 默認(rèn)
13、appendfsync no
# aof重寫觸發(fā)
14、auto-aof-rewrite-percentage 100
15、auto-aof-rewrite-min-size 64mb
# 設(shè)置為從服務(wù)器
16、salveof <master-ip> <master-port>

Redis相關(guān)文件存放路徑

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/下存放服務(wù)啟動文件

Redis主從復(fù)制

  • 定義
1、一個(gè)Redis服務(wù)可以有多個(gè)該服務(wù)的復(fù)制品,這個(gè)Redis服務(wù)成為master,其他復(fù)制品成為slaves
2、master會一直將自己的數(shù)據(jù)更新同步給slaves,保持主從同步
3、只有master可以執(zhí)行寫命令,slave只能執(zhí)行讀命令
  • 作用
分擔(dān)了讀的壓力(高并發(fā))
  • 原理
從服務(wù)器執(zhí)行客戶端發(fā)送的讀命令,比如GET、LRANGE、SMEMMBERS、HGET、ZRANGE等等,客戶端可以連接slaves執(zhí)行讀請求,來降低master的讀壓力
  • 實(shí)現(xiàn)方式
    • 方式一(Linux命令行實(shí)現(xiàn))

      redis-server --slaveof <master-ip> <master-port> --masterauth <master password>

      # 從服務(wù)端
      redis-server --port 6300 --slaveof 127.0.0.1 6379
      # 從客戶端
      redis-cli -p 6300
      127.0.0.1:6300> keys * 
      # 發(fā)現(xiàn)是復(fù)制了原6379端口的redis中數(shù)據(jù)
      127.0.0.1:6300> set mykey 123
      (error) READONLY You can't write against a read only slave.
      127.0.0.1:6300> 
      # 從服務(wù)器只能讀數(shù)據(jù),不能寫數(shù)據(jù)
      
    • 方式二(Redis命令行實(shí)現(xiàn))

      # 兩條命令
      1、>slaveof IP PORT
      2、>slaveof no one
      
      # 服務(wù)端啟動
      redis-server --port 6301
      # 客戶端連接
      tarena@tedu:~$ 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
      
      
    • 方式三(利用配置文件)

      # 每個(gè)redis服務(wù),都有1個(gè)和他對應(yīng)的配置文件
      # 兩個(gè)redis服務(wù)
        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服務(wù)
      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、一個(gè)Master可以有多個(gè)Slaves
2、Slave下線,只是讀請求的處理性能下降
3、Master下線,寫請求無法執(zhí)行
4、其中一臺Slave使用SLAVEOF no one命令成為Master,其他Slaves執(zhí)行SLAVEOF命令指向這個(gè)新的Master,從它這里同步數(shù)據(jù)
# 以上過程是手動的,能夠?qū)崿F(xiàn)自動,這就需要Sentinel哨兵,實(shí)現(xiàn)故障轉(zhuǎn)移Failover操作

演示

1、啟動端口6400redis,設(shè)置為6379的slave
   redis-server --port 6400
   redis-cli -p 6400
   redis>slaveof 127.0.0.1 6379
2、啟動端口6401redis,設(shè)置為6379的slave
   redis-server --port 6401
   redis-cli -p 6401
   redis>slaveof 127.0.0.1 6379
3、關(guān)閉6379redis
   sudo /etc/init.d/redis-server stop
4、把6400redis設(shè)置為master
   redis-cli -p 6400
   redis>slaveof no one
5、把6401的redis設(shè)置為6400redis的salve
   redis-cli -p 6401
   redis>slaveof 127.0.0.1 6400
# 這是手動操作,效率低,而且需要時(shí)間,有沒有自動的???

Sentinel哨兵

Redis之哨兵 - sentinel

1、Sentinel會不斷檢查Master和Slaves是否正常
2、每一個(gè)Sentinel可以監(jiān)控任意多個(gè)Master和該Master下的Slaves

案例演示

**1、**環(huán)境搭建
# 共3個(gè)redis的服務(wù)
1、啟動6379的redis服務(wù)器
    sudo /etc/init.d/redis-server start
2、啟動6380的redis服務(wù)器,設(shè)置為6379的從
    redis-server --port 6380
    tarena@tedu:~$ redis-cli -p 6380
    127.0.0.1:6380> slaveof 127.0.0.1 6379
    OK
3、啟動6381的redis服務(wù)器,設(shè)置為6379的從
    redis-server --port 6381
    tarena@tedu:~$ 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
驗(yàn)證: 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服務(wù)終止,查看從是否會提升為主
sudo /etc/init.d/redis-server stop
# 發(fā)現(xiàn)提升6381為master,其他兩個(gè)為從
# 在6381上設(shè)置新值,6380查看
127.0.0.1:6381> set name tedu
OK

# 啟動6379,觀察日志,發(fā)現(xiàn)變?yōu)榱?381的從
主從+哨兵基本就夠用了

sentinel.conf解釋

# sentinel監(jiān)聽端口,默認(rèn)是26379,可以修改
port 26379
# 告訴sentinel去監(jiān)聽地址為ip:port的一個(gè)master,這里的master-name可以自定義,quorum是一個(gè)數(shù)字,指明當(dāng)有多少個(gè)sentinel認(rèn)為一個(gè)master失效時(shí),master才算真正失效
sentinel monitor <master-name> <ip> <redis-port> <quorum>

#如果master有密碼,則需要添加該配置
sentinel auth-pass <master-name> <password>

#master多久失聯(lián)才認(rèn)為是不可用了,默認(rèn)是30秒
sentinel down-after-milliseconds <master-name> <milliseconds> 
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1.關(guān)系型與非關(guān)系型 關(guān)系型:mysql oracle非關(guān)系型:redis mongo ES 2.Redis重要特...
    linux_wjh閱讀 206評論 0 1
  • redis概念下載安裝命令操作數(shù)據(jù)結(jié)構(gòu)持久化操作使用Java客戶端操作redis Redis 概念: redis是...
    abboo閱讀 217評論 0 0
  • redis是什么 redis是一個(gè)開源的、使用C語言編寫的、支持網(wǎng)絡(luò)交互的、可基于內(nèi)存也可持久化的Key-Valu...
    燁楓_邱閱讀 834評論 0 6
  • 本文是我自己在秋招復(fù)習(xí)時(shí)的讀書筆記,整理的知識點(diǎn),也是為了防止忘記,尊重勞動成果,轉(zhuǎn)載注明出處哦!如果你也喜歡,那...
    波波波先森閱讀 3,480評論 0 40
  • 【本教程目錄】 1.redis是什么2.redis的作者3.誰在使用redis4.學(xué)會安裝redis5.學(xué)會啟動r...
    徐猿猿閱讀 1,918評論 0 35

友情鏈接更多精彩內(nèi)容