Redis基础教程

写在前面,感谢狂神,下面所有的都是来自狂神说Java - B站UP主

redis学习

Redis 是一个开源的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件MQ。它支持字符串、散列、列表、集合、有序集合与范围查询,bitmaps、hyperloglogs和地理空间(geospatial)索引半径查询。Redis内置了复制(replication),LUA脚本,lURU驱动时间,事物和不通级别的磁盘持久化,并通过Redis哨兵和自动分区提供高可用性。

基本命令

# 连接命令
 redis-cli -p 6379  
# 看是否连接成功
127.0.0.1:6379> ping 
PONG
# 清空数据库
127.0.0.1:6379> flushall
OK
# 设置keys
127.0.0.1:6379> set name shd
OK
# 查看当前有哪些key
127.0.0.1:6379> keys *
1) "name"

# 查看key是否存在 1是存在 0 是不存在
127.0.0.1:6379> exists name
(integer) 1
127.0.0.1:6379> EXISTS age
(integer) 0

# 设置key的过期时间  expire key sec
127.0.0.1:6379> expire name 10
(integer) 1
# 查看当前key的过期时间 ttl
127.0.0.1:6379> ttl name
(integer) 4
127.0.0.1:6379> ttl name
(integer) 2
127.0.0.1:6379> ttl name
(integer) -2
127.0.0.1:6379> ttl name
(integer) -2
# 根据key 获取value
127.0.0.1:6379> get name
(nil)

# 查看key的类型
127.0.0.1:6379> keys *
1) "name"
127.0.0.1:6379> type name
string
#

五大数据类型

String

127.0.0.1:6379> get key1
"v1"
127.0.0.1:6379> append key1 hello  # 追加, 如果不存在则新增一个  set key value
(integer) 7
127.0.0.1:6379> get key1
"v1hello"
127.0.0.1:6379> strlen key1 # 获取key的长度
(integer) 7
=================================================================
# 自增和自减  incr 自增  decr 自减
127.0.0.1:6379> set age 1
OK
127.0.0.1:6379> incr age
(integer) 2
127.0.0.1:6379> incr age
(integer) 3
127.0.0.1:6379> decr age
(integer) 2
127.0.0.1:6379> decr age
(integer) 1
127.0.0.1:6379> decr age
(integer) 0
127.0.0.1:6379> decr age
(integer) -1
127.0.0.1:6379> decr age
(integer) -2
127.0.0.1:6379> decr age
(integer) -3

# 步长式增加或减少 incrby step    decrby step
127.0.0.1:6379> INCRBY age 100
(integer) 97
127.0.0.1:6379> incrby age 100
(integer) 197
127.0.0.1:6379> decrby age 50
(integer) 147
127.0.0.1:6379> decrby age 50
(integer) 97
=====================================================
# 截取
127.0.0.1:6379> set name shd  # 设置name的值
OK
127.0.0.1:6379> get name   # 获取key
"shd"
127.0.0.1:6379> getrange name 1 2  # 截取1到2,闭区间
"hd"
127.0.0.1:6379> getrange name 1 1
"h"
127.0.0.1:6379> getrange name 0 -1 # 获取所有的
"shd"

#######################################
# 按下标 截取字符串
127.0.0.1:6379> set key1 abcdefgh
OK
127.0.0.1:6379> get key1
"abcdefgh"
127.0.0.1:6379> setrange key1 1 xxx  # 从下标1更改为xxx
(integer) 8
127.0.0.1:6379> get key1
"axxxefgh"
127.0.0.1:6379>

################################################
# setex 设置过期时间
127.0.0.1:6379> setex name 30 ddd
OK
127.0.0.1:6379> get name
"ddd"
127.0.0.1:6379> ttl name
(integer) 23

# setnx 不存在在设置 -- 分布式锁中会用到
127.0.0.1:6379> set name shd  # 首先设置name 为shd
OK
127.0.0.1:6379> setnx name myj # 通过setnx 设置name 为myj
(integer) 0   # 设置失败
127.0.0.1:6379> setnx bb myj  # 设置bb 为myj
(integer) 1     #设置成功
127.0.0.1:6379> get bb
"myj"

################################################
# 批量设置  mset 批量
127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3
OK
127.0.0.1:6379> keys *
1) "k3"
2) "k2"
3) "k1"

# 批量获取
127.0.0.1:6379> mget k1 k2 k3
1) "v1"
2) "v2"
3) "v3"

