5.Redis类型详解

五大基本数据类型

String


  1. 追加字符串,字符串长度
127.0.0.1:6379> set k1 v1
OK
127.0.0.1:6379> get k1
"v1"
127.0.0.1:6379> keys *
1) "k1"
127.0.0.1:6379> exists k1
(integer) 1
127.0.0.1:6379> APPEND k1 "hello" # 追加字符串,如果当前字符串不存在则相当于set key
(integer) 7
127.0.0.1:6379> get k1
"v1hello"
127.0.0.1:6379> STRLEN k1 # 获取字符串长度
(integer) 7
127.0.0.1:6379> APPEND k1 "wz"
(integer) 9
127.0.0.1:6379> get k1
"v1hellowz"

  1. 自增、自减、设置步长
127.0.0.1:6379> set views 0
OK
127.0.0.1:6379> get views
"0"
127.0.0.1:6379> incr views # 自增1
(integer) 1
127.0.0.1:6379> get views
"1"
127.0.0.1:6379> incr views
(integer) 2
127.0.0.1:6379> decr views # 自减1
(integer) 1
127.0.0.1:6379> get views
"1"
127.0.0.1:6379> decr views
(integer) 0
127.0.0.1:6379> get views
"0"
127.0.0.1:6379> decr views
(integer) -1
127.0.0.1:6379> get views
"-1"
127.0.0.1:6379> INCRBY views 10 # 设置步长指定增量
(integer) 9
127.0.0.1:6379> get views
"9"
127.0.0.1:6379> DECRBY views 5 # 设置步长指定减量
(integer) 4
127.0.0.1:6379> get views
"4"
  1. 字符串范围:截取与替换
127.0.0.1:6379> set k1 "hello,warms"
OK
127.0.0.1:6379> get k1
"hello,warms"
127.0.0.1:6379> GETRANGE k1 0 3 # 截取字符串 [0,3]
"hell"
127.0.0.1:6379> GETRANGE k1 0 -1 #获取全部字符串
"hello,warms"
127.0.0.1:6379> set k2 abcdefg
OK
127.0.0.1:6379> get k2
"abcdefg"
127.0.0.1:6379> SETRANGE k2 1 xx # 替换指定位置开始的字符串
(integer) 7
127.0.0.1:6379> get k2
"axxdefg"
  1. setex、setnx:设置过期时间,当前值不存在设置
# setex (set with expire)
# setnx (set if noy exist)在分布式锁中常常使用
127.0.0.1:6379> setex k3 30 "hello" 
OK
127.0.0.1:6379> ttl k3
(integer) 26
127.0.0.1:6379> setnx mykey "redis" # 创建成功
(integer) 1
127.0.0.1:6379> keys *
1) "k2"
2) "mykey"
3) "k1"
127.0.0.1:6379> setnx mykey "mogodb" # 创建失败
(integer) 0
  1. 设置、获取多个键值
127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3 # 同时设置多个值
OK
127.0.0.1:6379> keys * 
1) "k2"
2) "k3"
3) "k1"
127.0.0.1:6379> mget k1 k2 k3 # 同时获取多个值
1) "v1"
2) "v2"
3) "v3"
127.0.0.1:6379> msetnx k1 v1 k2 v2 
(integer) 0
127.0.0.1:6379> msetnx k1 v1 k4 v4 # 原子性操作,要么一起成功要么一起失败
(integer) 0
  1. 对象
set user:1 {name:zhangsan, age:3} 设置一个user:1 对象 值为json字符来保存一个对象


# 这里的key是一个巧妙地设计:user:{id}:{field} 例如文章浏览量:set article:1:views 0
127.0.0.1:6379> mset user:1:name zhangsan user:1:age 2
OK
127.0.0.1:6379> mget user:1:name user:1:age
1) "zhangsan"
2) "2"

  1. 组合命令 getset:先get 在set
127.0.0.1:6379> getset db "redis" # 如果不存在值则返回null
(nil)
127.0.0.1:6379> get db
"redis"
127.0.0.1:6379> getset db "mogodb" # 如果存在值则获取原来的值并设置新的值
"redis"
127.0.0.1:6379> get db
"mogodb"

