【redis】redis基本操作和几种数据类型
狂神老师的视频地址:https://space.bilibili.com/95256449
1、基本操作
- select 3 :选择第三个数据库,一共有15个
- DBSIZE: 查看当前数据库大小
- keys * : 查看所有的key
- flushall: 清空全部
- flushDB:清空当前数据库
- EXISTS key:判断key是否存在,1表示存在,0表示不存在
- move key db:从db中删除key,默认的数据库是1
- expire key seconds: 设置key过期时间
- ttl key: 查看key剩余到过期时间
- type key: 查看key类型
redis是单线程,所有的数据存在内存当中,它的瓶颈是机器的内存和网络带宽。
那么为什么一个单线程的效率要不多线程要快呢?因为多线程是需要CPU调度上下文切换的,这个是比较费时间的,对于内存系统没有CPU调度,那么单线程就是比多线程要快
2、五大数据类型
官网介绍:
Redis是一个开源(BSD许可),内存存储的数据结构服务器,可用作数据库,高速缓存和消息队列代理。它支持字符串、哈希表、列表、集合、有序集合,位图,hyperloglogs等数据类型。内置复制、Lua脚本、LRU收回、事务以及不同级别磁盘持久化功能,同时通过Redis Sentinel提供高可用,通过Redis Cluster提供自动分区。
2.1、String
除了上面的基本命令外:
- appeend key value: 增加value到key后面,如果key不存在则新加
- strlen key: 查看key长度
【增减】
- incr key: 相当于key++,可应用于阅读量这样的需求里面
- decr key: 相当于key--
- incrby key nums: 相当于 key += nums
- decrby key nums: 相当于 key -= nums
【片段】
- getrange key start end: 获取key的 start到end
- setrange ket offset value: 指定对应偏移量的位置替换成value
【高级设置】
- setex key second value: setex expire,设置key的值和过期时间
- setnx key value: set while not exist,如果不存在设置值,否则设置失败,分布式锁里面经常用
- mset [key value...]: 批量设置多个key
- mget [key value...]: 批量获取多个key
- msetnx [key value...]: 如果不存在,同时设置多个key,这是一个原子性操作,要么全部成功,要么全部失败
【对象】
-
set user:1 {name:wcy,azge:3}: 设置一个user:1 对象,值为json字符串

这里的key设计的很巧妙,user:{id}:{filed},如此设计在Redis中完全是OK的
还可以不用json的方式

这个可以用到什么场景呢?就是key的复用,比如一个用户的粉丝,浏览量, 就可以用这样的结构: uid:123:fans:123 uis:123:readNum:123
【组合命令】
- getset key value: 获取并设置,如果没有返回nil,如果存在返回之前的值
2.2、List
在redis里面,可以通过双向取的方式将其完成栈、队列、阻塞队列
【压入和弹出】
- LPUSH key value: 从前边压入值
- RPUSH key value: 从后边压入值
- LPOP key: 弹出并返回队列头部
- RPOP key: 弹出并返回队列底部
【获取】
- LRANGE key start end: 获取start到end的key值,注意是闭区间,然后0 -1 就是逆序获取
- LIndex key index: 获取队列的具体位置的值
- LLen key: 获取k队列的长度
【移除和截断】
- Lrem key count value: 移除队列中指定个数对应的值(因为list可以重复嘛)
- Ltrim key start end: 截取指定的长度,注意这个是会修改key的
【组合操作】
- RPOPLPUSH source destination: 弹出目标队列最后元素压入到新队列,如果新队列没有会自动创建
【指定替换和插入】
-
EXISTS key: 这个之前讲过,一般指定替换前会线判断队列是否存在
-
lset key index value: 给队列的指定下标赋值,队列或位置不存在则报错
-
linsert key before|after pivot value: 在队列pivot值的前后后插入值

