基本概念
共16个子数据库,分别为0-15。默认端口6379
作用:
- 数据库
- 缓存
- 消息中间件
**Redis是单线程的!**6.0以上是多线程的
Redis是基于内存操作,CPU不是Redis的瓶颈,Redis的瓶颈是机器的内存和网络的带宽,所以单线程来实现不奇怪。
但是单线程为啥还这么快?
多线程(CPU上下文切换)不一定比单线程效率高
核心:redis将所有的数据放在内存中,所以说使用单线程去操作效率是最高的,多线程(cpu上下文切换:耗时的操作),对于内存系统来说,如果没有上下文切换效率就是最高的。多次读写都在一个CPU上,在内存情况下,这就是最佳的方案。
基本数据类型
redis共五种基本数据类型,指的是value值的数据类型
String(字符串)
使用场景:
- 计数器
- 统计多单位的数量
- 粉丝数
- 对象缓存存储
redis> set test hello
OK
redis> exists test
1
redis> append test world # 往test追加 world,没有的话就是创建操作
10
redis> strlen test
10
redis> appen test1 word
ERR unknown command `appen`, with args beginning with: `test1`, `word`,
redis> append test1 "word"
4
redis> keys *
0
test
1
test1
redis> get test1
word
redis> get test
helloworld
redis> getrange test 0 3 # 截取字符串【0-3】
hell
redis> setrange test 1 xx # 替换字符串从1替换成xx
10
redis> get test
hxxloworld
####################################
redis> setex age 18 5 # 设置过期时间,先是时间,再是值
OK
redis> ttl age
12
redis> ttl age
10
redis> ttl age
9
redis> get age
5
####################################
redis> setnx test redis # 不存在时设置,存在则创建失败(分布式锁经常使用)
1
redis> get test
redis
redis> setnx test mysql
0
redis> get test
redis
####################################
redis> mset k1 v1 k2 v2 k3 v3 # 批量设置和批量获取
OK
redis> keys *
k3
k2
test
k1
redis> mget k1 k2 k3
v1
v2
v3
redis> msetnx k1 v1 k4 v4 # 原子性操作,要么一起成功,要么一起失败
0
redis> keys *
k3
k2
test
k1
redis> msetnx k4 v4
1
redis> keys *
k3
k1
k4
k2
test
####################################
redis> mset user:1:name zhangsan user:1:age 18 # 这种设计也是OK的
OK
redis> mget user:1:name user:1age
zhangsan
null
redis> mget user:1:name user:1:age
zhangsan
18
####################################
redis> getset db redis # 先获取,再设置,返回设置前的值
null
redis> get db
redis
redis> getset db mondb
redis
redis> get db
mondb
List(列表)
小结:
- 实际上是一个链表
- key如果不存在,创建新的链表
- key存在,新增新的内容
- 移除了所以的值,空链表,也代表不存在
- 在两边插入或者是改动值,效率最高。中间元素,相对来说效率较低
redis> LPUSH namelist pipi
1
redis> LPUSH namelist pip
2
redis> LPUSH namelist pipxia
3
redis> lrange name
ERR wrong number of arguments for 'lrange' command
redis> lrange name 0 -1
redis> lrange namelist 0 -1 # 理解成后进先出
pipxia
pip
pipi
redis> rpush namelist hello
4
redis> lrange namelist 0 -1
pipxia
pip
pipi
hello
redis> lpush namelist world
5
redis> lrange namelist 0 -1
world
pipxia
pip
pipi
hello
redis> lrange namelist 0 1
world
pipxia
####################################
redis> lpop namelist # 左边开始移除
world
redis> lrange namelist 0 -1
pipxia
pip
pipi
hello
redis> rpop namelist # 右边开始移除
hello
redis> lrange namelist 0 -1
pipxia
pip
pipi
####################################
redis> lindex namelist 0 # 根据下标获取相应的值
pipxia
redis> lindex namelist 1
pip
####################################
redis> llen namelist # 获取list的长度
3
####################################
redis> lrange namelist 0 -1
pipi
pip
pipxia
pipi
pp
pipi
redis> lrem namelist 2 pipi # 从左开始移除制定个数pipi
2
redis> lrange namelist 0 -1
pip
pipxia
pp
pipi
####################################
redis> ltrim namelist 1 2 # 从左开始截取namelist,同时namelist已经发生了改变
OK
redis> lrange namelist 0 -1
pipxia
pp
####################################
redis> lrange namelist 0 -1
pip
pipxia
pp
redis> rpoplpush namelist mylist # 从namelist右边移除一个元素并添加到mylist中
pp
redis> lrange namelist 0 -1
pip
pipxia
redis> lrange mylist 0 -1
pp
####################################
redis> lrange mylist 0 -1
pp
redis> lset mylist 0 pipixa # 替换制定下标位置为指定的值
OK
redis> lrange mylist 0 -1
pipixa
redis> lset mylist 1 pipi # 不存在报错
ERR index out of range
####################################
edis> lrange mylist 0 -1
hello
pipixa
redis> linsert mylist before pipixa ppp # 在指定的值pipixa前面添加ppp
3
redis> lrange mylist 0 -1
hello
ppp
pipixa
####################################
redis> lrange mylist 0 -1
xxxx
hello
ppp
pipixa
hello
redis> linsert mylist after hello www
6
redis> lrange mylist 0 -1
xxxx
hello
www
ppp
pipixa
hello
Set(集合)
set中的值不能重复
redis> sadd myset hello # 往set里面添加对应的值
1
redis> sadd myset hi
1
redis> sadd myset nihao
1
redis> smembers myset # 查看set集合中的所有的值
nihao
hi
hello
redis> sismember myset hi
1
redis> sismember myset pipi # 查看set集合中是否有该值,没有的话返回0,否则返回1
0
redis> sca
scard scan
redis> scard myset # 查看set集合中的myset的长度
3
####################################
redis> smembers myset
nihao
hi
hello
redis> srandmember myset # 随机取数
nihao
redis> srandmember myset
nihao
redis> srandmember myset
hi
redis> srandmember myset
hi
redis> srandmember myset
hello
redis> srandmember myset
nihao
####################################
redis> srem myset world # 删除一个值
0
redis> srem myset hi
1
redis> smembers myset
nihao
hello
redis> sadd myset hello # set值不能重复,此时不可添加
0
####################################
redis> smembers myset
hell
hello
helloworld
pipixia
pipi
nihao
pip
redis> spop myset # 随机移除myset集合中的元素
hello
redis> spop myset
helloworld
redis> spop myset
pipi
redis> smembers myset
pipixia
nihao
hell
pip
####################################
redis> sadd set1 world
1
redis> smove myset set1 hell # 将其中一个set集合的元素移动到另一个集合中
1
redis> smove myset set1 hell
0
redis> smembers set1
world
hell
####################################
# 微博和公众号的共同关注
redis> smembers key1
a
c
b
redis> smembers key2
e
c
d
redis> sdiff key1 key2 # 差集
a
b
redis> sinter key1 key2 # 交集
c
redis> sunion key1 key2 # 并集
e
b
c
a
d
Hash(哈希)
Map集合,key-map!本质上和String类型没有太大的区别,还是简单的key-value
应用场景:hash适合经常变更的数据,例如user、name、age。hash适合存储对象,而string适合存储字符串
redis> hset myhash key1 pipi # 设置值
1
redis> hget myhash key1 # 取值
pipi
redis> hmset mhash key2 hello key3 world # 批量设置值
OK
redis> hgetall mhash # 批量获取值
key2 hello
key3 world
redis> hmset mhash key2 wo key3 shi
OK
redis> hgetall mhash # 存在会覆盖
key2 wo
key3 shi
redis> hdel myhash key1 # 删除key1的
1
redis> hgetall myhash
####################################
redis> hlen mhash # 获取mhash的长度
2
redis> hkeys mhash # 获取键
key2
key3
redis> hvals mhash # 获取值
wo
shi
####################################
redis> hincrby myhash key1 3 # 加减
9
redis> hincrby myhash key1 -2
7
####################################
redis> hget myhash key1
hello
redis> hsetnx myhash key1 world
0
redis> hget myhash key1
hello
redis> hsetnx myhash key2 world # 存在即设置,不存在不设置
1
redis> hgetall myhash
key1 hello
key2 world
Zset(有序集合)
在set的基础上,增加了一个值,set k1 v1 zset k1 score1 v1 在set的基础上增加了排序
redis> zadd myzset 0 pipi
1
redis> zadd myzset 0 pipixia
1
redis> zrange myzset 0 -1
pipi
pipixia
redis> zadd myzset 2 hh
1
redis> zadd myzset 3 xx
1
redis> zrange myzset 0 -1
pipi
pipixia
hh
xx
####################################
redis> zadd salary 500 zhangsan
1
redis> zadd salary 1200 lisi
1
redis> zadd salary 6000 wangba
1
redis> zadd salary 1000 pipi
1
redis> zrange salary 0 -1 # 升序排序方法一
zhangsan
pipi
lisi
wangba
redis> zrangebyscore salary -inf +inf # 升序排序方法二 -inf表示负无穷 +inf表示正无穷
zhangsan
pipi
lisi
wangba
redis> zrevrangebyscore salary +inf -inf # 倒序排列
wangba
lisi
pipi
zhangsan
####################################
redis> zrange salary 0 -1
zhangsan
pipi
lisi
wangba
redis> zrem salary pipi # 移除元素
1
redis> zrange salary 0 -1
zhangsan
lisi
wangba
redis> zcard salary # 获取有序集合的个数
3
####################################
redis> zrangebyscore salary -inf +inf withscores # 除了排序以外,集合的成绩也会带出来
zhangsan
500
lisi
1200
wangba
6000
redis> zcount salary 500 1000 # 查看范围内有多少满足条件的集合
1
redis> zcount salary 500 1500
2
redis> zcount salary 500 6000
3
三大特殊类型
redis 有三大特殊类型geospatial、hyperloglog和Bitmaps
geospatial地理位置
在redis3.2版本推出,可以推算地理位置的信息,两地直接的距离,方圆几里的人。
redis> geoadd china:city 114.085947 22.547 sz # 添加城市的经纬度
1
redis> geoadd china:city 115.892151 28.676493 nc
1
redis> geoadd china:city 119.306239 26.075302 fuzhou
1
redis> geoadd china:city 114.177314 22.266416 xianggang
1
redis> geoadd china:city 116.405285 39.904989 beij
1
redis> geoadd china:city 117.190182 39.125596 tianj
1
redis> geoadd china:city 104.065735 30.659462 chend
1
redis> geoadd china:city 91.132212 29.660361 xiz
1
####################################
redis> geopos china:city sz # 获取sz的地理位置
114.08594459295272827
22.54699993773966327
redis> geopos china:city nc
115.89214950799942017
28.67649306190701708
####################################
redis> geodist china:city sz nc # 计算两地之间的直线距离
705381.2341
redis> geodist china:city sz nc km # 计算两地之间的距离,以km为单位
705.3812
####################################
#附件的人(获得所有附件的人的地址,定位)
redis> georadius china:city 114.085947 22.547 1000 km # 以114.085947 22.547经纬度,在china:city方圆1000公里内的地址
xianggang
sz
fuzhou
nc
redis> georadius china:city 114.085947 22.547 500 km
xianggang
sz
####################################
redis> georadius china:city 114.085947 22.547 500 km withdist withcoord count 2 # 以114.085947 22.547经纬度,筛选指定的结果
sz
0.0002
114.08594459295272827
22.54699993773966327
xianggang
32.5917
114.17731136083602905
22.26641644428547551
####################################
geredis> georadiusbymember china:city sz 1000 km # 找出china:city中sz附件1000km的地点
xianggang
sz
fuzhou
nc
####################################
redis> geohash china:city sz nc # 返回经纬度的字符串,字符串越接近,距离越近
ws10k0dcg10
wt47jhqhdv0
####################################
redis> zrange china:city 0 -1 # 查看所有元素
xiz
chend
xianggang
sz
fuzhou
nc
tianj
beij
####################################
redis> zrem china:city fuzhou # 移除元素
1
hyperloglog(基数)
场景:统计网站的用户访问量
如果允许容错,使用hyperloglog
如果不允许容错,使用set或其他数据类型
redis> pfadd mypf a b c d e f a b g h i # 和set有点类似
1
redis> pfcount mypf
9
redis> pfadd mypf2 a m n o p q
1
redis> pfcount mypf2
6
redis> pfmerge mypf mypf2 # 将mypf mypf2合并为mypf
OK
redis> pfcount mypf # 统计基数数量
14
Bitmaps(位储存)
统计用户信息,活跃或不活跃,登录和未登录,打卡和未打卡。这种两种状态的,使用bitmaps
Bitmaps位图:记录周一到周日的打卡。
redis> setbit sign 0 1
0
redis> setbit sign 1 1
0
redis> setbit sign 2 1
0
redis> setbit sign 3 1
0
redis> setbit sign 4 0
0
redis> setbit sign 5 0
0
redis> setbit sign 6 0
0
redis> setbit sign 7 0
####################################
redis> getbit sign 3 # 查看状态
1
redis> getbit sign 4
0
redis> getbit sign 5
0
####################################
redis> bitcount sign # 统计一周打卡的总数
4