String类型使用场景:

  • 计数器
  • 统计多单位数量uid:123123:follow
  • 粉丝数
  • 对象缓存

List


基本数据类型,列表。
在redis中可以将list用作栈、队列、阻塞队列!
所有的list命令以 l l l开头

  1. 插入数据
127.0.0.1:6379> lpush list one # 将一个值或多个值加入列表头部(左)
(integer) 1
127.0.0.1:6379> lpush list two
(integer) 2
127.0.0.1:6379> lpush list three
(integer) 3
127.0.0.1:6379> lrange list 0 -1 # 获取list中的值
1) "three"
2) "two"
3) "one"
127.0.0.1:6379> lrange list 0 1 # 通过区间获取具体的值
1) "three"
2) "two"
127.0.0.1:6379> rpush list right # 将一个或多个值放入列表尾部(右)
(integer) 4
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "two"
3) "one"
4) "right"
  1. 移除数据
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "two"
3) "one"
4) "right"
127.0.0.1:6379> lpop list # 从左侧移除数据
"three"
127.0.0.1:6379> lrange list 0 -1
1) "two"
2) "one"
3) "right"
127.0.0.1:6379> rpop list # 从右侧移除数据
"right"
127.0.0.1:6379> lrange list 0 -1
1) "two"
2) "one"
  1. 通过下标获得某一个值
127.0.0.1:6379> lrange list 0 -1
1) "two"
2) "one"
127.0.0.1:6379> lindex list 1
"one"
127.0.0.1:6379> lindex list 0
"two"
127.0.0.1:6379> 
  1. list有多少元素
127.0.0.1:6379> llen list
(integer) 2
  1. 移除指定的值
127.0.0.1:6379> lpush list three
(integer) 3
127.0.0.1:6379> lpush list three
(integer) 4
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "three"
3) "two"
4) "one"
127.0.0.1:6379> lrem list 1 one # 移除list中指定个数的value,精确匹配
(integer) 1
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "three"
3) "two"
127.0.0.1:6379> lrem list 2 three
(integer) 2
127.0.0.1:6379> lrange list 0 -1
1) "two"
  1. 只保留某一部分的元素
127.0.0.1:6379> rpush mylist "hello"
(integer) 1
127.0.0.1:6379> rpush mylist "hello1"
(integer) 2
127.0.0.1:6379> rpush mylist "hello12"
(integer) 3
127.0.0.1:6379> rpush mylist "hello13"
(integer) 4
127.0.0.1:6379> ltrim mylist 1 2 # 通过下标截取指定长度,只保留截取的元素
OK
127.0.0.1:6379> lrange mylist 0 -1
1) "hello1"
2) "hello12"

  1. 组合操作rpoplpush
27.0.0.1:6379> lrange mylist 0 -1
1) "hello1"
2) "hello12"
127.0.0.1:6379> rpoplpush mylist mylist # 从尾部弹出,并从头部加入指定list
"hello12"
127.0.0.1:6379> lrange mylist 0 -1
1) "hello12"
2) "hello1"
  1. 更新list中的值
127.0.0.1:6379> lpush list value1
(integer) 1
127.0.0.1:6379> lrange list 0 -1
1) "value1"
127.0.0.1:6379> lset list 0 item # 设置list下标为0的值为item
OK
127.0.0.1:6379> lrange list 0 -1
1) "item"
127.0.0.1:6379> lset list 1 a # 值不存在无法设置
(error) ERR index out of range

  1. 插入操作
127.0.0.1:6379> lpush mylist hello
(integer) 1
127.0.0.1:6379> lpush mylist world
(integer) 2
127.0.0.1:6379> lrange mylist 0 -1
1) "world"
2) "hello"
127.0.0.1:6379> linsert mylist before world other # 在列表某个值前插入
(integer) 3
127.0.0.1:6379> lrange mylist 0 -1
1) "other"
2) "world"
3) "hello"
127.0.0.1:6379> linsert mylist after world new # 在列表某个值后插入
(integer) 4
127.0.0.1:6379> lrange mylist 0 -1
1) "other"
2) "world"
3) "new"
4) "hello"

