人生最大的幸福就是健康地生活著痴施!
總結(jié):
- redis最關(guān)注的問題: 是你要用python來解決數(shù)據(jù)存儲(如何選擇數(shù)據(jù)存儲的類型)的問題娘摔;內(nèi)存如何合理使用的問題碰煌;
- redis的數(shù)據(jù)安全指的是:將所有的二進制數(shù)據(jù)轉(zhuǎn)成10進制后太雨,在轉(zhuǎn)成字符串蕊退;
- redis的本質(zhì)是key-value對验夯, 只不過value 可以為:str/Dict(hash 字典V 套字典)/set(集合),所以他的變化指的是value的類型變化猖吴; 他就是內(nèi)存結(jié)構(gòu)的典型的嵌套結(jié)構(gòu)的一個復(fù)雜的K-V對;
- 任何 flashdb都是危險操作;
- 介紹 Redis 的對象系統(tǒng)中的字符串對象(String)挥转、列表對象(List)海蔽、哈希對象(Hash)、集合對象(Set)和有序集合對象(ZSet)
- Redis 的list 可以當(dāng)成緩沖隊列 來使用的绑谣;業(yè)務(wù)場景:
參考:
- Redis數(shù)據(jù)結(jié)構(gòu)詳解党窜,五種數(shù)據(jù)結(jié)構(gòu)分分鐘掌握
- 十二張圖詳解Redis的數(shù)據(jù)結(jié)構(gòu)和對象系統(tǒng)
- 萬字長文的Redis五種數(shù)據(jù)結(jié)構(gòu)詳解(理論+實戰(zhàn)),建議收藏
Redis
官方網(wǎng)站:http://www.radis.io
中文網(wǎng)站:http://www.redis.cn
開源的(BSD協(xié)議)借宵,使用ANSI C 編寫幌衣,基于內(nèi)存的且支持持久化,高性能的Key-Value的NoSQL數(shù)據(jù)庫壤玫。
支持?jǐn)?shù)據(jù)結(jié)構(gòu)類型豐富豁护,有如 字符串(strings), 散列(hashes)欲间, 列表(lists)楚里, 集合(sets), 有序集合(sorted sets) 與范圍查詢猎贴, bitmaps班缎, hyperloglogs 和 地理空間(geospatial) 索引半徑查詢蝴光。
豐富的支持主流語言的客戶端,C吝梅、C++虱疏、Python、Erlang苏携、R做瞪、C#、Java右冻、PHP装蓬、Objective-C、Perl纱扭、Ruby牍帚、Scala、Go乳蛾、JavaScript暗赶。
用途:緩存(StackOverFlow)、數(shù)據(jù)庫(微博)肃叶、消息中間件(微博)
Redis版本
目前主要版本為3.2
redis在2017年也發(fā)布了4.x版本蹂随,目前是4.0.x
部署環(huán)境是Linux,本次部署在CentOS 6.x上因惭。
Windows版本由微軟提供 https://github.com/MicrosoftArchive/redis
可視化工具RedisDesktopManager岳锁。windows目前使用redis-desktop-manager-0.8.x,0.9有點問題蹦魔。
1. Redis安裝
Linux單節(jié)點安裝
# yum -y install gcc tcl
# tar xf redis-3.2.12.tar.gz
# mv redis-3.2.12/ redis
# cd redis
# make
------------------------------------編譯安裝成功激率;
LINK redis-server # 最常用的3個文件 ;
INSTALL redis-sentinel
CC redis-cli.o
Hint: It's a good idea to run 'make test' ;)
make[1]: Leaving directory `/root/redis-3.2.12/src'
如果出錯勿决,需要redis目錄下
# cd deps
# make jemalloc
# make lua
# make linenoise
# make hiredis
# cd ..
缺省安裝
# make install
默認(rèn)安裝到/usr/local/bin
自定義安裝
# mkdir -p /magedu/redis
# make PREFIX=/magedu/redis install
可執(zhí)行文件
cd src
redis-benchmark
redis-check-aof
redis-check-dump
redis-cli # 客戶端
redis-server
[root@Centos7 src]# mkdir /magedu/redis -p # 創(chuàng)建目錄
[root@Centos7 redis-3.2.12]# make PREFIX=/magedu/redis/ install # 拷貝文件乒躺;
cd src && make install
make[1]: Entering directory `/root/redis-3.2.12/src'
Hint: It's a good idea to run 'make test' ;)
INSTALL install
INSTALL install
INSTALL install
INSTALL install
INSTALL install
make[1]: Leaving directory `/root/redis-3.2.12/src'
[root@Centos7 src]# cd /magedu/redis/
[root@Centos7 redis]# ls
bin
[root@Centos7 redis]# cd bin/
[root@Centos7 bin]# ll
total 15080
-rwxr-xr-x. 1 root root 2433432 Aug 13 17:10 redis-benchmark
-rwxr-xr-x. 1 root root 24992 Aug 13 17:10 redis-check-aof
-rwxr-xr-x. 1 root root 5191752 Aug 13 17:10 redis-check-rdb
-rwxr-xr-x. 1 root root 2586480 Aug 13 17:10 redis-cli
lrwxrwxrwx. 1 root root 12 Aug 13 17:10 redis-sentinel -> redis-server
-rwxr-xr-x. 1 root root 5191752 Aug 13 17:10 redis-server
# 把redis變成一個服務(wù);
[root@Centos7 utils]# ./install_server.sh
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 []
環(huán)境變量
可以將下面的變量追加入到~/.bash_pro?le文件末尾
export REDIS_HOME=/magedu/redis
export PATH=REDIS_HOME/bin
配置PATH路徑
[root@Centos7 bin]# nano ~/.bash_profile
# .bash_profile
# Get the aliases and functions
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
# User specific environment and startup programs
PATH=$PATH:$HOME/bin
export PATH
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
export REDIS_HOME=/magedu/redis
export PATH=$PATH:$REDIS_HOME/bin
[root@Centos7 bin]# source ~/.bash_profile # 刷新
[root@Centos7 bin]# ls
redis-benchmark redis-check-aof redis-check-rdb redis-cli redis-sentinel redis-server
[root@Centos7 bin]# echo $REDIS_HOME # 配置路徑成功低缩;
/magedu/redis
# 服務(wù)
[root@Centos7 ~]# redis-3.2.12/utils/install_server.sh
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 [] /magedu/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 : /magedu/redis/bin/redis-server
Cli Executable : /magedu/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!
[root@Centos7 bin]# cd /etc/init.d
[root@Centos7 init.d]# ll
total 48
-rw-r--r--. 1 root root 18281 Aug 19 2019 functions
-rwxr-xr-x. 1 root root 4569 Aug 19 2019 netconsole
-rwxr-xr-x. 1 root root 7928 Aug 19 2019 network
-rwxr-xr-x. 1 root root 4014 Nov 30 2017 rabbitmq-server
-rw-r--r--. 1 root root 1160 Jun 30 23:11 README
-rwxr-xr-x. 1 root root 1708 Aug 13 17:14 redis_6379
[root@Centos7 init.d]# mv redis_6379 redisd # 改一下服務(wù)名稱聪蘸;
redis服務(wù)
[root@Centos7 init.d]# chkconfig
Note: This output shows SysV services only and does not include native
systemd services. SysV configuration data might be overridden by native
systemd configuration.
If you want to list systemd services use 'systemctl list-unit-files'.
To see services enabled on particular target use
'systemctl list-dependencies [target]'.
netconsole 0:off 1:off 2:off 3:off 4:off 5:off 6:off
network 0:off 1:off 2:on 3:on 4:on 5:on 6:off
rabbitmq-server 0:off 1:off 2:on 3:on 4:on 5:on 6:off
[root@Centos7 init.d]# chkconfig redisd on # 開機啟動 redis 2345
[root@Centos7 init.d]# chkconfig
Note: This output shows SysV services only and does not include native
systemd services. SysV configuration data might be overridden by native
systemd configuration.
If you want to list systemd services use 'systemctl list-unit-files'.
To see services enabled on particular target use
'systemctl list-dependencies [target]'.
netconsole 0:off 1:off 2:off 3:off 4:off 5:off 6:off
network 0:off 1:off 2:on 3:on 4:on 5:on 6:off
rabbitmq-server 0:off 1:off 2:on 3:on 4:on 5:on 6:off
redisd 0:off 1:off 2:on 3:on 4:on 5:on 6:off
# redis 配置文件
[root@Centos7 src]# nano /etc/redis/6379.conf
bind 192.168.0.100 127.0.0.1
protected-mode yes
port 6379
tcp-keepalive 300 # TCP服務(wù)保存多長時間;
daemonize yes # 以后臺服務(wù)跑起來
databases 16 # 總共有16 個庫(0-15)
# 修改配置文件后 重新 啟動 redisd
[root@Centos7 ~]# systemctl restart redisd.service
[root@Centos7 ~]# ss -tanl
LISTEN 0 128 127.0.0.1:6379 *:*
LISTEN 0 128 192.168.0.100:6379
Redis Windows安裝
項目地址 https://github.com/MicrosoftArchive/redis
下載地址 https://github.com/MicrosoftArchive/redis/releases/download/win-3.2.100/Redis-x64-3.2.100.zip
解壓縮表制,就可以用了健爬。
2. Redis數(shù)據(jù)模型
redis支持?jǐn)?shù)據(jù)模型非常豐富
2.1 鍵Key
Redis key 值是二進制安全的,這意味著可以用任何二進制序列作為key值么介,從形如”foo”的簡單字符串到一個JPEG文件的內(nèi)容都可以娜遵。空字符串也是有效key值
Key取值原則
鍵值不需要太長壤短,消耗內(nèi)存设拟,而且查找這類鍵值的計算成本較高
鍵值不宜過短慨仿,可讀性較差
習(xí)慣上key采用'user:123:password'形式,表示用戶id為123的用戶的密碼
2.2字符串
字符串是一種最基本簡單的Redis值類型纳胧。Redis字符串是二進制安全的镰吆,這意味著一個Redis字符串能包含任意類型的數(shù)據(jù),例如: 一張JPEG格式的圖片或者一個序列化的Ruby對象跑慕。
一個字符串類型的值最多能存儲512M字節(jié)的內(nèi)容万皿。
1. python中redis編程
安裝redis庫
$ pip install redis
import redis
db = redis.Redis('192.168.0.100') # 默認(rèn)本地6379的0號庫
print(db.keys('*')) # 查看所有匹配keys
db.set(0b01100001, 'a') # 0x61(16進制61) bin二進制=>十進制97=>str :a
print(db.keys('*'))
#------------------------------
[]
[b'97']
print(db.get(0b01100001))
print(db.get('97')) # 用字符串 拿
#----------------------
b'a'
b'a'
# key的三種形式
db.set(0b11, 'abc')
print(db.get(0b11))
print(db.get(3))
print(db.get('3'))
#----------------------
b'abc'
b'abc'
b'abc'
注意:上例中0x62實際上發(fā)生了類型變化,因為返回的bytes類型98核行,實際上對應(yīng)ASCII的98牢硅,已經(jīng)是2字節(jié)了。
數(shù)值會先轉(zhuǎn)換成10進制64位有符號數(shù)后芝雪,再轉(zhuǎn)成字符串减余,存入redis中。
2. 查看幫助
> Help 查看幫助
> Help <tab> 使用tab鍵切換幫助
> Help set 查看set命令幫助
> Help @string 查看命令組幫助
3. 字符串設(shè)置
SET key value [EX seconds][PX milliseconds] [NX|XX]
設(shè)置字符串值
EX 設(shè)置過期時間惩系,秒位岔,等同于 SETEX key seconds value
PX 設(shè)置過期時間,毫秒堡牡,等同于 PSETEX key milliseconds value
NX 鍵不存在抒抬,才能設(shè)置,等同于 SETNX key value
XX 鍵存在時悴侵,才能設(shè)置
MSET key value [key value ...]
設(shè)置多個鍵的字符串值,key存在則覆蓋拭嫁,key不存在則增加
原子操作
MSETNX key value [key value ...]
key不存在則設(shè)置可免,key存在則失敗。nx指不存在做粤。
這個命令是原子操作(一個失敗浇借,操作全部失敗)
4. 過期操作和生存時間
Redis中可以給每個Key設(shè)置一個生存時間(秒或毫秒)怕品,當(dāng)達(dá)到這個時長后妇垢,這些鍵值將會被自動刪除
EXPIRE key seconds
PEXPIRE key milliseconds
設(shè)置多少秒或者毫秒后過期
EXPIREAT key timestamp
PEXPIREAT key milliseconds-timestamp
設(shè)置在指定Unix時間戳過期
PERSIST key
持久key,即取消過期
Time To Live肉康,Key的剩余生存時間
TTL key
PTTL key
key存在但沒有設(shè)置TTL闯估,返回-1
key存在,但還在生存期內(nèi)吼和,返回剩余的秒或者毫秒
key曾經(jīng)存在涨薪,但已經(jīng)消亡,返回-2(2.8版本之前返回-1)
適用場景
一炫乓、多少秒過期刚夺,例如一個緩存數(shù)據(jù)失效
二献丑、PEXPIREAT key milliseconds-timestamp,比如現(xiàn)在開始緩存數(shù)據(jù)侠姑,到0點失效
set s5 abc ex 20
ttl s5
setnx s6 6
expire s6 60
pttl s6
persist s6
ttl s6
EXPIREAT cache 1355292000
PEXPIREAT mykey 1555555555005
5. key操作
keys pattern
pattern可以取如下值:
1. * 任意長度字符
2. ? 任意一個字符
3. [] 字符集合创橄,表示一個字符
keys *
keys s?
keys s[13]
keys s*
keys ??
keys s[1-3]
TYPE key | key類型 |
EXISTS key | key是否存在 |
RENAME key newkey 、 RENAMENX key newkey | 鍵重命名 |
DEL key [key ...] | 鍵刪除 |
6. 字符串獲取
GET key | 獲取值 |
MGET key [key ...] | 獲取多個給定的鍵的值 |
GETSET key value | 返回舊值并設(shè)置新值莽红,如果鍵不存在妥畏,就創(chuàng)建并賦值 |
STRLEN key | 字符串長度 |
get s4
mget s1 s3 s5 s7
strlen s3
mgetset s5 100
7. 字符串操作
APPEND key value | 追加字符串。如果鍵存在就追加船老;如果不存在就等同于SET key value |
獲取子字符串 | |
GETRANGE key start end | 索引值從0開始咖熟,支持負(fù)索引,-1表示最后一個字符柳畔。范圍是[start, end]馍管,start必須在end的左邊,否則返回空串(前后都包括) |
SETRANGE key offset value | 從指定索引處開始覆蓋字符串薪韩,返回覆蓋后字符串長度确沸。key不存在會創(chuàng)建新的 |
127.0.0.1:6379[1]> get s4
(nil)
127.0.0.1:6379[1]> APPEND s4 0123
(integer) 4
127.0.0.1:6379[1]> get s4
"0123"
127.0.0.1:6379[1]> setrange s4 2 a
(integer) 4
127.0.0.1:6379[1]> get s4
"01a3"
127.0.0.1:6379[1]> setrange s4 2 abcde
(integer) 7
127.0.0.1:6379[1]> get s4
"01abcde"
8. 自增、自減
INCR key 和 DECR key | 步長1的增減 |
INCRBY key decrement 和 DECRBY key decrement | 步長增減 |
字符串值會被解釋成64位有符號的十進制整數(shù)來操作俘陷,結(jié)果依然轉(zhuǎn)成字符串
127.0.0.1:6379[1]> set s3 10
OK
127.0.0.1:6379[1]> incr s3
(integer) 11
127.0.0.1:6379[1]> incrby s3 100
(integer) 111
127.0.0.1:6379[1]> DECRBY s3 200
(integer) -89
127.0.0.1:6379[1]>
2.3 庫操作
任何 flashdb都是危險操作,一定有損失罗捎;
登錄不同的庫
redis-cli --help
redis-cli -n 2
清除當(dāng)前庫數(shù)據(jù)
FLUSHDB
清除所有庫中的數(shù)據(jù)
FLUSHALL
2.4 位圖bitmap
位圖不是真正的數(shù)據(jù)類型,它是定義在字符串類型上拉盾,只不過把字符串按位操作
一個字符串類型的值最多能存儲512M字節(jié)的內(nèi)容桨菜,可以表示2^32位位上限:
512=29
1M=1024*1024=210+10
1Byte=8bit=23bit
2(9+10+10+3) = 232 b = 4294967296 b ,接近43億個位
SETBIT key offset value | 設(shè)置某一位上的值 o?set偏移量捉偏,從0開始倒得; value不寫,默認(rèn)是0 |
GETBIT key offset | 獲取某一位上的值 |
BITPOS key bit [start][end] | 返回指定值0或者1在指定區(qū)間上第一次出現(xiàn)的位置 |
BITCOUNT key [start][end] | 統(tǒng)計指定位區(qū)間上值為1的個數(shù)夭禽,從左向右從0開始霞掺,從右向左從-1開始,注意官方start讹躯、end是位菩彬,測試后是字節(jié) |
BITCOUNT testkey 0 0 | 表示從索引為0個字節(jié)到索引為0個字節(jié),就是第一個字節(jié)的統(tǒng)計 |
BITCOUNT testkey 0 -1 | 等同于 BITCOUNT testkey潮梯;最常用的就是 BITCOUNT testkey |
# 記住 \x3 7
127.0.0.1:6379[1]> set s4 7
OK
127.0.0.1:6379[1]> getbit s4 0
(integer) 0
127.0.0.1:6379[1]> getbit s4 1
(integer) 0
127.0.0.1:6379[1]> getbit s4 2
(integer) 1
127.0.0.1:6379[1]> getbit s4 3
(integer) 1
127.0.0.1:6379[1]> getbit s4 4
(integer) 0
127.0.0.1:6379[1]> getbit s4 5
(integer) 1
127.0.0.1:6379[1]> getbit s4 6
(integer) 1
127.0.0.1:6379[1]> getbit s4 7
(integer) 1
#------------------------------------
127.0.0.1:6379[1]> set str1 abc
OK
127.0.0.1:6379[1]> setbit str1 6 1
(integer) 0
127.0.0.1:6379[1]> setbit str1 7 0
(integer) 1
127.0.0.1:6379[1]> get str1
"bbc"
#------------------------------------
# 按照位統(tǒng)計的骗灶;
127.0.0.1:6379[1]> set s4 77
OK
127.0.0.1:6379[1]> bitcount s4 0 0
(integer) 5
127.0.0.1:6379[1]> bitcount s4 1 1
(integer) 5
127.0.0.1:6379[1]> bitcount s4
(integer) 10
1. 位操作
BITOP命令用于對多個值(除NOT操作外)執(zhí)行位運算操作,并將結(jié)果保存至指定的鍵值對中秉馏。BITOP命令將返回結(jié)果字符串的長度矿卑,其值等于輸入中最長字符串的長度。
BITOP operation destkey key [key ...]
BITOP命令支持與(AND)沃饶、或(OR)母廷、亦或(XOR)以及非(NOT)四個位運算操作轻黑,其使用方式為:
AND 與操作,使用方式為BITOP AND destkey srckey1 srckey2 ...
OR 或操作琴昆,使用方式為BITOP OR destkey srckey1 srckey2 ...
XOR 亦或操作氓鄙,使用方式為BITOP XOR destkey srckey1 srckey2 ...
NOT 非操作,使用方式為BITOP NOT destkey srckey
當(dāng)輸入的字符串長度不同時业舍,將使用0填充至與最長長度相同抖拦。若輸入的鍵不存在則認(rèn)定為一個空白字符串,并以0填充至與最長長度相同舷暮。
# 10101010
redis> SET key1 "\xaa"
OK
# 01010101
redis> SET key2 "\x55"
OK
# 11110000
redis> SET key3 "\xf0"
OK
# 01010101 01010101
redis> SET key4 "\x5555"
OK
與(AND)操作:
# 10101010 & 01010101 = 00000000
redis> BITOP AND result key1 key2
(integer) 1
redis> GET result
"\x00"
或(OR)操作:
# 10101010 | 01010101 = 11111111
redis> BITOP OR result key1 key2
(integer) 1
redis> GET result
"\xff"
亦或(XOR)操作:
# 10101010 ^ 11110000 = 01011010
redis> BITOP XOR result key1 key3
(integer) 1
# 字符Z二進制值為 01011010
redis> GET result
"Z"
或(OR)操作:
# !10101010 = 01010101
redis> BITOP NOT result key1
(integer) 1
# 字符U二進制值為 01010101
redis> GET result
"U"
不同長度的字符串進行位運算:
# key1的值將以0填充為 10101010 00000000
# 10101010 00000000 | 01010101 01010101 = 11111111 00000000
redis> BITOP OR result key1 key4
(integer) 2
redis> GET result
"\xffU"
思考:'a'位或'b'是什么态罪?
set s1 ab
bitcount s1
bitcount s1 0 0
bitcount s1 1 1
set s2 a
set s3 b
bitop or s8 s2 s3 # 等于什么?
set cn 中
get cn
bitcount cn
2. 習(xí)題
1下面、網(wǎng)站用戶的上線次數(shù)統(tǒng)計(活躍用戶)
2复颈、按天統(tǒng)計網(wǎng)站活躍用戶
參考
1、網(wǎng)站用戶的上線次數(shù)統(tǒng)計(活躍用戶)
為每一個用戶做上線記錄沥割,某天登錄就標(biāo)記一次耗啦。
用戶ID為key,天作為o?set机杜,上線置為1
ID為500的用戶帜讲,今年的第1天上線、第30天上線
SETBIT u:500 1 1
SETBIT u:500 30 1
BITCOUNT u:500
KYES u*
from redis import Redis
redis = Redis('192.168.0.100', db=2)
# user id 1
redis.setbit('u:1', 1, 1)
redis.setbit('u:1', 30, 1)
# user id 101
redis.setbit('u:101', 3, 1)
redis.setbit('u:1', 30, 1)
# user id 501
for i in range(3, 365, 3):
redis.setbit('u:501', i, 1)
for i in range(2, 365, 2):
redis.setbit('u:1000', i, 1)
active = []
inactive = []
users = redis.keys('u*')
print(users)
for user in users:
count = redis.bitcount(user)
if count > 100:
active.append(user)
else:
inactive.append(user)
print('活躍用戶為{}椒拗,{}'.format(active, len(active)))
print('不活躍用戶為{}似将,{}'.format(inactive, len(inactive)))
2、按天統(tǒng)計網(wǎng)站活躍用戶
天作為key蚀苛,用戶ID為o?set在验,上線置為1
求一段時間內(nèi)活躍用戶數(shù)
SETBIT 20160602 15 1
SETBIT 20160601 123 1
SETBIT 20160606 123 1求6月1日到6月10日的活躍用戶
BITOP OR 20160601-10 20160601 20160602 20160603 20160610
BITCOUNT 20160601-10
結(jié)果為2
2.5 List列表
列表類型存儲了一個有序的字符串列表。常用的操作是向兩端插入新的元素枉阵。時間復(fù)雜度為O(1)译红。結(jié)構(gòu)為一個鏈表预茄。記錄頭和尾的地址兴溜。看到這里耻陕,Redis數(shù)據(jù)類型的列表類型一個重大的作用呼之欲出拙徽,那就是隊列。新來的請求插入到尾部诗宣,新處理過的從頭部刪除膘怕。另外,比如微博的新鮮事召庞。比如日志岛心。列表類型就是一個下標(biāo)從0開始的數(shù)組来破。由于是鏈表存儲,那么越靠近頭和尾的元素操作越快忘古,越靠近中間則越慢徘禁。
- 其列表是基于雙向鏈表實現(xiàn),列表頭尾增刪快髓堪,中間增刪慢
- 元素是字符串類型
- 元素可以重復(fù)出現(xiàn)
- 索引支持正索引和負(fù)索引送朱,從左至右從0開始,從右至左從-1開始
命令說明
字母 | 說明 |
---|---|
B | Block阻塞 |
L | Left左起 |
R | Right 右起 |
X | exist 存在 |
LPUSH key value [value ...] | 從左邊向隊列中壓入元素 | |
LPUSHX key value | 從左邊向隊列加入元素干旁,要求key必須存在 | |
RPUSH key value [value ...] | 從右邊向隊列中壓入數(shù)據(jù) | |
RPUSHX key value | 要求key存在 | |
- | - | |
LPOP key | 從左邊彈出列表中一個元素 | |
RPOP key | 從右邊彈出列表中一個元素 | |
- | - | |
RPOPLPUSH source destination | 從源列表中右邊pop一個元素驶沼,從左邊加入到目標(biāo)列表 | |
LRANGE key start stop | 返回列表中指定訪問的元素,例如LRANGE user 0 -1 | |
- | - | |
LINDEX key index | 返回列表中指定索引的元素 | |
LSET key index value | 設(shè)置列表中指定索引位置的元素值争群,index不能超界 | |
LREM key count value | 從左邊刪除列表中與value相等的元素 | |
count > 0 | 從左至右搜索回怜,移除與 value 相等的元素,數(shù)量至多為 count 次 | |
count < 0 | 從右至左搜索祭阀,移除與 value 相等的元素鹉戚,數(shù)量至多為 -count次 | |
count = 0 | 移除列表中所有value值 | |
- | - | |
LTRIM key start stop | 去除指定范圍外的元素 | |
RPUSH listkey c abc c ab 123 ab bj ab redis list | ||
LTRIM listkey 0 -1 | # 什么都沒有去除 | |
LTRIM listkey 1 -1 | # 去掉左邊頭 | |
LTRIM listkey 1 10000 | ||
- | - | |
LINSERT key BEFORE | AFTER pivot value | 在列表中某個存在的值(pivot)前或后插入元素一次,key或pivot不存在专控,不進行任何操作 |
RPUSH lst 1 2 3 4 2 8
LINSERT lst AFTER 2 Python
LINSERT lst BEFORE 2 Ruby
阻塞(可以作為隊列使用)
如果彈出的列表不存在或者為空抹凳,就會阻塞
超時時間設(shè)置為0,就是永久阻塞伦腐,直到有數(shù)據(jù)可以彈出
如果多個客戶端阻塞在同一個列表上赢底,使用First In First Service原則,先到先服務(wù)
BLPOP key [key ...] timeout | 列表左邊阻塞彈出元素柏蘑。timeout是超時秒數(shù)幸冻,為0為永久阻塞。 |
BRPOP key [key ...] timeout | 列表左邊阻塞彈出元素 |
BRPOPLPUSH source destination timeout | 從一個列表尾部阻塞彈出元素壓入到另一個列表的頭部 |
# 阻塞式消息隊列
BLPOP MyQueue 0
RPUSH MyQueue hello
習(xí)題
微博某貼最后評論的50條
LPUSH u1234:forumid:comments "這是第1條評論"
LPUSH u1234:forumid:comments "這是第2條評論"
LPUSH u1234:forumid:comments "這是第3條評論"
LTRIM u1234:forumid:comments 0 49
2.6 hash散列
值是由?eld和value組成的map鍵值對
?eld和value都是字符串類型
HSET key field value | 設(shè)置單個字段咳焚。?eld不存在創(chuàng)建洽损,存在覆蓋value |
HSETNX key field value | 設(shè)置單個字段,要求?eld不存在革半。如果key不存在碑定,相當(dāng)于?eld也不存在 |
HMSET key field value [field value ...] | 設(shè)置多個字段 |
HLEN key | 返回字段個數(shù) |
HEXISTS key field | 判斷字段是否存在。key或者?eld不存在又官,返回0 |
HGET key field | 返回字段值 |
HMGET key field [field ...] | 返回多個字段值 |
HGETALL key | 返回所有的鍵值對 |
HKEYS key | 返回所有字段名 |
HVALS key | 返回所有值 |
HINCRBY key field increment | 在字段對應(yīng)的值上進行整數(shù)的增量計算 |
HINCRBYFLOAT key field increment | 在字段對應(yīng)的值上進行浮點數(shù)的增量計算 |
HDEL key field [field ...] | 刪除指定的字段 |
hash用途
節(jié)約內(nèi)存空間
每創(chuàng)建一個鍵延刘,它都會為這個鍵儲存一些附加的管理信息(比如這個鍵的類型,這個鍵最后一次被訪問的時間等等)
所以數(shù)據(jù)庫里面的鍵越多六敬,redis數(shù)據(jù)庫服務(wù)器在儲存附加管理信息方面耗費的內(nèi)存就越多碘赖,花在管理數(shù)據(jù)庫鍵上的CPU時間也會越多
不適合hash的情況
使用二進制位操作命令:因為Redis目前支持對字符串鍵進行SETBIT、GETBIT、BITOP等操作普泡,如果你想使用這些操作播掷,那么只能使用字符串鍵,雖然散列也能保存二進制數(shù)據(jù)
使用過期鍵功能:Redis的鍵過期功能目前只能對鍵進行過期操作撼班,而不能對散列的字段進行過期操作叮趴,因此如果你要對鍵值對數(shù)據(jù)使用過期功能的話,那么只能把鍵值對儲存在字符串里面
習(xí)題
用戶維度統(tǒng)計
統(tǒng)計數(shù)包括:關(guān)注數(shù)权烧、粉絲數(shù)眯亦、喜歡商品數(shù)、發(fā)帖數(shù)
用戶為Key般码,不同維度為Field妻率,Value為統(tǒng)計數(shù)
比如關(guān)注了5人
HSET user:100000 follow 5
HINCRBY user:100000 follow 1商品維度統(tǒng)計
統(tǒng)計值包括喜歡數(shù),評論數(shù)板祝,購買數(shù)宫静,瀏覽數(shù)等
HSET item:58000 fav 500
HINCRBY item:58000 fav 1緩存用戶信息
登錄后,反復(fù)需要讀取用戶的常用信息券时,最好的方式就是緩存起來
set user:001 "bob,18,20010101"
mset user:001:name "bob" user:001:age 18 user:001:birthday "20010101"
hmset user:001 name "bob" age 18 birthday "20010101 # 推薦使用
2.7 Set集合
集合的元素是無序的孤里、去重的,元素是字符串類型橘洞。
SADD key member [member ...] | 增加一個或多個元素捌袜,元素已存在將忽略 |
SREM key member [member ...] | 移除一個或多個元素,元素不存在自動忽略 |
SCARD key | 返回集合中元素的個數(shù)炸枣。不需要遍歷虏等。 |
SMEMBERS key | 返回集合中的所有元素(hash順序)。注意适肠,如果集合中元素過多霍衫,應(yīng)當(dāng)避免使用該方法 |
SISMEMBER key member | 元素是否是在集合中 |
# 拿數(shù)據(jù)的順序 不一定一致 ;
127.0.0.1:6379> sadd f1 perter
(integer) 1
127.0.0.1:6379> sadd f1 john may tom
(integer) 3
127.0.0.1:6379> SMEMBERS f1
1) "tom"
2) "may"
3) "perter"
4) "john"
127.0.0.1:6379> sadd f1 ben
(integer) 1
127.0.0.1:6379> sadd f2 john may tom perter ben
(integer) 5
127.0.0.1:6379> SMEMBERS f2
1) "tom"
2) "may"
3) "perter"
4) "john"
5) "ben"
127.0.0.1:6379> SMEMBERS f1
1) "tom"
2) "may"
3) "perter"
4) "john"
5) "ben"
SRANDMEMBER key [count] 隨機返回集合中指定個數(shù)的元素如果 count 為正數(shù)侯养,且小于集合基數(shù)敦跌,那么命令返回一個包含 count 個元素的數(shù)組,數(shù)組中的元素各不相同逛揩。如果 count 大于等于集合基數(shù)柠傍,那么返回整個集合
如果 count 為負(fù)數(shù),那么命令返回一個數(shù)組息尺,數(shù)組中的元素可能會重復(fù)出現(xiàn)多次携兵,而數(shù)組的長度為 count 的絕對值
如果 count 為 0疾掰,返回空
如果 count 不指定搂誉,隨機返回一個元素
集合運算
差集 | |
---|---|
SDIFF key [key ...] | 從第一個key的集合中去除其他集合和自己的交集部分 |
SDIFFSTORE destination key [key ...] | 將差集結(jié)果存儲在目標(biāo)key中 |
SADD number1 123 456 789
SADD number2 123 456 999
SDIFF number1 number2
交集 | |
---|---|
SINTER key [key ...] | 取所有集合交集部分 |
SINTERSTORE destination key [key ...] | 將交集結(jié)果存儲在目標(biāo)key中 |
SADD number1 123 456 789
SADD number2 123 456 999
SINTER number1 number2
并集 | |
---|---|
SUNION key [key ...] | 取所有集合并集 |
SUNIONSTORE destination key [key ...] | 將并集結(jié)果存儲在目標(biāo)key中 |
SADD number1 123 456 789
SADD number2 123 456 999
SUNION number1 number2
習(xí)題
微博的共同關(guān)注
需求:當(dāng)用戶訪問另一個用戶的時候,會顯示出兩個用戶共同關(guān)注哪些相同的用戶
設(shè)計:將每個用戶關(guān)注的用戶放在集合中静檬,求交集即可
2.8 SortedSet有序集合
類似Set集合炭懊,有序的集合并级。
每一個元素都關(guān)聯(lián)著一個浮點數(shù)分值(Score),并按照分值從小到大的順序排列集合中的元素侮腹。分值可以相同
ZADD key score member [score member ...] | 增加一個或多個元素嘲碧。如果元素已經(jīng)存在,則使用新的score |
ZCARD key | 返回集合的元素個數(shù) |
ZCOUNT key min max | 返回指定score范圍元素的個數(shù) |
ZSCORE key member | 顯示分值 |
ZINCRBY key increment member | 增加或減少分值抡句。increment為負(fù)數(shù)就是減少 |
ZRANGE key start stop [WITHSCORES] | 返回指定索引區(qū)間元素 如果score相同粤攒,則按照字典序lexicographical order 排列 默認(rèn)按照score從小到大蚌本,如果需要score從大到小排列,使用ZREVRANGE |
ZREVRANGE key start stop [WITHSCORES] | 返回指定索引區(qū)間元素 如果score相同履婉,則按照字典序lexicographical order 的 逆序 排列 默認(rèn)按照score從大到小,如果需要score從小到大排列斟览,使用ZRANGE |
ZRANK key member | 返回元素的排名(索引) |
ZREVRANK key member | 返回元素的逆序排名(索引) |
ZADD employees 3500 jack 4000 peter 4000 john 4500 tom 2500 david
ZCOUNT employees 3000 4000 # 空的毁腿;索引
ZCOUNT employees 0 1 # david jack
ZADD employees 3.2 david
ZSCORE employees david
ZINCRBY employees 1.5 jack
ZINCRBY employees -500 tom
ZRANGE employees 0 -1 WITHSCORES
ZRANK employees peter
ZREVRANGE employees 0 -1 WITHSCORES # 逆序后的索引0到-1,即返回所有
ZREVRANK employees peter
ZRANGEBYSCORE key min max [WITHSCORES][LIMIT offset count] 返回指定分?jǐn)?shù)區(qū)間的元素苛茂,返回score默認(rèn)屬于[min,max]之間已烤,元素按照score升序排列,score相同字典序
LIMIT中o?set代表跳過多少個元素妓羊,count是返回幾個胯究。類似于Mysql
使用小括號,修改區(qū)間為開區(qū)間躁绸,例如 (5 或者 (10唐片、5)
-inf和+inf表示負(fù)無窮和正無窮
ZREVRANGEBYSCORE key max min [WITHSCORES][LIMIT offset count] 降序返回指定分?jǐn)?shù)區(qū)間的元素 返回score默認(rèn)屬于[min,max]之間,元素按照score降序排列涨颜,score相同字典降序
ZRANGEBYSCORE employees 3500 4000
ZRANGEBYSCORE employees (4000 5000
ZRANGEBYSCORE employees 4000 5000 LIMIT 1 5 # 跳過一個费韭,返回至多5個
ZREVRANGEBYSCORE employees +inf -inf
ZREM key member [member ...] | 移除一個或多個元素。元素不存在庭瑰,自動忽略 |
ZREMRANGEBYRANK key start stop | 移除指定排名范圍的元素 |
ZREMRANGEBYSCORE key min max | 移除指定分值范圍的元素 |
ZREMRANGEBYRANK employees 0 1
ZREMRANGEBYSCORE employees 4000 5000
集合運算
并集
ZUNIONSTORE destination numkeys key [key ...] [WEIGHTS weight] [AGGREGATE SUM|MIN|MAX] | numkeys指定key的數(shù)量星持,必須 WEIGHTS選項,與前面設(shè)定的key對應(yīng)弹灭,對應(yīng)key中每一個score都要乘以這個權(quán)重 AGGREGATE選項督暂,指定并集結(jié)果的聚合方式 |
SUM: | 將所有集合中某一個元素的score值之和作為結(jié)果集中該成員的score值,默認(rèn) |
MIN: | 將所有集合中某一個元素的score值中最小值作為結(jié)果集中該成員的score值 |
MAX: | 將所有集合中某一個元素的score值中最大值作為結(jié)果集中該成員的score值 |
ZADD scores1 70 tom 80 peter 60 john
ZADD scores2 90 peter 60 ben
ZUNIONSTORE scores-all 2 scores1 scores2
ZUNIONSTORE scores-all1 2 scores1 scores2 AGGREGATE SUM
ZUNIONSTORE scores-all2 2 scores1 scores2 WEIGHTS 1 0.5 AGGREGATE SUM
交集
ZINTERSTORE destination numkeys key [key ...] [WEIGHTS weight] [AGGREGATE SUM|MIN|MAX] | numkeys指定key的數(shù)量穷吮,必須 WEIGHTS選項逻翁,與前面設(shè)定的key對應(yīng),對應(yīng)key中每一個score都要乘以這個權(quán)重 AGGREGATE選項捡鱼,指定并集結(jié)果的聚合方式 |
SUM: | 將所有集合中某一個元素的score值之和作為結(jié)果集中該成員的score值 |
MIN: | 將所有集合中某一個元素的score值中最小值作為結(jié)果集中該成員的score值 |
MAX: | 將所有集合中某一個元素的score值中最大值作為結(jié)果集中該成員的score值 |
習(xí)題
音樂排行榜怎樣實現(xiàn)
每首歌的歌名作為元素(先不考慮重復(fù))
每首歌的播放次數(shù)作為分值
ZREVRANGE來獲取播放次數(shù)最多的歌曲(就是最多播放榜了八回,云音樂熱歌榜,沒有競價,沒有權(quán)重)
redis3 版本與 2X版本變化較大缠诅;
# redis庫3.x版本
import redis
r = redis.Redis('127.0.0.1', 6379, db=3)
r.zadd('mboard', {'yellow':1, 'rolling in the deep':1, 'happy':1, 'just the way you are':1})
r.zadd('mboard', {'eye of the tiger':1, 'billie jean':1, 'say you say me':1, 'payphone':1})
r.zadd('mboard', {'my heart will go on':1, 'when you believe':1, 'hero':1})
r.zincrby('mboard', 50, 'yellow')
r.zincrby('mboard', 60, 'rolling in the deep')
r.zincrby('mboard', 68.8, 'my heart will go on')
r.zincrby('mboard', 70, 'when you believe')
allmusic = r.zrange('mboard', 0, -1, withscores=True)
print(type(allmusic))
for m in allmusic:
print(m)
print('-' * 30)
# 排行榜
musicboard = r.zrevrange('mboard', 0, 9, True)
print('歐美熱歌榜')
for i, m in enumerate(musicboard):
print(i, *m)
# redis庫 2.x版本
import redis
r = redis.Redis(host='192.168.142.135', port=6379, db=3)
r.zadd('mboard','yellow',1,'rolling in the deep',1,'happy',1,'just the way you are',1)
r.zadd('mboard','eye of the tiger',1,'billie jean',1,'say you say me',1,'payphone',1)
r.zadd('mboard','my heart will go on',1,'when you believe',1,'hero',1)
r.zincrby('mboard','yellow',50)
r.zincrby('mboard','rolling in the deep',60)
r.zincrby('mboard','my heart will go on',68.8)
r.zincrby('mboard','when you believe',70)
# 所有元素
allmusic = r.zrange('mboard', 0, -1, withscores=True)
print(type(allmusic))
for m in allmusic:
print(m)
print('-'*30)
# 排行榜
musicboard = r.zrevrange('mboard', 0, 9, True)
print('歐美熱曲榜')
for i, m in enumerate(musicboard):
print(i, *m)
新浪微博翻頁
新聞網(wǎng)站溶浴、博客、論壇管引、搜索引擎士败,頁面列表條目多,都需要分頁
blog這個key中使用時間戳作為score
ZADD blog 1407000000 '今天天氣不錯'
ZADD blog 1450000000 '今天我們學(xué)習(xí)Redis'
ZADD blog 1560000000 '幾個Redis使用示例'
ZREVRANGE blog 10 20
顯示所有博客中的最后的指定的條目
京東圖書暢銷榜
統(tǒng)計單日榜褥伴,計算出周榜單谅将、月榜單、年榜單 , 怎么做重慢?
每天統(tǒng)計一次排行榜
ZADD bk:it:01 1000 'java' 1500 'Redis' 2000 'haoop' 100 'scala' 80 'python'
ZADD bk:it:02 1020 'java' 1500 'Redis' 2100 'haoop' 120 'python' 110 'scala'
ZADD bk:it:03 1620 'java' 1510 'Redis' 3000 'haoop' 150 'storm' 120 'python'
求銷售前10名
ZUNIONSTORE bk:it:01-03 3 bk:it:01 bk:it:02 bk:it:03
行嗎戏自?
因為上面的單日榜單是累計值,所以不能直接使用并集伤锚,要指定聚合運算為MAX
ZUNIONSTORE bk:it:01-03 3 bk:it:01 bk:it:02 bk:it:03 AGGREGATE MAX
ZREVRANGE bk:it:01-03 0 9 WITHSCORES
注意:如果參與并集元素的元素太多擅笔,會耗費大量內(nèi)存和計算時間,可能會導(dǎo)致Redis服務(wù)阻塞屯援,如果非要計算猛们,選在空閑時間或備用服務(wù)器上計算。
另一種統(tǒng)計
# 常見:
ZADD bk:it:01 50 'java' 20 'Redis' 40 'haoop'
ZADD bk:it:02 70 'java' 30 'Redis' 20 'haoop'
ZADD bk:it:03 20 'java' 30 'Redis' 5 'haoop'
每天統(tǒng)計當(dāng)天銷售量狞洋,統(tǒng)計IT類圖書一段時間的最新銷售榜單
ZUNIONSTORE bk:it:01-03 3 bk:it:01 bk:it:02 bk:it:03 AGGREGATE SUM
ZREVRANGE bk:it:01-03 0 9 WITHSCORES