NoSQL概述
數(shù)據(jù)庫類型
RDBMS
- 關(guān)系數(shù)據(jù)庫管理系統(tǒng):Relational Database Management System
- 按照預(yù)先設(shè)置的組織結(jié)構(gòu),將數(shù)據(jù)存儲在物理介質(zhì)上
- 數(shù)據(jù)之間可以做關(guān)聯(lián)操作
- 主流的RDBMS軟件
- MySQL
- MariaDB
- Oracle
- DB2
- SQL Server
- PostgreSQL
NoSQL:Not Only SQL
- 意為"不僅僅是SQL"
- 泛指非關(guān)系型數(shù)據(jù)庫
- 不需要預(yù)先定義數(shù)據(jù)存儲結(jié)構(gòu)
- 每條記錄可以有不同的數(shù)據(jù)類型和字段個(gè)數(shù)
- 在一些數(shù)據(jù)庫結(jié)構(gòu)經(jīng)常變化绸吸,數(shù)據(jù)結(jié)構(gòu)不定的系統(tǒng)中鼻弧,就非常適合使用NoSQL來存儲。比如監(jiān)控系統(tǒng)中的監(jiān)控信息的存儲锦茁,可能每種類型的監(jiān)控信息都不太一樣攘轩。這樣可以避免經(jīng)常對MySQL進(jìn)行表結(jié)構(gòu)調(diào)整,增加字段帶來的性能問題蜻势。
- 這種架構(gòu)的缺點(diǎn)就是數(shù)據(jù)直接存儲在NoSQL中撑刺,不能做關(guān)系數(shù)據(jù)庫的復(fù)雜查詢,如果由于需求變更握玛,需要進(jìn)行某些查詢够傍,可能無法滿足,所以采用這種架構(gòu)的時(shí)候需要確認(rèn)未來是否會(huì)進(jìn)行復(fù)雜關(guān)系查詢以及如何應(yīng)對挠铲。
- 主流軟件
- Redis
- Memcached
- MongoDB
- CouchDB
- Neo4j
- FlockDB
部署Redis服務(wù)
在redis1(192.168.1.11)上部署redis
- 安裝編譯器
[root@redis1 ~]# yum install -y gcc
- 編譯安裝redis
[root@redis1 ~]# tar xf redis-4.0.8.tar.gz
[root@redis1 ~]# cd redis-4.0.8
# 修改安裝目錄為/usr/local/redis
[root@redis1 redis-4.0.8]# vim +27 src/Makefile
PREFIX?=/usr/local/redis
# 編譯安裝
[root@redis1 redis-4.0.8]# make && make install
# 將redis命令目錄添加至PATH環(huán)境變量
[root@redis1 redis-4.0.8]# vim /etc/bashrc # 尾部追加
export PATH=$PATH:/usr/local/redis/bin
[root@redis1 redis-4.0.8]# source /etc/bashrc
# 初始化redis服務(wù)
[root@redis1 redis-4.0.8]# ./utils/install_server.sh # 全部問題直接回車采用默認(rèn)值
Welcome to the redis service installer
This script will help you easily set up a running redis server
Please select the redis port for this instance: [6379]
Selecting default: 6379
Please select the redis config file name [/etc/redis/6379.conf]
Selected default - /etc/redis/6379.conf
Please select the redis log file name [/var/log/redis_6379.log]
Selected default - /var/log/redis_6379.log
Please select the data directory for this instance [/var/lib/redis/6379]
Selected default - /var/lib/redis/6379
Please select the redis executable path [/usr/local/redis/bin/redis-server]
Selected config:
Port : 6379
Config file : /etc/redis/6379.conf
Log file : /var/log/redis_6379.log
Data dir : /var/lib/redis/6379
Executable : /usr/local/redis/bin/redis-server
Cli Executable : /usr/local/redis/bin/redis-cli
Is this ok? Then press ENTER to go on or Ctrl-C to abort.
Copied /tmp/6379.conf => /etc/init.d/redis_6379
Installing service...
Successfully added to chkconfig!
Successfully added to runlevels 345!
Starting Redis server...
Installation successful!
- 驗(yàn)證服務(wù)
# 查看服務(wù)狀態(tài)
[root@redis1 ~]# /etc/init.d/redis_6379 status
Redis is running (10023)
# 也可以使用以下方式查看服務(wù)狀態(tài)
[root@redis1 ~]# service redis_6379 status
Redis is running (10023)
[root@redis1 ~]# ss -tlnp | grep :6379
LISTEN 0 128 127.0.0.1:6379 *:* users:(("redis-server",pid=10023,fd=6))
# 關(guān)閉服務(wù)
[root@redis1 ~]# service redis_6379 stop
Stopping ...
Redis stopped
# 也可以使用以下方式關(guān)閉服務(wù)
[root@redis1 ~]# /etc/init.d/redis_6379 stop
# 啟動(dòng)服務(wù)
[root@redis1 ~]# service redis_6379 start
Starting Redis server...
# 也可以使用以下方式啟動(dòng)服務(wù)
[root@redis1 ~]# /etc/init.d/redis_6379 start
# 重啟服務(wù)
[root@redis1 ~]# service redis_6379 restart
Stopping ...
Redis stopped
Starting Redis server...
# 也可以使用以下方式重啟服務(wù)
[root@redis1 ~]# /etc/init.d/redis_6379 restart
# 連接redis
[root@redis1 ~]# redis-cli
127.0.0.1:6379> ping # 測試服務(wù)冕屯,正常返回PONG
PONG
127.0.0.1:6379> exit
Redis數(shù)據(jù)類型
字符串
- 字符串類型是 Redis 中最基本的數(shù)據(jù)類型,它能存儲任何形式的字符串拂苹,包括二進(jìn)制數(shù)據(jù)
- 可以用其存儲用戶的郵箱安聘、JSON 化的對象甚至是一張圖片
- 一個(gè)字符串類型鍵允許存儲的數(shù)據(jù)的最大容量是512 MB
- 字符串類型是其他4種數(shù)據(jù)類型的基礎(chǔ),其他數(shù)據(jù)類型和字符串類型的差別從某種角度來說只是組織字符串的形式不同
字符串操作命令
- 賦值命令
# 賦值
SET key value
# 取值
GET key
- 賦值命令示例
127.0.0.1:6379> SET username tom
OK
127.0.0.1:6379> GET username
"tom"
127.0.0.1:6379> GET password # 當(dāng)鍵不存在時(shí)會(huì)返回空結(jié)果瓢棒。
(nil)
- 遞增數(shù)字:字符串類型可以存儲任何形式的字符串浴韭,當(dāng)存儲的字符串是整數(shù)形式時(shí),Redis 提供了一個(gè)實(shí)用的命令 INCR脯宿,其作用是讓當(dāng)前鍵值遞增念颈,并返回遞增后的值。
# 當(dāng)要操作的鍵不存在時(shí)會(huì)默認(rèn)鍵值為0连霉,所以第一次遞增后的結(jié)果是1榴芳。
127.0.0.1:6379> INCR num
(integer) 1
127.0.0.1:6379> INCR num
(integer) 2
127.0.0.1:6379> GET num
"2"
- 當(dāng)鍵值不是整數(shù)時(shí)Redis會(huì)提示錯(cuò)誤
127.0.0.1:6379> SET foo bar
OK
127.0.0.1:6379> INCR foo
(error) ERR value is not an integer or out of range
- 增加指定的整數(shù)
127.0.0.1:6379> INCRBY num 2
(integer) 4
127.0.0.1:6379> INCRBY num 2
(integer) 6
- 遞減數(shù)字
127.0.0.1:6379> DECR num
(integer) 5
127.0.0.1:6379> DECRBY num 2
(integer) 3
- 向尾部追加值
127.0.0.1:6379> SET hi Hello
OK
127.0.0.1:6379> APPEND hi " World" # 因?yàn)樽址崭裎嗣遥枰褂靡?(integer) 11 # 返回值為hi的總長度
127.0.0.1:6379> GET hi
"Hello World"
- 獲取字符串長度
127.0.0.1:6379> STRLEN hi
(integer) 11
- 中文字符返回字節(jié)數(shù)
127.0.0.1:6379> SET name 張三
OK
127.0.0.1:6379> STRLEN name
(integer) 6 # UTF-8編碼的中文,由于“張”和“三”兩個(gè)字的UTF-8編碼的長度都是3窟感,所以此例中會(huì)返回6讨彼。
- 同時(shí)獲得/設(shè)置多個(gè)鍵值
127.0.0.1:6379> MSET username tom password tedu.cn
OK
127.0.0.1:6379> MGET username password
1) "tom"
2) "tedu.cn"
- 判斷字段是否存在
127.0.0.1:6379> EXISTS num
(integer) 1
127.0.0.1:6379> EXISTS number
(integer) 0
- 字段不存在時(shí)賦值
127.0.0.1:6379> SETNX number 100
(integer) 1
127.0.0.1:6379> GET number
"100"
- 查看所有的key
127.0.0.1:6379> KEYS *
- 刪除字段
127.0.0.1:6379> DEL number
(integer) 1
127.0.0.1:6379> DEL number
(integer) 0
- 查看鍵的類型
127.0.0.1:6379> TYPE name
string
字符串實(shí)踐
- Redis 對于鍵的命名并沒有強(qiáng)制的要求,但比較好的實(shí)踐是用“對象類型:對象ID:對象屬性”來命名一個(gè)鍵柿祈,如使用鍵【
user:1:friends
】來存儲ID為1的用戶的好友列表哈误。 - 例:如果你正在編寫一個(gè)博客網(wǎng)站,博客的一個(gè)常見的功能是統(tǒng)計(jì)文章的訪問量谍夭,我們可以為每篇文章使用一個(gè)名為【
post:文章ID:page.view
】的鍵來記錄文章的訪問量黑滴,每次訪問文章的時(shí)候使用INCR命令使相應(yīng)的鍵值遞增。
# 有用戶訪問文章ID號為42的博文紧索,則將其訪問計(jì)數(shù)加1
127.0.0.1:6379> INCR post:42:page.view
(integer) 1
127.0.0.1:6379> GET post:42:page.view
"1"
127.0.0.1:6379> INCR post:42:page.view
(integer) 2
127.0.0.1:6379> GET post:42:page.view
"2"
散列類型
- 散列類型(hash)的鍵值也是一種字典結(jié)構(gòu)袁辈,其存儲了字段(field)和字段值的映射
- 字段值只能是字符串
- 散列類型適合存儲對象。使用對象類別和 ID 構(gòu)成鍵名珠漂,使用字段表示對象的屬性晚缩,而字段值則存儲屬性值
散列類型操作命令
- 賦值與取值
# 設(shè)置單個(gè)字段
127.0.0.1:6379> HSET user1 name bob
(integer) 1
127.0.0.1:6379> HSET user1 gender male
(integer) 1
127.0.0.1:6379> HGET user1 name
"bob"
127.0.0.1:6379> HGET user1 gender
"male"
# 設(shè)置多個(gè)字段
127.0.0.1:6379> HMSET user1 email bob@tedu.cn phone 13412345678
OK
127.0.0.1:6379> HMGET user1 email phone
1) "bob@tedu.cn"
2) "13412345678"
# 獲取所有字段
127.0.0.1:6379> HGETALL user1
1) "name"
2) "bob"
3) "gender"
4) "male"
5) "email"
6) "bob@tedu.cn"
7) "phone"
8) "13412345678"
- 判斷
# 判斷字段是否存在
127.0.0.1:6379> HEXISTS user1 address
(integer) 0
127.0.0.1:6379> HEXISTS user1 name
(integer) 1
# 當(dāng)字段不存在時(shí)賦值
127.0.0.1:6379> HSETNX user1 address beijing
(integer) 1
127.0.0.1:6379> HSETNX user1 address shanghai
(integer) 0
- 數(shù)字遞增
127.0.0.1:6379> HINCRBY user1 age 20
(integer) 20
127.0.0.1:6379> HINCRBY user1 age 1
(integer) 21
- 刪除字段
127.0.0.1:6379> HDEL user1 age
(integer) 1
- 只獲取字段名
127.0.0.1:6379> HKEYS user1
1) "name"
2) "gender"
3) "email"
4) "phone"
5) "address"
- 只獲取值
127.0.0.1:6379> HVALS user1
1) "bob"
2) "male"
3) "bob@tedu.cn"
4) "13412345678"
5) "beijing"
- 獲得字段數(shù)量
127.0.0.1:6379> HLEN user1
(integer) 5
散列類型實(shí)踐
- 例:將文章ID號為10的文章以散列類型存儲在Redis中
127.0.0.1:6379> HSET post:10 title 例解Python
(integer) 1
127.0.0.1:6379> HGETALL post:10
1) "title"
2) "\xe4\xbe\x8b\xe8\xa7\xa3Python"
127.0.0.1:6379> HSET post:10 author ZhangZhiGang
(integer) 1
127.0.0.1:6379> HMSET post:10 date 2021-05-01 summary 'Python Programming'
OK
127.0.0.1:6379> HGETALL post:10
1) "title"
2) "\xe4\xbe\x8b\xe8\xa7\xa3Python"
3) "author"
4) "ZhangZhiGang"
5) "date"
6) "2021-05-01"
7) "summary"
8) "Python Programming"
列表類型
列表類型(list)可以存儲一個(gè)有序的字符串列表
常用的操作是向列表兩端添加元素,或者獲得列表的某一個(gè)片段
列表類型內(nèi)部是使用雙向鏈表(double linked list)實(shí)現(xiàn)的媳危,獲取越接近兩端的元素速度就越快
使用鏈表的代價(jià)是通過索引訪問元素比較慢
這種特性使列表類型能非耻癖耍快速地完成關(guān)系數(shù)據(jù)庫難以應(yīng)付的場景:如社交網(wǎng)站的新鮮事,我們關(guān)心的只是最新的內(nèi)容待笑,使用列表類型存儲鸣皂,即使新鮮事的總數(shù)達(dá)到幾千萬個(gè),獲取其中最新的100條數(shù)據(jù)也是極快的
列表類型操作命令
- LPUSH命令用來向列表左邊增加元素暮蹂,返回值表示增加元素后列表的長度
127.0.0.1:6379> LPUSH numbers 1
(integer) 1
127.0.0.1:6379> LPUSH numbers 2 3
(integer) 3
- 取出列表所有元素
127.0.0.1:6379> LRANGE numbers 0 -1 # 起始下標(biāo)為0寞缝,結(jié)束下標(biāo)為-1
1) "3"
2) "2"
3) "1"
- RPUSH命令用來向列表右邊增加元素,返回值表示增加元素后列表的長度
127.0.0.1:6379> RPUSH numbers 0 -1
(integer) 5
127.0.0.1:6379> LRANGE numbers 0 -1
1) "3"
2) "2"
3) "1"
4) "0"
5) "-1"
- 從列表兩端彈出元素
127.0.0.1:6379> LPOP numbers
"3"
127.0.0.1:6379> LRANGE numbers 0 -1
1) "2"
2) "1"
3) "0"
4) "-1"
127.0.0.1:6379> RPOP numbers
"-1"
127.0.0.1:6379> LRANGE numbers 0 -1
1) "2"
2) "1"
3) "0"
- 獲取列表中元素的個(gè)數(shù)
127.0.0.1:6379> LLEN numbers
(integer) 3
- 刪除列表中指定的值
# 語法
LREM key count value
#LREM命令會(huì)刪除列表中前count個(gè)值為value的元素仰泻,返回值是實(shí)際刪除的元素個(gè)數(shù)荆陆。根據(jù)count值的不同,LREM命令的執(zhí)行方式會(huì)略有差異集侯。
#(1)當(dāng) count > 0時(shí) LREM 命令會(huì)從列表左邊開始刪除前 count 個(gè)值為 value的元素被啼。
#(2)當(dāng) count < 0時(shí) LREM 命令會(huì)從列表右邊開始刪除前 count 個(gè)值為 value 的元素。
#(3)當(dāng) count = 0是 LREM命令會(huì)刪除所有值為 value的元素棠枉。
127.0.0.1:6379> LPUSH numbers 0 1 2 0 1 2 0 1 2
(integer) 12
127.0.0.1:6379> RPUSH numbers 2 1 0 2 1 0 2 1 0
(integer) 21
127.0.0.1:6379> LRANGE numbers 0 -1
1) "2"
2) "1"
3) "0"
4) "2"
5) "1"
6) "0"
7) "2"
8) "1"
9) "0"
10) "2"
11) "1"
12) "0"
13) "2"
14) "1"
15) "0"
16) "2"
17) "1"
18) "0"
19) "2"
20) "1"
21) "0"
#
127.0.0.1:6379> LREM numbers 2 1 # 從左側(cè)開始刪除2個(gè)1
(integer) 2
127.0.0.1:6379> LRANGE numbers 0 -1
1) "2"
2) "0"
3) "2"
4) "0"
5) "2"
6) "1"
7) "0"
8) "2"
9) "1"
10) "0"
11) "2"
12) "1"
13) "0"
14) "2"
15) "1"
16) "0"
17) "2"
18) "1"
19) "0"
# 從右側(cè)開始刪除2個(gè)0
127.0.0.1:6379> LREM numbers -2 0
(integer) 2
127.0.0.1:6379> LRANGE numbers 0 -1
1) "2"
2) "0"
3) "2"
4) "0"
5) "2"
6) "1"
7) "0"
8) "2"
9) "1"
10) "0"
11) "2"
12) "1"
13) "0"
14) "2"
15) "1"
16) "2"
17) "1"
# 刪除所有的0
127.0.0.1:6379> LREM numbers 0 0
(integer) 5
127.0.0.1:6379> LRANGE numbers 0 -1
1) "2"
2) "2"
3) "2"
4) "1"
5) "2"
6) "1"
7) "2"
8) "1"
9) "2"
10) "1"
11) "2"
12) "1"
- 獲得/設(shè)置指定索引的元素值
# 獲取numbers列表中下標(biāo)為0的值
127.0.0.1:6379> LINDEX numbers 0
"2"
# 設(shè)置下標(biāo)為1的值為10
127.0.0.1:6379> LSET numbers 1 10
OK
127.0.0.1:6379> LRANGE numbers 0 -1
1) "2"
2) "10"
3) "2"
4) "1"
5) "2"
6) "1"
7) "2"
8) "1"
9) "2"
10) "1"
11) "2"
12) "1"
- 刪除指定范圍之外的所有元素
127.0.0.1:6379> LTRIM numbers 0 2
OK
127.0.0.1:6379> LRANGE numbers 0 -1
1) "2"
2) "10"
3) "2"
- 插入元素
# 在2的前面插入20
127.0.0.1:6379> LINSERT numbers BEFORE 2 20
(integer) 4
127.0.0.1:6379> LRANGE numbers 0 -1
1) "20"
2) "2"
3) "10"
4) "2"
# 在2的后面插入30
127.0.0.1:6379> LINSERT numbers AFTER 2 30
(integer) 5
127.0.0.1:6379> LRANGE numbers 0 -1
1) "20"
2) "2"
3) "30"
4) "10"
5) "2"
列表類型實(shí)踐
- 例:記錄最新的10篇博文
127.0.0.1:6379> LPUSH posts:list 11 12 13
(integer) 3
127.0.0.1:6379> LRANGE posts:list 0 -1
1) "13"
2) "12"
3) "11"
集合類型
集合中的每個(gè)元素都是不同的浓体,且沒有順序
增加/刪除元素
127.0.0.1:6379> SADD letters a b c
(integer) 3
127.0.0.1:6379> SADD letters b c d
(integer) 1
127.0.0.1:6379> SMEMBERS letters
1) "d"
2) "b"
3) "a"
4) "c"
127.0.0.1:6379> SREM letters a c
(integer) 2
127.0.0.1:6379> SMEMBERS letters
1) "d"
2) "b"
- 判斷元素是否在集合中
127.0.0.1:6379> SISMEMBER letters a
(integer) 0
127.0.0.1:6379> SISMEMBER letters b
(integer) 1
- 集合運(yùn)算
127.0.0.1:6379> SADD s1 a b c
(integer) 3
127.0.0.1:6379> SADD s2 b c d
(integer) 3
127.0.0.1:6379> SINTER s1 s2
1) "b"
2) "c"
127.0.0.1:6379> SUNION s1 s2
1) "a"
2) "c"
3) "b"
4) "d"
127.0.0.1:6379> SDIFF s1 s2
1) "a"
- 獲得集合中元素個(gè)數(shù)
127.0.0.1:6379> SCARD letters
(integer) 2
- 隨機(jī)獲得集合中的元素
# 在集合s1中隨機(jī)取出兩個(gè)不同元素。
127.0.0.1:6379> SRANDMEMBER s1 2
1) "b"
2) "c"
# 在集合s1中隨機(jī)取出兩個(gè)有可能相同元素辈讶。
127.0.0.1:6379> SRANDMEMBER s1 -2
1) "c"
2) "c"
127.0.0.1:6379> SRANDMEMBER s1 -2
1) "a"
2) "b"
- 集合中隨機(jī)彈出一個(gè)元素
127.0.0.1:6379> SPOP s1
"a"
127.0.0.1:6379> SMEMBERS s1
1) "b"
2) "c"
集合實(shí)踐
- 例:為文章號為10的博客文章添加標(biāo)簽
127.0.0.1:6379> SADD post:10:tags python redis nginx
(integer) 3
127.0.0.1:6379> SMEMBERS post:10:tags
1) "python"
2) "nginx"
3) "redis"
有序集合類型
在集合類型的基礎(chǔ)上有序集合類型為集合中的每個(gè)元素都關(guān)聯(lián)了一個(gè)分?jǐn)?shù)
這使得我們不僅可以完成插入汹碱、刪除和判斷元素是否存在等集合類型支持的操作,還能夠獲得分?jǐn)?shù)最高(或最低)的前N個(gè)元素荞估、獲得指定分?jǐn)?shù)范圍內(nèi)的元素等與分?jǐn)?shù)有關(guān)的操作
雖然集合中每個(gè)元素都是不同的咳促,但是它們的分?jǐn)?shù)卻可以相同。
-
有序集合類型在某些方面和列表類型有些相似
- 二者都是有序的
- 二者都可以獲得某一范圍的元素
-
有序集合類型和列表也有著很大的區(qū)別勘伺,這使得它們的應(yīng)用場景也是不同的
- 列表類型是通過鏈表實(shí)現(xiàn)的跪腹,獲取靠近兩端的數(shù)據(jù)速度極快,而當(dāng)元素增多后飞醉,訪問中間數(shù)據(jù)的速度會(huì)較慢冲茸,所以它更加適合實(shí)現(xiàn)如“新鮮事”或“日志”這樣很少訪問中間元素的應(yīng)用
- 有序集合類型是使用散列表和跳躍表(Skip list)實(shí)現(xiàn)的,所以即使讀取位于中間部分的數(shù)據(jù)速度也很快
- 列表中不能簡單地調(diào)整某個(gè)元素的位置缅帘,但是有序集合可以(通過更改這個(gè)元素的分?jǐn)?shù))
- 有序集合要比列表類型更耗費(fèi)內(nèi)存
有序集合類型操作
- ZADD 命令用來向有序集合中加入一個(gè)元素和該元素的分?jǐn)?shù)轴术,如果該元素已經(jīng)存在則會(huì)用新的分?jǐn)?shù)替換原有的分?jǐn)?shù)。ZADD命令的返回值是新加入到集合中的元素個(gè)數(shù)
127.0.0.1:6379> ZADD scores 88 tom 90 jerry 75 bob 92 alice
(integer) 4
127.0.0.1:6379> ZRANGE scores 0 -1
1) "bob"
2) "tom"
3) "jerry"
4) "alice"
127.0.0.1:6379> ZRANGE scores 0 -1 WITHSCORES
1) "bob"
2) "75"
3) "tom"
4) "88"
5) "jerry"
6) "90"
7) "alice"
8) "92"
127.0.0.1:6379> ZADD scores 85 jerry
(integer) 0
127.0.0.1:6379> ZRANGE scores 0 -1 WITHSCORES
1) "bob"
2) "75"
3) "jerry"
4) "85"
5) "tom"
6) "88"
7) "alice"
8) "92"
- 獲得元素的分?jǐn)?shù)
127.0.0.1:6379> ZSCORE scores tom
"88"
- 獲得指定分?jǐn)?shù)范圍的元素
127.0.0.1:6379> ZRANGEBYSCORE scores 80 90 WITHSCORES
1) "jerry"
2) "85"
3) "tom"
4) "88"
- 增加某個(gè)元素的分?jǐn)?shù)
127.0.0.1:6379> ZINCRBY scores 3 bob
"78"
127.0.0.1:6379> ZSCORE scores bob
"78"
- 獲得集合中元素的數(shù)量
127.0.0.1:6379> ZCARD scores
(integer) 4
- 獲得指定分?jǐn)?shù)范圍內(nèi)的元素個(gè)數(shù)
127.0.0.1:6379> ZCOUNT scores 80 90
(integer) 2
- 刪除元素
127.0.0.1:6379> ZREM scores bob
(integer) 1
- 獲得元素的排名
127.0.0.1:6379> ZRANK scores tom # 獲取tom的排名
(integer) 1 # 升序排列钦无,從0開始計(jì)數(shù)
127.0.0.1:6379> ZREVRANK scores alice # 獲取alice的排名
(integer) 0 # 降序排列逗栽,從0開始計(jì)數(shù)
有序集合類型實(shí)踐
- 例:將博客文章按照點(diǎn)擊量排序
127.0.0.1:6379> ZADD posts:page.view 0 post:10:page.view
(integer) 1
127.0.0.1:6379> ZINCRBY posts:page.view 1 post:10:page.view
"1"
127.0.0.1:6379> ZRANGE posts:page.view 0 -1 WITHSCORES
1) "post:10:page.view"
2) "1"
Redis其他操作命令
數(shù)據(jù)操作命令
- 查看key過期時(shí)間
127.0.0.1:6379> TTL name
(integer) -1 # -1 表示永不過期
# 創(chuàng)建key的同時(shí),設(shè)置它的過期時(shí)間失暂。key是user1:login彼宠,value是235124,超時(shí)時(shí)間60秒
127.0.0.1:6379> SET user1:login 235124 ex 60
OK
- 設(shè)置key的過期時(shí)間(秒)
127.0.0.1:6379> EXPIRE password 20
(integer) 1
127.0.0.1:6379> TTL password
(integer) 15
127.0.0.1:6379> TTL password
(integer) -2 # -2表示已過期
- 查看key是否存在
127.0.0.1:6379> EXISTS password
(integer) 0
- 存盤
127.0.0.1:6379> SAVE
OK
數(shù)據(jù)庫操作命令
- 默認(rèn)Redis有16個(gè)庫弟塞,將name移動(dòng)到1號庫
127.0.0.1:6379> MOVE name 1
(integer) 1
- 選擇庫
127.0.0.1:6379> SELECT 1
OK
127.0.0.1:6379[1]> KEYS *
1) "name"
- 清除庫
# 清除當(dāng)前庫
127.0.0.1:6379[1]> FLUSHDB
OK
127.0.0.1:6379[1]> KEYS *
(empty list or set)
# 清除所有庫
127.0.0.1:6379[1]> SELECT 0
OK
127.0.0.1:6379> KEYS *
1) "numbers"
2) "2"
3) "posts:list"
4) "letters"
5) "posts:page.view"
6) "scores"
7) "post:10:tags"
8) "foo"
9) "s1"
10) "s2"
11) "num"
12) "post:10"
13) "user1"
14) "username"
15) "hi"
16) "post:42:page.view"
127.0.0.1:6379> SELECT 1
OK
127.0.0.1:6379[1]> FLUSHALL
OK
127.0.0.1:6379[1]> SELECT 1
OK
127.0.0.1:6379[1]> KEYS *
(empty list or set)
- 關(guān)閉Redis
127.0.0.1:6379> SHUTDOWN
not connected> exit
修改Redis服務(wù)運(yùn)行參數(shù)
常用參數(shù)
- 監(jiān)聽地址:默認(rèn)運(yùn)行在127.0.0.1上
- 監(jiān)聽端口:默認(rèn)監(jiān)聽6379端口(不用修改)
- 密碼
[root@redis1 ~]# vim /etc/redis/6379.conf
protected-mode no # 關(guān)閉保護(hù)模式凭峡,以允許不指定服務(wù)綁定在哪個(gè)地址
# bind 127.0.0.1 # 注釋此行,運(yùn)行在0.0.0.0上
port 6379 # 端口號
requirepass tedu.cn # 密碼
- 修改啟動(dòng)腳本
[root@redis1 ~]# vim +43 /etc/init.d/redis_6379
... ...
$CLIEXEC -p $REDISPORT -a tedu.cn shutdown
... ...
- 啟動(dòng)服務(wù)并測試
[root@redis1 ~]# service redis_6379 start
Starting Redis server...
[root@redis1 ~]# redis-cli -h 192.168.1.11 -p 6379 -a tedu.cn
192.168.1.11:6379> PING
PONG
附:python操作redis
# 安裝redis模塊
[root@zzgrhel8 ~]# pip3 install redis
# 操作
[root@zzgrhel8 ~]# python3
>>> import redis
>>> help(redis.Redis)
>>> r = redis.Redis(host='192.168.1.11', db=0, password='tedu.cn')
# 操作字符串類型數(shù)據(jù)
>>> r.set('name', 'tom')
# 更多操作參見:https://www.cnblogs.com/melonjiang/p/5342505.html
部署支持php和Redis的Nginx服務(wù)器
安裝并配置Nginx服務(wù)器
- 在nginx1(192.168.1.10)上安裝nginx
# 安裝編譯器
[root@nginx1 ~]# yum install -y gcc pcre-devel zlib-devel
# 編譯安裝nginx
[root@nginx1 ~]# tar xf nginx-1.12.2.tar.gz
[root@nginx1 ~]# cd nginx-1.12.2
[root@nginx1 nginx-1.12.2]# ./configure
[root@nginx1 nginx-1.12.2]# make && make install
- 安裝php-fpm
[root@nginx1 ~]# yum install -y php-fpm
[root@nginx1 ~]# systemctl start php-fpm
[root@nginx1 ~]# ss -tlnp | grep :9000
LISTEN 0 128 127.0.0.1:9000 *:* users:(("php-fpm",pid=11310,fd=0),("php-fpm",pid=11309,fd=0),("php-fpm",pid=11308,fd=0),("php-fpm",pid=11307,fd=0),("php-fpm",pid=11306,fd=0),("php-fpm",pid=11305,fd=6))
- 修改配置文件
[root@nginx1 ~]# vim +65 /usr/local/nginx/conf/nginx.conf
location ~ \.php$ {
root html;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
include fastcgi.conf;
}
- 啟動(dòng)nginx服務(wù)
[root@nginx1 ~]# /usr/local/nginx/sbin/nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
[root@nginx1 ~]# /usr/local/nginx/sbin/nginx
[root@nginx1 ~]# ss -tlnp | grep :80
LISTEN 0 128 *:80 *:* users:(("nginx",pid=11376,fd=6),("nginx",pid=11375,fd=6))
- 測試
[root@nginx1 ~]# vim /usr/local/nginx/html/test.php
<?php
echo "Hello World!\n";
phpinfo();
?>
[root@nginx1 ~]# curl http://127.0.0.1/test.php
Hello World!
... ...
配置PHP支持Redis
- 安裝php擴(kuò)展
[root@nginx1 ~]# yum install -y php-devel automake autoconf
- 安裝php-redis
[root@nginx1 ~]# tar xf redis-cluster-4.3.0.tgz
[root@nginx1 ~]# cd redis-4.3.0/
[root@nginx1 redis-4.3.0]# phpize
[root@nginx1 redis-4.3.0]# ./configure --with-php-config=/usr/bin/php-config
[root@nginx1 redis-4.3.0]# make && make install
[root@nginx1 redis-4.3.0]# ls /usr/lib64/php/modules/redis.so
/usr/lib64/php/modules/redis.so
- 修改php配置文件并重啟服務(wù)
[root@nginx1 redis-4.3.0]# vim /etc/php.ini # 在730行下添加
extension_dir = "/usr/lib64/php/modules"
extension = "redis.so"
[root@nginx1 ~]# systemctl restart php-fpm
- 測試
# 創(chuàng)建腳本决记,寫入redis數(shù)據(jù)庫
[root@nginx1 ~]# vim /usr/local/nginx/html/set_redis.php
<?php
$redis = new redis();
$redis->connect("192.168.1.11", "6379");
$redis->auth("tedu.cn");
$redis->set("username", "tom");
?>
# 創(chuàng)建腳本摧冀,讀取redis數(shù)據(jù)
[root@nginx1 ~]# vim /usr/local/nginx/html/get_redis.php
<?php
$redis = new redis();
$redis->connect("192.168.1.11", "6379");
$redis->auth("tedu.cn");
echo $redis->get("username");
?>
# 訪問測試頁面
[root@nginx1 ~]# curl http://127.0.0.1/set_redis.php
[root@nginx1 ~]# curl http://127.0.0.1/get_redis.php
tom
# 在redis數(shù)據(jù)庫上查看
[root@redis1 ~]# redis-cli -a tedu.cn
127.0.0.1:6379> KEYS *
1) "username"
127.0.0.1:6379> GET username
"tom"
附加練習(xí):參見【tedu_nsd/software/php_redis_mysql_bbs/】