小结

  • list实际上是一个链表
  • 如果key不存在则创建新链表
  • 如果key存在则新增内容
  • 如果移除了所有值则代表空链表,也不存在
  • 可以作为消息队列、栈使用

Set


set中的值不能重复
set命令以s开头

  1. 添加元素、查看元素、判断值是否存在
127.0.0.1:6379> sadd myset hello # set集合中添加元素
(integer) 1
127.0.0.1:6379> smembers myset # 查看指定set的所有值
1) "hello"
127.0.0.1:6379> sismember myset hello  # 判断某个值是否在集合中
(integer) 1

  1. 获取集合元素个数
127.0.0.1:6379> scard myset
(integer) 1
  1. 移除元素
127.0.0.1:6379> sadd myset nihao
(integer) 1
127.0.0.1:6379> srem myset hello # 移除myset中的hello
(integer) 1
127.0.0.1:6379> smembers myset
1) "nihao"

  1. set为无序不重复集合,可以抽随机
127.0.0.1:6379> sadd myset v1
(integer) 1
127.0.0.1:6379> sadd myset v2
(integer) 1
127.0.0.1:6379> sadd myset v3
(integer) 1
127.0.0.1:6379> srandmember myset # 随机抽一个元素
"nihao"
127.0.0.1:6379> srandmember myset 
"v2"
127.0.0.1:6379> srandmember myset 2 # 随机抽选指定个数的元素
1) "v1"
2) "v2"
  1. 随机删除元素
127.0.0.1:6379> smembers myset
1) "v3"
2) "v1"
3) "v2"
4) "nihao"
127.0.0.1:6379> spop myset # 随机删除元素
"v3"
  1. 将一个指定的值移动到另外一个set中
127.0.0.1:6379> sadd myset hello
(integer) 1
127.0.0.1:6379> sadd myset world
(integer) 1
127.0.0.1:6379> sadd myset warms
(integer) 1
127.0.0.1:6379> sadd myset2 set2
(integer) 1
127.0.0.1:6379> smembers myset
1) "hello"
2) "warms"
3) "world"
127.0.0.1:6379> smembers myset2
1) "set2"
127.0.0.1:6379> smove myset myset2 warms # 将指定的值移动到另一个集合中
(integer) 1
127.0.0.1:6379> smembers myset2
1) "warms"
2) "set2"
127.0.0.1:6379> smembers myset
1) "hello"
2) "world"
  1. 并集、差集、交集
127.0.0.1:6379> sadd k1 a
(integer) 1
127.0.0.1:6379> sadd k1 b
(integer) 1
127.0.0.1:6379> sadd k1 c
(integer) 1
127.0.0.1:6379> sadd k2 c
(integer) 1
127.0.0.1:6379> sadd k2 d
(integer) 1
127.0.0.1:6379> sadd k2 e
(integer) 1
127.0.0.1:6379> sdiff k1 k2 # 差集
1) "b"
2) "a"
127.0.0.1:6379> sinter k1 k2 # 交集 (共同好友可以这样实现)
1) "c"
127.0.0.1:6379> sunion k1 k2 # 并集
1) "b"
2) "c"
3) "e"
4) "a"
5) "d"

Hash


Map集合, Key - Map,这时候的值为一个Map集合!本质和String类型没有太大区别,还是简单的Key-Value。
所有的Hash命令以h开头

  1. 设置与获取
127.0.0.1:6379> hset myhash field1 warms # 设置一个 key-value
(integer) 1
127.0.0.1:6379> hget myhash field1 # 获取1个字段值
"warms"
127.0.0.1:6379> hmset myhash field1 hello field2 world # set多个key-value
OK
127.0.0.1:6379> hmget myhash field1 field2 # 获取多个字段值
1) "hello"
2) "world"
127.0.0.1:6379> hgetall myhash # 获取全部数据
1) "field1"
2) "hello"
3) "field2"
4) "world"

  1. 删除字段
127.0.0.1:6379> hdel myhash field1 # 删除hash指定的key字段
(integer) 1
127.0.0.1:6379> hgetall myhash
1) "field2"
2) "world"
  1. 获取hash中有几个键值对