【小结】
redis里面的list其实是一个链表,类似linkedlist?
左右都可以插入值,如果key为空,即空链表,等同于key不存在
2.3、Set
【添加和查询】
- sadd key member [member...]: 添加集合
- smembers key: 查看集合所有元素
- srandmember key [count]: 随机抽选出指定数量的元素
- sismember key member: 查看集合key中是否存在member
- scard key: 获取集合中个数
【移除】
- srem key member: 移除key集合中指定元素
- spop key [count]: 随机删除指定数量元素
【组合命令】
- smove source destination member: 将元素从原集合移动到目标集合
【差集、并集、交集】
- sdiff key [key..]: 查询key1中有点key2中没有的
- sinter key [key..]: 查询key1和key2的并集
- sunion key [key..]: 查询key1和key2的交集
可以用于共同关注啊,共同好友这样的情景
2.4、Hash(哈希)
【添加和查询】
- hset key field value: 添加<field,value>值
- hget key field: 获取key哈希中的field的值
- hmset key field value [field value..]: 批量添加
- hmget key field [field..]: 批量获取
- hgetall key: 获取所有的键值对
【删除】
- hdel key field: 删除对应键值对
【获取】
- hlen key: 获取长度
- hexists key field: 判断指定的字段是否存在
- hkeys key: 获取哈希所有的field
- hvals key: 获取哈希所有的value
- hincrby、hdecrby、hsetnx这些和string的一样,不多赘述
【小结】
Hash更适合对象的存储,尤其是对于用户信息,经常变变更的数据。
虽然string可以通过key:1这样的方式存储对象
2.5、Zset(有序集合)
【添加】
127.0.0.1:6379> zadd myzset 1 one
(integer) 1
127.0.0.1:6379> zadd myzset 2 two
(integer) 1
127.0.0.1:6379> zadd myzset 3 three 4 four
(integer) 2
127.0.0.1:6379> zrange myzset 0 -1
1) "one"
2) "two"
3) "three"
4) "four"
【排序】
127.0.0.1:6379> zadd salary 1 1000
(integer) 1
127.0.0.1:6379> zadd salary 2 2000
(integer) 1
127.0.0.1:6379> zadd salary 3 3000
(integer) 1
127.0.0.1:6379> zrangebyscore salary -inf +inf #排序
1) "1000"
2) "2000"
3) "3000"
127.0.0.1:6379> zrangebyscore salary -inf +inf withscores #排序查询带位置
1) "1000"
2) "1"
3) "2000"
4) "2"
5) "3000"
6) "3"
127.0.0.1:6379> zrevrange salary 0 -1 #逆序查询
1) "3000"
2) "2000"
【查询】
127.0.0.1:6379> zrange salary 0 -1 #查询所有
1) "1000"
2) "2000"
3) "3000"
127.0.0.1:6379> zrem salary 1000 #移除
(integer) 1
127.0.0.1:6379> zcard salary #查询集合长度
(integer) 2
127.0.0.1:6379> zcount salary 1 2 #查询指定位置有多少元素
(integer) 1
【小结】
有序集合可以应用到例如下面这些情景:
- 重要消息
- 带权重的消息
3、三种特殊类型
3.1、geospatial
一共只有六个指令
- geoadd:插入城市纬、经度
一般是通过java程序导入,这里手动输入演示:
127.0.0.1:6379> geoadd china:city 116.40 39.90 beijin
(integer) 1
127.0.0.1:6379> geoadd china:city 121.47 31.23 shanghai
(integer) 1
- geopos:获取指定城市的纬、经度
127.0.0.1:6379> geopos china:city beijin shanghai
1) 1) "116.39999896287918091"
2) "39.90000009167092543"
2) 1) "121.47000163793563843"
2) "31.22999903975783553"
-
geodist:两个点之间的距离
单位:
m(默认单位)、km、mi(英里)、ft(英尺)
127.0.0.1:6379> geodist china:city beijin shanghai
"1067378.7564"
127.0.0.1:6379> geodist china:city beijin shanghai km
"1067.3788"
- georadius:已给定的纬、经度为中心,找出某一半径的元素
127.0.0.1:6379> georadius china:city 110 30 9000 km #获取110,30这个经纬度为中心找9000km内的城市
1) "shanghai"
2) "beijin"
127.0.0.1:6379> georadius china:city 110 30 9000 km withcoord #显示城市和经纬度
1) 1) "shanghai"
2) 1) "121.47000163793563843"
2) "31.22999903975783553"
2) 1) "beijin"
2) 1) "116.39999896287918091"
2) "39.90000009167092543"
127.0.0.1:6379> georadius china:city 110 30 9000 km withdist #显示城市和距离
1) 1) "shanghai"
2) "1105.9098"
2) 1) "beijin"
2) "1245.2858"
127.0.0.1:6379> georadius china:city 110 30 9000 km count 1 #显示指定数量城市
1) "shanghai"
- georadiusbymember:已给定的纬、经度为中心,找出指定距离的城市
127.0.0.1:6379> georadiusbymember china:city beijin 10000 km
1) "shanghai"
2) "beijin"
- geohash:返回一个位置或多个位置的11位字符串(没什么用)
127.0.0.1:6379> geohash china:city beijin shanghai
1) "wx4fbxxfke0"
2) "wtw3sj5zbj0"
3.2、HyperLogLog
在 Redis 里面,每个 HyperLogLog 键只需要花费 12 KB 内存,就可以计算接近 2^64 个不同元素的基 数。这和计算基数时,元素越多耗费内存就越多的集合形成鲜明对比。
什么是基数
比如数据集 {1, 3, 5, 7, 5, 7, 8}, 那么这个数据集的基数集为 {1, 3, 5 ,7, 8}, 基数(不重复元素)为5。 基数估计就是在误差可接受的范围内,快速计算基数。
redis 127.0.0.1:6379> PFADD w3ckey "redis" #添加基数
1) (integer) 1
redis 127.0.0.1:6379> PFADD w3ckey "mongodb"
1) (integer) 1
redis 127.0.0.1:6379> PFADD w3ckey "mysql"
1) (integer) 1
redis 127.0.0.1:6379> PFCOUNT w3ckey #计算基数个数
(integer) 3
redis 127.0.0.1:6379> PFMERGE w3ckey w3ckey1 w3ckey2 #两个并集返回给w3ckey
OK
【小结】
应用场景例如计算访问人数的时候,一个人的重复访问需要去重,一般是用set,但是数量特别多的时候比较麻烦。
而这个场景的核心任务是计数,而不是保存所有的用户id,而HyperLogLog占用内存非常小,有0.81%的错误率(可以忽略不计),就适合这种场景了
3.3、Bitmaps
使用场景:统计用户信息,活跃不活跃、打卡未打卡等等
Bitmaps位图,都是操作二进制来进行记录,只有0和1两个状态
例如记录一周打卡情况
C:\Users\86155>redis-cli
127.0.0.1:6379> setbit sign 0 1
(integer) 0
127.0.0.1:6379> setbit sign 1 0
(integer) 0
127.0.0.1:6379> setbit sign 2 1
(integer) 0
127.0.0.1:6379> setbit sign 3 0
(integer) 0
127.0.0.1:6379> getbit sign 1 #查看某天打卡情况
(integer) 0
127.0.0.1:6379> getbit sign 3
(integer) 0
127.0.0.1:6379> getbit sign 2
(integer) 1
127.0.0.1:6379> bitcount sign #查看一周打卡情况
(integer) 2
浙公网安备 33010602011771号