redis(remote dictionary server)属于一个开源的基于键值对的非关系型数据库(NoSQL),属于单线程服务
最大的特点是工作在内存中,可以用于消息列队和缓存,和memcache不同,1s可以处理10w条数据
redis支持多种数据类型(string字符串、hash哈希、list列表、set集合、zset有序集合)
通过上述五种数据类型开发了很多功能:
bitmaps位图:一个键值对存放512M(4294967295bit)的数据,字节是位的8倍,使用位图更加方便节省空间,存放二进制
hyperloglog:用来统计流量,通过用户登录来自动触发计算,使用了一个计数器
GEO地理信息定位:标识地点,你所在的位置(坐标)方圆范围内有的学校、医院等
事务:
流水线:把多条命令打包成1条命令,最后一下传入redis识别
键过期:设置键值对的存在时长,到期直接从内存中删除(但是硬盘中还是存在)
复制:复制到其他数据库
哨兵:监控,负责监控后端服务器的稳定性,故障转移工具(将故障后的服务器移除群集),多个哨兵用来确定故障的误判,保障故障的真实性。多数服从少数
持久化:长效保存,内存通过持久化将数据导入硬盘,硬盘中保存了键值对中的数据,分为两种方式,快照和日志
redis安装
[root@localhost ~]# tar zxf redis-5.0.5.tar.gz -C /usr/src
[root@localhost ~]# cd /usr/src/redis-5.0.5/
[root@localhost redis-5.0.5]# make && make install
redis分类
redis服务端运行命令(刚安装完)redis-server
启动时会以阻塞的方式开启(打开另一终端,使用redis-cli即可)
_._
_.-``__ ''-._
_.-`` `. `_. ''-._ Redis 5.0.5 (00000000/0) 64 bit
.-`` .-```. ```\/ _.,_ ''-._
( ' , .-` | `, ) Running in standalone mode
|`-._`-...-` __...-.``-._|'` _.-'| Port: 6379
| `-._ `._ / _.-' | PID: 35422
`-._ `-._ `-./ _.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' | http://redis.io
`-._ `-._`-.__.-'_.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' |
`-._ `-._`-.__.-'_.-' _.-'
`-._ `-.__.-' _.-'
`-._ _.-'
`-.__.-'
35422:M 16 Dec 2019 15:59:37.338 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
[root@localhost redis-5.0.5]# echo 511 > /proc/sys/net/core/somaxconn
[root@localhost redis-5.0.5]# cat /proc/sys/net/core/somaxconn
511
35422:M 16 Dec 2019 15:59:37.338 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
[root@localhost redis-5.0.5]# echo 'vm.overcommit_memory = 1' >> /etc/sysctl.conf
[root@localhost redis-5.0.5]# sysctl -p
vm.overcommit_memory = 1
35422:M 16 Dec 2019 15:59:37.338 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.
[root@localhost redis-5.0.5]# redis-server /usr/src/redis-5.0.5/redis.conf
role(角色) M:主服务器 S:从服务器 C:子进程 X:哨兵
redis-server
redis客户端允许命令redis-cli [option] -h 指定连接主机 默认127.0.0.1 -p 指定端口 默认6379
[root@localhost redis-5.0.5]# redis-cli
127.0.0.1:6379> ping #表示没有问题
PONG
redis配置
[root@localhost ~]# vim /usr/src/redis-5.0.5/redis.conf
修改:
daemonize yes
bind 0.0.0.0
logfile "/root/logredis.log"
redis特点
1、速度快 官方给出的理论速度为10w次/秒
(1)工作在内存中
(2)使用c语言编写,距离操作系统较近
(3)单线程系统,避免多线程争抢资源
2、基于键值对的数据结构服务器
3、功能丰富
4、简单稳定:代码量少,10w行代码
5、客户端语言多
6、持久化
7、复制、高可用
结束redis服务端的方式
1、在命令行中
redis-cli -h host -p port shutdown
2、结束进程
3、在客户端命令行执行
127.0.0.1:6379>shutdown
运行多个redis
终端1:
[root@localhost ~]# cp /usr/src/redis-5.0.5/redis.conf /root/redis6380.conf
[root@localhost ~]# redis-server /usr/src/redis-5.0.5/redis.conf
终端2:
[root@localhost ~]# vim redis6380.conf
修改:
port 6380
[root@localhost ~]# redis-server redis6380.conf
终端3:
[root@localhost ~]# redis-cli
127.0.0.1:6379> ping
PONG
127.0.0.1:6379> exit
[root@localhost ~]# redis-cli -p 6380
127.0.0.1:6380> ping
PONG
127.0.0.1:6380> exit
redis命令
全局命令
1、查看当前redis中的键值对
keys *
2、设置键值对
set key value
通过set设置出来的数据类型都是字符串数据类型(string)
127.0.0.1:6380> set a b 键a值b
OK
127.0.0.1:6380> keys *
1) "a"
用于查看键值对中数据(get key)不通用
127.0.0.1:6380> get a
"b"
3、查看当前redis中键的总和
dbsize
127.0.0.1:6380> set a b
OK
127.0.0.1:6380> set b c
OK
127.0.0.1:6380> set c d
OK
127.0.0.1:6380> keys *
1) "b"
2) "c"
3) "a"
127.0.0.1:6380> dbsize
(integer) 3 当前redis有3个键值对
4、查看键是否存在
exists key
127.0.0.1:6380> exists a 返回1为存在
(integer) 1
127.0.0.1:6380> exists aa 返回0为不存在
(integer) 0
5、删除键值对
del key
127.0.0.1:6380> del a 删除成功
(integer) 1
127.0.0.1:6380> keys *
1) "b"
2) "c"
6、设置键过期时间
expire key seconds
设置秒级别过期时间,一旦键值对设置过期时间,超过过期时间将会被redis自动删除
127.0.0.1:6380> expire b 20
(integer) 1
耐心等待20s
127.0.0.1:6380> keys *
1) "c"
ttl:查看键值对过期剩余时间(如果在过期时间内,重新设置过期时间,过期时间将会被刷新)
大于0:该键值对剩余的过期时间
-1:该键值对没有设置过期时间
-2:该键值对不存在,或者已经过期
127.0.0.1:6380> expire c 100
(integer) 1
127.0.0.1:6380> ttl c
(integer) 89
7、查看键值对数据类型
type key
127.0.0.1:6380> type hello
string
通过set设置出来的数据类型都是字符串数据类型(string)
127.0.0.1:6380> rpush list a b c d e
(integer) 5
127.0.0.1:6380> sadd myset a b c d e
(integer) 5
127.0.0.1:6380> type list
list
127.0.0.1:6380> type myset
set
8、内部编码
每个数据类型下面都有一种或者多种内部编码来进行实现,redis会自动根据数据选择合适的内部编码进行使用
string(字符串) 3中 int(8) embstr(9-44) raw(>44)
hash(哈希) 2种 hashtable ziplist
list(列表) 1种 quicklist
set(集合) 2种 hashtable intset
zset(有序集合) 2种 skiplist ziplist
查看内部编码的方式 object encoding key
内部编码的优点
1)可以在不同的场景发挥不同的作用
2)改进内部编码对于命令或者键值对的结构不会产生任何影响
字符串数据类型,一个键值对最多存放512M数据类型,在字符串数据类型中,内容可以是图片、视频或者音频文件,只要在512M大小以内,皆可存储,属于redis最基本的数据类型,其余四种数据类型都是基于字符串数据类型开发
局部命令
设置数据类型命令
set key value [ex seconds] [px milliseconds] [nx | xx]
ex seconds
设置秒级别过期时间(仅能给字符串数据类型设置)
px milliseconds
设置毫秒级别过期时间
nx
表示键值对不存在才能设置成功,用于创建新的键值对
xx
表示键值对存在才能设置成功,用于更新旧的键值对
得到键值对中的值:get key
批量设置键值对:mset key1 value key2 value...
批量查看键值对:mget key1 key2
计数
对于字符串来说是不能增加或者减少,只能针对数值
除了带float字样的命令,其余都是对整数进行增加或者减少
incr kye
给指定的键值对增加数值
127.0.0.1:6379> set a 1
OK
127.0.0.1:6379> incr a
(integer) 2
127.0.0.1:6379> incr a
(integer) 3
127.0.0.1:6379> incr a
(integer) 4
127.0.0.1:6379> incr a
(integer) 5
decr key
给指定的键值对减少数值
127.0.0.1:6379> decr a
(integer) 4
127.0.0.1:6379> decr a
(integer) 3
127.0.0.1:6379> decr a
(integer) 2
127.0.0.1:6379> decr a
(integer) 1
incrby key 数值
给指定的键值对增加指定数值
127.0.0.1:6379> incrby a 100
(integer) 101
127.0.0.1:6379> incr redis
(integer) 1
127.0.0.1:6379> decr red
(integer) -1
decrby key 数值
给指定的键值对减少指定数值
127.0.0.1:6379> decrby a 50
(integer) 51
incrbyfloat key 数值
给指定的键值对增加指定的浮点数(减少使用负值)
127.0.0.1:6379> incrby a 100.1 #不能对整数进行操作
(error) ERR value is not an integer or out of range
127.0.0.1:6379> incrbyfloat a 10.1
"61.1"
追加值
append key value
在已经存在的键值对后面追加值,等同于合并
127.0.0.1:6379> append b ' redis is easy to learn' #添加是先加空格用于区分
(integer) 25
127.0.0.1:6379> get b #两个值存在于一个键中
"c redis is easy to learn "
计算字符串的长度
strlen key
127.0.0.1:6379> strlen b
(integer) 25
127.0.0.1:6379> set f '你好'
OK
127.0.0.1:6379> strlen f
(integer) 6
127.0.0.1:6379> get f
"\xe4\xbd\xa0\xe5\xa5\xbd"
redis -cli –raw 用该方法登录redis可以将中文正常显示(一个汉字3个字节)
[root@localhost ~]# redis-cli --raw
127.0.0.1:6379> get f
你好
设置并返回原值
getset key value
查看a键中的值,再将a键中的值设置为hello
127.0.0.1:6379> getset a hello
61.1
设置指定位置的字符
setrange key offset value
键中值的第一位为第0位
127.0.0.1:6379> set redis 12345
OK
127.0.0.1:6379> setrange redis 0 a
5
127.0.0.1:6379> get redis
a2345
如果设置的位置超过了字符串本身的长度会在指定位置写入数据,中间用0字节添加到指定长度
\x00零字节,用于占位,相当于占位符,但是没有实际意义
127.0.0.1:6379> setrange redis 10 b
11
127.0.0.1:6379> get redis
"12345\x00\x00\x00\x00\x00a"
127.0.0.1:6379> strlen redis
11
键值中的最大长度为536870911=512M/8
127.0.0.1:6379> setrange redis 536870912 a
ERR string exceeds maximum allowed size (512MB)
127.0.0.1:6379> setrange redis 536870911 a
536870912
获取部分字符串数据
getrange key start(起始位置) end(结束位置)
如果在不知道键值有多长时,-1代表最后一位
127.0.0.1:6379> getrange b 3 23
"edis is easy to learn"
字符串内部编码
int 8字节长度整形,最大为9223372036854775807位整数
127.0.0.1:6379> set f 9223372036854775809
OK
127.0.0.1:6379> object encoding f #超过最大数值将会自动变为embstr
"embstr"
embstr 不大于44个字节的字符串
raw 大于44字节的字符串
哈希
所有的语言几乎都支持hash类型,在redis中哈希类型数据键值对本身又是键值对结构,映射关系如下:key field value
key=表 field=字段 value=字段中的值
redis采用了字典结构,而hash属于字典结构的代表,存放了字段和字段值之间的映射,一个hash类型中可以包含2的32次方-1个字段
建立哈希类型键值对的方式
hset key field value
127.0.0.1:6379> hset cyj sex nan
(integer) 1
127.0.0.1:6379> hset cyj class sjk
(integer) 1
查看键值对中的值
hget key field
127.0.0.1:6379> hget cyj class
"sjk"
127.0.0.1:6379> hget cyj sex
"nan"
删除field
hdel key field [field...]
127.0.0.1:6379> hdel cyj class
(integer) 1
127.0.0.1:6379> hdel cyj sex
(integer) 1
127.0.0.1:6379> hget cyj class #返回空
(nil)
127.0.0.1:6379> hget cyj sex
(nil)
随着键中最后一个字段的删除键也会消失
==键值对中键和值时相互依存的关系,有键才有值,有值必有键,键和值不能单独存在==
计算字段个数
hlen key
127.0.0.1:6379> hlen cyj
(integer) 2
批量设置和获取键值对
hmset key field value [field value...]
127.0.0.1:6379> hmset cyj sex nan age 23 class sjk habbit paoniu
127.0.0.1:6379> hlen cyj
(integer) 4
hmget key field [field]...
127.0.0.1:6379> hmget cyj sex age clsss habbit
1) "nan"
2) "23"
3) (nil)
4) "paoniu"
判断字段是否存在
存在返回1,不存在返回0hexists key field
127.0.0.1:6379> hexists cyj class
(integer) 1
127.0.0.1:6379> hexists cyj classdd
(integer) 0
查看所有字段
hkeys key
127.0.0.1:6379> hkeys cyj
1) "sex"
2) "age"
3) "class"
4) "habbit"
查看所有字段中的值
hvals key
127.0.0.1:6379> hvals cyj
1) "nan"
2) "23"
3) "sjk"
4) "paoniu"
查看所有字段和值
hgetall key
127.0.0.1:6379> hgetall cyj
1) "sex"
2) "nan"
3) "age"
4) "23"
5) "class"
6) "sjk"
7) "habbit"
8) "paoniu"
查看值的长度
hstrlen key field
127.0.0.1:6379> hstrlen cyj sex
(integer) 3
127.0.0.1:6379> hstrlen cyj habbit
(integer) 6
哈希内部编码
ziplist:当hash类型的元素数量小于512个且每个元素的字节长度小于64字节,使用ziplist实现数据的紧凑连续性存储
hashtable:当不满足ziplist条件意味着数据量过大,需要使用hashtable的方式作为内部编码来存储数据
可以通过redis的配置文件来改变512或者64
[root@localhost ~]# vim /usr/src/redis-5.0.5/redis.conf
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list列表
列表用于存放多个有序的可重复的字符串,每个字符串在列表中称之为元素,一个列表最多可以存放2的32次方-1个元素,且元素属于有序形式,通过索引下标实现数据的有序化
类型 命令
添加 rpush lpush linsert
查看 lrange lindex llen
删除 lpop rpop lrem ltrim
修改 lset
添加列表的语法
右写入:rpush key value [value...]
127.0.0.1:6379> rpush list1 a b c d e
(integer) 5
127.0.0.1:6379> rpush list1 a b c d e
(integer) 10
127.0.0.1:6379> lpush list1 a b c d e
(integer) 15
127.0.0.1:6379> lrange list1 0 -1
1) "e"
2) "d"
3) "c"
4) "b"
5) "a"
6) "a"
7) "b"
8) "c"
9) "d"
10) "e"
11) "a"
12) "b"
13) "c"
14) "d"
15) "e"
左写入:lpush key value [value...]
向指定的元素前或者后写入元素
linsert key before | after pivot value
只能在检索到的第一个符合要求的元素前或者后添加新的元素,如果指定元素有多个,只检索第一个
127.0.0.1:6379> linsert list1 before h redis #在list1中在找到的第一个h之前加入redis
(integer) 26
127.0.0.1:6379> lrange list1 0 -1
1) "j"
2) "redis"
3) "h"
4) "i"
5) "g"
6) "f"
查看指定范围的元素
lrange key star end
127.0.0.1:6379> lrange list1 10 15 #第11个到16个
1) "a"
2) "a"
3) "b"
4) "c"
5) "d"
6) "e"
获取指定索引下标的元素
lindex key 索引下标
一次只能查看一个元素,如果需要批量查看需使用lrange
127.0.0.1:6379> lindex list1 10
"a"
11) "a" 减1即是他的下标
查看当前列表的元素个数
llen key
127.0.0.1:6379> llen list1
(integer) 26
删除
lpop 左删除(左弹出) 删除列表中左侧的第一个元素
rpop 右删除(右弹出) 删除列表中右侧的第一个元素
lrem 删除指定的元素
ltrim 保留指定的元素
lpop左删除(左弹出)
127.0.0.1:6379> lpop list1
"j"
127.0.0.1:6379> lpop list1
"redis"
127.0.0.1:6379> lpop list1
"h"
127.0.0.1:6379> llen list1
(integer) 23
rpop右删除(右弹出)
127.0.0.1:6379> rpop list1
"j"
127.0.0.1:6379> rpop list1
"h"
127.0.0.1:6379> rpop list1
"i"
127.0.0.1:6379> llen list1
(integer) 20
lrem 删除指定的元素
lrem key count value
count表示删除的数量,写入count有三种类型
count大于0,从左往右删除,删除count个value
count小于0,从右往左删除,删除count个value
count等于0,删除所有value
127.0.0.1:6379> lrem list1 3 c #从左往右删除3个c元素
(integer) 3
127.0.0.1:6379> lrem list1 -2 b #从右往左删除2个b元素
(integer) 2
127.0.0.1:6379> lrem list1 0 a #删除所有list1中的所有a
(integer) 3
ltrim 保留指定的元素
ltrim key start end
127.0.0.1:6379> ltrim list1 0 2 #保留第1个到第三个元素
OK
127.0.0.1:6379> lrange list1 0 -1
1) "i"
2) "g"
3) "f"
修改
lset 修改指定位置的元素lset key index newvalue
127.0.0.1:6379> lset list1 2 redis #修改第三个元素为redis
OK
127.0.0.1:6379> lrange list1 0 -1
1) "i"
2) "g"
3) "redis"
阻塞操作
也叫阻塞式弹出,当并发太大,进行阻塞,缓解压力
blpop key [key] timeout
brpop key [key] timeout
阻塞操作会去寻找可用的列表内容,当找到要求的列表时,直接弹出数据,如果没有找到符合要求的数据,阻塞操作将会直接把用户进行阻塞直到出现该数据,或者阻塞时间超过timeout秒为止
列表中的内部编码
quicklist 快速列表 属于ziplist和linkedlist的结合,是一种双向链表结构,既可以实现数据的紧凑存储,还能实现数据的快速引用
集合
集合中用于存放多个无序字符串,集合之间可以进行求交并差集,每个存放在集合中的字符串叫做元素,每个集合中可以存放2的32次方-1个元素
集合的特点
(1)元素无序存放
(2)元素不可重复
集合内的操作
创建集合并添加元素
sadd key element [element...]
127.0.0.1:6379> sadd pjf sing dance rap basketball
(integer) 4
删除元素
srem key element [element...]
127.0.0.1:6379> srem pjf sing
(integer) 1
查看集合元素个数
scard key
127.0.0.1:6379> scard pjf
(integer) 3
随机从集合中返回指定个数的元素(不会删除元素)
srandmember key [count]
如果count不写默认1
127.0.0.1:6379> sadd user1 a b c d e f g h i j k l m n
(integer) 14
127.0.0.1:6379> srandmember user1
"j"
127.0.0.1:6379> srandmember user1 5
1) "n"
2) "k"
3) "f"
4) "d"
5) "l"
从集合中随机删除元素
spop key [count]
默认为1
127.0.0.1:6379> spop user1 5
1) "d"
2) "e"
3) "a"
4) "c"
5) "n"
127.0.0.1:6379> scard user1
(integer) 9
查看集合内所有元素
smembers key
127.0.0.1:6379> smembers user1
1) "g"
2) "k"
3) "i"
4) "f"
5) "m"
6) "j"
7) "h"
8) "l"
9) "b"
127.0.0.1:6379> smembers pjf
1) "basketball"
2) "rap"
3) "dance"
集合之间的
求交集
sinter key key...
127.0.0.1:6379> sadd mp music study game art
(integer) 4
127.0.0.1:6379> sadd fy art sleep eat sport
(integer) 4
127.0.0.1:6379> sinter mp fy
1) "art"
求并集
sunion key key...
127.0.0.1:6379> sunion fy mp
1) "study"
2) "art"
3) "sleep"
4) "game"
5) "eat"
6) "sport"
7) "music"
求差集
sdiff key key...
以第一个写入的集合为准,差集为第一个拥有而其他集合都没有的数据
mp在前就输出mp有而fy没有的值
fy在前就输出fy有而mp没有的值
127.0.0.1:6379> sdiff mp fy
1) "study"
2) "game"
3) "music"
127.0.0.1:6379> sdiff fy mp
1) "sport"
2) "eat"
3) "sleep"
保存交并差集的结果
sinterstore destination key key...
127.0.0.1:6379> sinterstore mp:fyj:j mp fy
(integer) 1
127.0.0.1:6379> smembers mp:fyj:j
1) "art"
sunionstore destination key key...
sdiffstore destination key key...
集合的内部编码
intset 当集合中的元素小于512个且所有元素都是整数时,使用intset作为内部编码
hashtable 当不满足intset的条件时使用hashtable作为内部编码
127.0.0.1:6379> object encoding mp:fyj:j
"hashtable"