127.0.0.1:6379> hgetall myhash
1) "field2"
2) "world"
3) "field1"
4) "hello"
127.0.0.1:6379> hlen myhash
(integer) 2
  1. 判断某个字段是否存在
127.0.0.1:6379> hexists myhash field1 # 判断hash中的指定字段是否存在
(integer) 1
  1. 只获得所有的field、只获得所有的value
127.0.0.1:6379> hkeys myhash # 只获得所有的field
1) "field2"
2) "field1"
127.0.0.1:6379> hvals myhash # 只获得所有的value
1) "world"
2) "hello"
  1. 指定增量、如果不存在则可以设置
127.0.0.1:6379> 
127.0.0.1:6379> hset myhash field3 5
(integer) 1
127.0.0.1:6379> hincrby myhash field3 1
(integer) 6
127.0.0.1:6379> hget myhash field3
"6"
127.0.0.1:6379> hincrby myhash field3 -1
(integer) 5
127.0.0.1:6379> hget myhash field3
"5"
127.0.0.1:6379> hsetnx myhash field4 hello
(integer) 1
127.0.0.1:6379> hsetnx myhash field4 hello
(integer) 0

hash应用:
存储变更数据,尤其是用户信息的保存,以及经常变动的信息。hash更适合对象的存储,String更加适合字符串存储。

Zset(有序集合)


在set的基础上增加了一个值,
set k1 v1
zset k1 score1 v1
Zset命令以z开头

  1. 设置与获取
127.0.0.1:6379> zadd myset 1 one # 添加一个值
(integer) 1
127.0.0.1:6379> zadd myset 2 two
(integer) 1
127.0.0.1:6379> zrange myset 0 -1 # 获取所有值
1) "one"
2) "two"

  1. 实现排序
127.0.0.1:6379> zadd salary 2500 xiaohong # 添加三个用户
(integer) 1
127.0.0.1:6379> zadd salary 5000 zhangsan
(integer) 1
127.0.0.1:6379> zadd salary 500 warms
(integer) 1
127.0.0.1:6379> zrange salary 0 -1
1) "warms"
2) "xiaohong"
3) "zhangsan"
127.0.0.1:6379> zrangebyscore salary -inf +inf # 递增显示全部用户
1) "warms"
2) "xiaohong"
3) "zhangsan"
127.0.0.1:6379> zrangebyscore salary -inf +inf withscores # 带score显示
1) "warms"
2) "500"
3) "xiaohong"
4) "2500"
5) "zhangsan"
6) "5000"
127.0.0.1:6379> zrangebyscore salary -inf 2500 withscores # 显示工资小于2500员工的升序排序
1) "warms"
2) "500"
3) "xiaohong"
4) "2500"
127.0.0.1:6379> zrevrange salary 0 -1 # 降序排序
1) "zhangsan"
2) "warms"
127.0.0.1:6379> zrevrange salary 0 -1 withscores
1) "zhangsan"
2) "5000"
3) "warms"
4) "500"

  1. 移除元素
127.0.0.1:6379> zrange salary 0 -1
1) "warms"
2) "xiaohong"
3) "zhangsan"
127.0.0.1:6379> zrem salary xiaohong # 移除集合中的指定元素
(integer) 1
127.0.0.1:6379> zrange salary 0 -1
1) "warms"
2) "zhangsan"
  1. 查看元素数量
127.0.0.1:6379> zcard salary # 获取有序集合中的个数
(integer) 2
  1. 统计某区间内的成员数量
127.0.0.1:6379> zcount salary 0 5000
(integer) 2

应用思路:

  • 班级成绩表、工资表
  • 带权重:普通消息、重要消息
  • 排行榜、top N 测试!

三种特殊的数据类型

geospatial(地理位置)


应用:朋友定位、附近的人、打车距离计算

可以查询一些测试数据:http://www.jsons.cn/lngcode/

Geo底层为Zset实现

  1. geoadd添加地理位置
    规则:两极无法添加,我们一般会加载城市数据通过java程序一次性导入
    参数: key 值 (纬度、经度、名称)