# setnx 批量设置为原子操作
127.0.0.1:6379> msetnx k1 v1 k4 v4 # 因为k1存在了,所有k4设置失败了
(integer) 0

#######################################################
# 存入对象
127.0.0.1:6379> set user:1 "{name:zhangsan, age:10}"
OK
127.0.0.1:6379> get user:1
"{name:zhangsan, age:10}"

# 批量存放对象 , 设计的key为关键
127.0.0.1:6379> mset user:1:name zhangsan user:1:age 10
OK
127.0.0.1:6379> mget user:1:name user:1:age
1) "zhangsan"
2) "10"
#######################################################
# 先get在set     
127.0.0.1:6379> keys * # 目前没有一个key
(empty array)
127.0.0.1:6379> getset name shd # 先获取name在设置name为shd
(nil)  # 因为不存在,所以为nil
127.0.0.1:6379> getset name myj # 在来一次,设置name为myj
"shd"  # 获取到了之前设置的shd


String 类型使用场景:value 除了是字符串,还可以是数字

  • 计数器 incr
  • 统计多单位的数量
  • 粉丝数 uid:988123:follow 0
  • 对象缓存存储

List

基本数据类型,列表

所有的list命令都是l开头的

##########################################
127.0.0.1:6379> lpush l one   # 将一个元素放入头部
(integer) 1
127.0.0.1:6379> lpush l two
(integer) 2
127.0.0.1:6379> lpush l three
(integer) 3
127.0.0.1:6379> lrange l 1 -1  # 获取第2个到最后一个元素
1) "two"
2) "one"
127.0.0.1:6379> lrange l 0 -1 # 获取第1个到最后一个元素
1) "three"
2) "two"
3) "one"
127.0.0.1:6379> rpush l four # 将一个元素放入尾部
(integer) 4
127.0.0.1:6379> lrange l 0 -1 # 通过区间获取列表的值
1) "three"
2) "two"
3) "one"
4) "four"
##########################################
# 移除元素
127.0.0.1:6379> lrange l 0 -1
1) "three"
2) "two"
3) "one"
4) "four"
127.0.0.1:6379> lpop l # 移除第一个元素
"three"
127.0.0.1:6379> rpop l # 移除最后一个元素
"four"
##########################################
# 根据下标获取元素
127.0.0.1:6379> lrange l 0 -1
1) "foure"
2) "three"
3) "two"
4) "one"
127.0.0.1:6379> lindex l 0 # 获取第0位元素
"foure"
## 返回列表的长度
127.0.0.1:6379> llen l 
(integer) 4
##########################################
# 移除指定的值
127.0.0.1:6379> lrange l 0 -1
1) "three"
2) "three"
3) "three"
4) "five"
5) "foure"
6) "two"
7) "one"
127.0.0.1:6379> lrem l  2 three # 移除指定数量的具体元素 
(integer) 2
127.0.0.1:6379> lrange l 0 -1
1) "three"
2) "five"
3) "foure"
4) "two"
5) "one"

##########################################
# 截断
127.0.0.1:6379> lrange l 0 -1
1) "python"
2) "vue"
3) "world"
4) "hello"
127.0.0.1:6379> ltrim l 1 2  # 通过下标截取1到2的元素
OK
127.0.0.1:6379> lrange l 0 -1
1) "vue"
2) "world"
##########################################
# rpoplpush  移除最后一个元素到另一个元素
127.0.0.1:6379> lrange l1 0 -1
1) "c"
2) "b"
3) "a"
127.0.0.1:6379> RPOPLPUSH l1 l2 # 把l1最后一个元素移动到l2中
"a"
127.0.0.1:6379> lrange l1 0 -1
1) "c"
2) "b"
127.0.0.1:6379> lrange l2 0 -1
1) "a"
########################################
# exists 查看列表是否存在 
#  lset 把已存在的元素通过下标更新为另一个元素
127.0.0.1:6379> exists l
(integer) 0
127.0.0.1:6379> lset l 0 name #如果不存在,则报错
(error) ERR no such key
127.0.0.1:6379> lpush l age
(integer) 1
127.0.0.1:6379> lset l 0 name
OK
127.0.0.1:6379> lindex l 0
"name"