127.0.0.1:6379> geoadd china:city 116.40 39.90 beiging
(integer) 1
127.0.0.1:6379> geoadd china:city 121.47 31.23 shanghai
(integer) 1
127.0.0.1:6379> geoadd china:city 106.50 29.53 chongqing
(integer) 1
127.0.0.1:6379> geoadd china:city 114.05 22.52 shengzheng
(integer) 1
127.0.0.1:6379> geoadd china:city 120.16 30.24 hangzhou
(integer) 1
127.0.0.1:6379> geoadd china:city 108.96 34.26 xian
(integer) 1
  1. 获取指定城市的精度和纬度
127.0.0.1:6379> geopos china:city beiging
1) 1) "116.39999896287918091"
   2) "39.90000009167092543"

  1. 计算两地距离

单位

  • m 表示米
  • km 表示千米
  • mi 表示英里
  • ft 表示英尺
# 单位默认为米
127.0.0.1:6379> geodist china:city beiging shanghai
"1067378.7564"
127.0.0.1:6379> geodist china:city beiging shanghai km
"1067.3788"
  1. 以给定的精度纬度为中心找出某一半径内的元素
127.0.0.1:6379> georadius china:city 110 30 1000 km # 获取在以(100,30)为中心方圆1000km内的城市
1) "chongqing"
2) "xian"
3) "shengzheng"
4) "hangzhou"
127.0.0.1:6379> georadius china:city 110 30 500 km
1) "chongqing"
2) "xian"
  1. 以一个元素为中心查找指定范围内的元素
127.0.0.1:6379> georadiusbymember china:city beiging 1000 km
1) "beiging"
2) "xian"

  1. 返回一个位置或多个位置的Geohash表示
# 将二维的经纬度转化为一维的字符串,如果两个字符串越接近,那么则距离越近
127.0.0.1:6379> geohash china:city beiging
1) "wx4fbxxfke0"
  1. 查询所有元素
127.0.0.1:6379> zrange china:city 0 -1
1) "chongqing"
2) "xian"
3) "shengzheng"
4) "hangzhou"
5) "shanghai"
6) "beiging"

  1. 移除元素
127.0.0.1:6379> zrem china:city beiging
(integer) 1
127.0.0.1:6379> zrange china:city 0 -1
1) "chongqing"
2) "xian"
3) "shengzheng"
4) "hangzhou"
5) "shanghai"

Hyperloglog

什么是基数?
A{1,3,5,7,8,7}
B{1 , 3,5,7,8}
基数(不重复的元素),可以接受误差

Redis Hyperloglog 是用于基数统计的算法,该算法占用内存是固定的,2^64不同的元素的基数,只需要费12KB内存。存在0.81的错误率,统计UV的任务可以忽略不计。
网页UV (一个人访问一个网站多次,但还是算作一个人)
传统的方式,set保存用户的id,然后就可以统计set中的元素数量作为标准判断!这种方式保存了大量用户id,会很麻烦!

  1. 添加、统计、合并
127.0.0.1:6379> pfadd mykey a b c d e f g h i j
(integer) 1
127.0.0.1:6379> pfcount mykey
(integer) 10
127.0.0.1:6379> pfadd mykey2 i j e a w k
(integer) 1
127.0.0.1:6379> pfcount mykey2
(integer) 6
127.0.0.1:6379> pfmerge mykey3 mykey mykey2
OK
127.0.0.1:6379> pfcount mykey3
(integer) 12

BitMap


位存储
统计用户信息,活跃,不活跃!登录、未登录!打卡!只有两个状态都可以使用Bitmap
Bitmap 位图,数据结构!都是操作二进制位来记录,就只有0和1两个状态!

  1. 使用Bitmap记录打卡
127.0.0.1:6379> setbit sign 0 1
(integer) 0
127.0.0.1:6379> setbit sign 2 0
(integer) 0
127.0.0.1:6379> setbit sign 1 0
(integer) 0

  1. 查看某一天是否打卡
127.0.0.1:6379> getbit sign 0
(integer) 1
127.0.0.1:6379> getbit sign 2
(integer) 0
  1. 统计打卡天数
127.0.0.1:6379> bitcount sign # 统计打卡天数就可以判断是否全勤
(integer) 1
原文地址:https://www.cnblogs.com/PythonFCG/p/13859881.html