########################################
# 插入值
127.0.0.1:6379> lindex l 0
"name"
127.0.0.1:6379> LINSERT l before name your # name前面插入一个值
(integer) 2
127.0.0.1:6379> lrange l 0 -1
1) "your"
2) "name"
127.0.0.1:6379> linsert l after name is # name后面插入一个值
(integer) 3
127.0.0.1:6379> lrange l 0 -1
1) "name"
2) "your"
3) "name"
4) "is"
127.0.0.1:6379> linsert l before name my # 如果有两个相同的元素,在name前插入,会优先插入下标最小的那个
(integer) 5
127.0.0.1:6379> lrange l 0 -1
1) "my"
2) "name"
3) "your"
4) "name"
5) "is"

  • 它实际上是一个链表,before node after, left,right都可以插值

  • 如果key不存在,创建新的链表

  • 如果key存在,新增内容

  • 如果移除了所有值,空链表,也代表不存在

  • 在两边插入或改动值,效率最高,中间元素,相对来说效率较低

  • 消息排队,消息队列 lpush rpop, 栈 lpush lpop

    Set(集合)

    set中的值是不可以重复的

    #########################################
    127.0.0.1:6379> sadd s name # 新增元素
    (integer) 1
    127.0.0.1:6379> sadd s age
    (integer) 1
    127.0.0.1:6379> smembers s # 获取所有成员
    1) "age"
    2) "name"
    127.0.0.1:6379> sismember s age # 判断元素是否存在
    (integer) 1
    127.0.0.1:6379> sismember s sex
    (integer) 0
    
    #########################################
    127.0.0.1:6379> scard s  # 获取元素个数
    (integer) 2
    
    127.0.0.1:6379> srem s age # 移除指定的元素
    (integer) 1
    127.0.0.1:6379> srem s sex
    (integer) 0
    127.0.0.1:6379> smembers s
    1) "name"
    
    127.0.0.1:6379> smembers s # 获取所有的元素
    1) "age"
    2) "name"
    3) "address"
    4) "sex"
    127.0.0.1:6379> spop s # 随机移除一个元素
    "address"
    127.0.0.1:6379> smembers s
    1) "age"
    2) "name"
    3) "sex"
    #########################################
    127.0.0.1:6379> SRANDMEMBER s 1  # 随机抽选随机个数的元素 srandmember
    1) "sex"
    127.0.0.1:6379> SRANDMEMBER s 1
    1) "name"
    127.0.0.1:6379> SRANDMEMBER s 1
    1) "age"
    127.0.0.1:6379> SRANDMEMBER s 1
    1) "age"
    
    #########################################
    127.0.0.1:6379> sadd s one
    (integer) 1
    127.0.0.1:6379> sadd s two
    (integer) 1
    127.0.0.1:6379> sadd s three
    (integer) 1
    127.0.0.1:6379> sadd s1 aaa
    (integer) 1
    127.0.0.1:6379> smove s s1 one  # 把s中的one 移到s1中
    (integer) 1
    127.0.0.1:6379> smembers s
    1) "two"
    2) "three"
    127.0.0.1:6379> smembers s1
    1) "one"
    2) "aaa"
    
    
    #########################################
     127.0.0.1:6379> sadd s c
    (integer) 1
    127.0.0.1:6379> sadd e c
    (integer) 1
    127.0.0.1:6379> sadd e d
    (integer) 1
    127.0.0.1:6379> sadd e f
    (integer) 1
    127.0.0.1:6379> sdiff s e  # 差集
    1) "a"
    2) "b"
    127.0.0.1:6379> sinter s e # 交集 共同好友
    1) "c"
    127.0.0.1:6379> sunion s e # 并集
    1) "a"
    2) "c"
    3) "f"
    4) "b"
    5) "d"
    
    

    微博,a用户将所有关注的人放一个set集合,将他的粉丝也放到一个集合中!

    Hash

    Map集合

    ####################################################################################
    # 注意hmset 批量设置多个key value 在redis4.0 被废弃
    127.0.0.1:6379> hset my age 10 name shd sex man # 设置多个key 和value
    (integer) 3
    127.0.0.1:6379> hget my age  # 根据指定key 获取 value
    "10"
    127.0.0.1:6379> hmget my age name sex # 根据多个filed 获取value
    1) "10"
    2) "shd"
    3) "man"
    127.0.0.1:6379> hgetall my # 根据key获取所有的 filed 和value
    1) "age"
    2) "10"
    3) "name"
    4) "shd"
    5) "sex"
    6) "man"
    ####################################################################################
    127.0.0.1:6379> hdel my name # 删除指定的field
    (integer) 1
    127.0.0.1:6379> hgetall my
    1) "age"
    2) "10"
    3) "sex"
    4) "man"
    
    
    ####################################################################################
    127.0.0.1:6379> hlen my # 获取hash的长度
    (integer) 2
    
    ####################################################################################
    127.0.0.1:6379> hgetall my
    1) "age"
    2) "10"
    3) "sex"
    4) "man"
    127.0.0.1:6379> hexists my name  # 判断 field 是否存在
    (integer) 0
    127.0.0.1:6379> hexists my age
    (integer) 1
    
    ####################################################################################
    127.0.0.1:6379> hkeys my # 获取所有的fields
    1) "age"
    2) "sex"
    127.0.0.1:6379> hvals my # 获取所有的values
    1) "10"
    2) "man"
    
    ####################################################################################
    127.0.0.1:6379> HINCRBY my age -1 # 指定增量
    (integer) 9
    127.0.0.1:6379> HINCRBY my age -1
    (integer) 8
    127.0.0.1:6379> HINCRBY my age -1
    (integer) 7
    127.0.0.1:6379> HINCRBY my age -1
    (integer) 6
    
    127.0.0.1:6379> hset my age 10
    (integer) 1
    127.0.0.1:6379> hsetnx my age 100
    (integer) 0
    127.0.0.1:6379> hsetnx my name shd # 不存在就创建
    (integer) 1
    

    hash变更的数据user name ,age,尤其是用户信息类的,经常变动的信息!hash更适合与对象的存储,string更适合自字符串的存储

    Zset

    在set的基础上,增加了一个值,set k1 v1 zset v1 score v1

    
    ####################################
    127.0.0.1:6379> zadd myset 1 one  # 添加一个元素
    (integer) 1
    127.0.0.1:6379> zadd myset 1 one 2 two 3 three 4 four # 添加多个元素 
    (integer) 3
    127.0.0.1:6379> zrange myset 0 -1
    1) "one"
    2) "two"
    3) "three"
    4) "four"
    
    ####################################
    # 排序
    127.0.0.1:6379> zadd user 1000 zhangsan
    (integer) 1
    127.0.0.1:6379> zadd user 800 wangwu
    (integer) 1
    127.0.0.1:6379> zadd user 1500 zhaosi
    (integer) 1
    127.0.0.1:6379> zrangebyscore user -inf +inf # 负无穷到 正无穷 排序
    1) "wangwu"
    2) "zhangsan"
    3) "zhaosi"
    127.0.0.1:6379> ZRANGEBYSCORE user -inf +inf  # 升序
    1) "one"
    2) "two"
    3) "three"
    4) "foure"
    5) "five"
    127.0.0.1:6379> ZREVRANGE user 0 -1 # 降序
    1) "five"
    2) "foure"
    3) "three"
    4) "two"
    5) "one"
    
    127.0.0.1:6379> zrangebyscore user 0 800 # 0 到800 的升序排列
    1) "wangwu"
    
    #################################################
    127.0.0.1:6379> zrem user wangwu # 移除元素
    (integer) 1
    127.0.0.1:6379> zcard user # 获取集合中的个数
    (integer) 2
    
    #################################################
    
    127.0.0.1:6379> ZREVRANGE user 0 -1
    1) "five"
    2) "foure"
    3) "three"
    4) "two"
    5) "one"
    127.0.0.1:6379>
    127.0.0.1:6379>
    127.0.0.1:6379> zcount user 2 3 # 获取区间的个数
    (integer) 2
    127.0.0.1:6379> zcount user 2 4 # 获取区间的个数
    (integer) 3
    
    

    案例思路:

    set排序,存储班级成绩表 工资排序标

    普通消息 1 重要消息 2 带权重进行判断

    排行榜应用

三种特殊类型

Geospatial (地理位置)

朋友的定位,附近的人 , 打车距离计算

############################################################
# geoadd
# 两极无法直接添加
127.0.0.1:6379> geoadd china:city 116.397128 39.916527 beijing # 添加一个城市的经纬度
(integer) 1
127.0.0.1:6379> geoadd china:city 121.48941 31.40527 chongqing
(integer) 1
127.0.0.1:6379> geoadd china:city 113.6401 34.72468 zhengzhou 108.93425 34.23053 xian # 添加多个城市的经纬度
(integer) 2

############################################################
#  geopos  获取指定城市的经纬度
127.0.0.1:6379> GEOPOS china:city beijing # 获取一个城市的 
1) 1) "116.39712899923324585"
   2) "39.91652647362980844"
127.0.0.1:6379> GEOPOS china:city beijing zhengzhou # 获取多个城市的
1) 1) "116.39712899923324585"
   2) "39.91652647362980844"
2) 1) "113.64010244607925415"
   2) "34.72467993544626808"

############################################################
# 获取两人的距离
单位
m 表示米
km 表示千米
mi 表示英里
ft 表示英尺
# 获取两个城市的距离
127.0.0.1:6379> geodist china:city beijing zhengzhou km # 千米
"626.7593" 

############################################################
# 获取附件的人
127.0.0.1:6379> georadius china:city 116 39 1000 km  # 获取中心为经度116 维度 39 1000千米的所有城市 
1) "zhengzhou"
2) "beijing"
3) "chongqing"
4) "xian"

127.0.0.1:6379> georadius china:city 116 39 1000 km  withdist # 获取中心为经度116维度391000千米的所有城市和距离
1) 1) "zhengzhou"
   2) "519.7813"
2) 1) "beijing"
   2) "107.4949"
3) 1) "chongqing"
   2) "980.5655"
4) 1) "xian"
   2) "823.7398"
127.0.0.1:6379> georadius china:city 116 39 1000 km  withcoord # 获取中心为经度116维度391000千米的所有城市和经纬度
1) 1) "zhengzhou"
   2) 1) "113.64010244607925415"
      2) "34.72467993544626808"
2) 1) "beijing"
   2) 1) "116.39712899923324585"
      2) "39.91652647362980844"
3) 1) "chongqing"
   2) 1) "121.48941010236740112"
      2) "31.40526993848380499"
4) 1) "xian"
   2) 1) "108.93425256013870239"
      2) "34.23053097599082406"

127.0.0.1:6379> georadius china:city 116 39 1000 km   count 2 # 获取指定数量的城市
1) "beijing"
2) "zhengzhou"

##################################################
# 找出指定元素周围的元素
127.0.0.1:6379> GEORADIUSBYMEMBER china:city beijing 1000 km withcoord
1) 1) "zhengzhou"
   2) 1) "113.64010244607925415"
      2) "34.72467993544626808"
2) 1) "beijing"
   2) 1) "116.39712899923324585"
      2) "39.91652647362980844"
3) 1) "xian"
   2) 1) "108.93425256013870239"
      2) "34.23053097599082406"
127.0.0.1:6379> GEORADIUSBYMEMBER china:city beijing 1000 km withdist
1) 1) "zhengzhou"
   2) "626.7593"
2) 1) "beijing"
   2) "0.0000"
3) 1) "xian"
   2) "915.0863"

geo底层的实现原理其实就是zset,可以使用zset的命令操作geo

Hyperloglog 基数统计

hyperlogolog优势:

占用内存是固定,2^64不通的元素的技术,只需要废12KB的内存

什么是基数?

A {1,3,5,7,8,7}

B{1,3,5,7, 8}

基数(不重复元素的个数) = 5,可以接受误差

网页的UV (1个人访问一个网站多次,但是还算做一个人)

传统的方式,set保存用户的id,然后就可以统计set中的元素来判断

这个方式如果保存了大量的用户id就会比较麻烦。我们目的是为了计数,而不是保存用户id

##########################################
127.0.0.1:6379> pfadd k1 a b c d # 新增元素
(integer) 1
127.0.0.1:6379> pfadd k2 d e f j k
(integer) 1
127.0.0.1:6379> pfmerge k3 k1 k2  # 合并元素到另一个元素中
OK
127.0.0.1:6379> pfcount k3 # 获取元素个数
(integer) 8

Bitmaps

位存储

统计疫情感染人数

统计用户信息,活跃,不活跃 登录 和未登录, 365打卡。两种状态的都可以使用bitmaps

bitmaps 位图,数据结构! 都是操作二进制位来记录,就只有0和1

##########################################################
# 统计一周内打卡的天数
# 首先是设置每周的打开状态 0 到6 表示 周一到周末
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 1
(integer) 0
127.0.0.1:6379> setbit sign 4 1
(integer) 0
127.0.0.1:6379> setbit sign 5 1
(integer) 0
127.0.0.1:6379> setbit sign 6 1
(integer) 0

## 查看某天是否打卡
127.0.0.1:6379> getbit sign 3 # 查看周四是否打卡
(integer) 1
## 查看一周是否全部打卡
127.0.0.1:6379> bitcount sign
(integer) 6

你可能感兴趣的:(Redis基础教程)