资讯详情

(笔记)-Redis

阿里云上redis外网无法访问的解决方案

  • 启动命令 redis-server Rconfig/redis.conf(在/usr/local/bin 目录下)
  • 原生客户端 redis-cli

    目录标题写在这里

    • 数据类型
      • 五种基本数据类型
        • Redis-key
        • String-字符串
        • List-列表
        • Set
        • Hash
        • Zset(有序集合)
      • 三种特殊数据类型
        • geospatial 地理位置
        • Hyperloglog
        • Bitmaps(位图) 位存储
    • 事务
        • Redis事务流程:
        • 监控 Watch
            • 悲观
            • 乐观锁
    • Jedis
        • 1.导入依赖
        • 2.编码测试
    • SpringBoot整合Redis
        • 一、区别
        • 二、整合
        • 三、自定义Redis工具类
        • 四、自定义Redis配置类
    • Redis.conf
        • 单位
        • 包含
        • 网络
        • 通用
        • 快照
        • SECURITY
        • 限制

数据类型

五种基本数据类型

  • Redis-key
  • String
  • List
  • Set
  • Hash
  • Zset

Redis-key

  • keys * 查看当前库所有key

  • exists name 判断namekey 是否存在

  • move name 1 移除name

  • expire name 10 设置name 10秒后过期

  • ttl name 检查过期时间

  • type name 查看当前 key 的类型

String-字符串

  • keys *获得所有key

  • get name获取name的value

  • append name asd在name加上值的末尾asd

  • exists name判断name是否存在

127.0.0.1:6379> keys * #获得所有key 1) "name" 2) "age" 127.0.0.1:6379> get name #获取值 "changan" 127.0.0.1:6379> append name love    #添加字符串 (integer) 11 127.0.0.1:6379> get name "changanlove" 127.0.0.1:6379> exists name  #判断它是否存在 (integer) 1 
  • incr views 给 views 加1

  • decr views 给 views 减1

  • incrby views 10 给 views 加10(步长)

  • decrby views 10 给 views 减10(步长)

  • getrange 范围查询数据 在这里插入图片描述

  • setrange 修改(替换)

  • setex key 60 "value"设置短时数据

  • setnx key "redis" 仅在key不存在时生效,生成新的key-value(常用于分布式锁)

  • mset 批量设置

  • mget 批量读取

  • msetnx 设置多个值 如果一个值设置失败,那么全部失败 (原子性)

    127.0.0.1:6379> msetnx k1 v1 k5 v5(integer) 0
    
  • getset 先获取在设置

    127.0.0.1:6379> set key value	
    OK
    127.0.0.1:6379> getset key hi	--> 如果存在,返回当前的值,并设置新的值
    "value"
    127.0.0.1:6379> get key
    "hi"
    127.0.0.1:6379> getset key1 hi	--> 不存在返回nil则创建
    (nil)
    127.0.0.1:6379> get key1
    "hi"
    
  • String的应用场景

    • 计数器
    • 统计多单位数量
    • 粉丝数
    • 对象缓存存储

List-列表

  • lpush左存储

    rpush 右存储

    lrange读取

    127.0.0.1:6379> lpush list 1 		-->左存储
    (integer) 1
    127.0.0.1:6379> lpush list 2
    (integer) 2
    127.0.0.1:6379> lpush list 3
    (integer) 3
    127.0.0.1:6379> lrange list 0 -1 	-->读取
    1) "3"
    2) "2"
    3) "1"
    127.0.0.1:6379> rpush list yyds		-->右存储
    (integer) 4
    127.0.0.1:6379> lrange list -1 -1	-->读取
    1) "yyds"
    
  • lpop : 左移除(移除左边第一个)

    rpop : 右移除(移除右边第一个)

    127.0.0.1:6379> lrange list 0 -1	
    1) "3"
    2) "2"
    3) "1"
    4) "yyds"
    127.0.0.1:6379> lpop list -->左移除
    "3"
    127.0.0.1:6379> rpop list -->右移除
    "yyds"
    127.0.0.1:6379> lrange list 0 -1
    1) "2"
    2) "1"
    
  • lindex 通过下标获取值

    127.0.0.1:6379> lrange list 0 -1
    1) "zxc"
    2) "asd"
    3) "y"
    4) "x"
    5) "2"
    127.0.0.1:6379> lindex list 0
    "zxc"
    127.0.0.1:6379> lindex list -1
    "2"
    
  • llen 获取list的长度

    127.0.0.1:6379> llen list
    (integer) 5
    
  • lrem 删除 ‘精确匹配’

    127.0.0.1:6379> lrange list 0 -1
    1) "1"
    2) "1"
    3) "1"
    4) "1"
    5) "zxc"
    6) "asd"
    7) "y"
    8) "x"
    9) "2"
    127.0.0.1:6379> lrem list 2 1
    (integer) 2
    127.0.0.1:6379> lrange list 0 -1
    1) "1"
    2) "1"
    3) "zxc"
    4) "asd"
    5) "y"
    6) "x"
    7) "2"
    
  • ltrim 截取

    127.0.0.1:6379> lrange list 0 -1
    1) "hello"
    2) "hello1"
    3) "hello2"
    4) "hello3"
    5) "hello4"
    6) "hello5"
    127.0.0.1:6379> ltrim list 1 3 -->截取标号1-3之间的元素
    OK
    127.0.0.1:6379> lrange list 0 -1
    1) "hello1"
    2) "hello2"
    3) "hello3"
    
  • rpoplpush 移除列表的最后一个元素,并移动到新的列表中

    127.0.0.1:6379> lrange list 0 -1
    1) "hello1"
    2) "hello2"
    3) "hello3"
    127.0.0.1:6379> RPOPLPUSH list mylist -->移除list的最后一个元素,并移动到新的mylist中
    "hello3"
    127.0.0.1:6379> lrange mylist 0 -1
    1) "hello3"
    
  • lset 将列表中指定下标的值替换为另外一个(update)

    127.0.0.1:6379> lrange list 0 -1
    1) "hello1"
    2) "hello2"
    127.0.0.1:6379> lset list 0 hi
    OK
    127.0.0.1:6379> lrange list 0 -1
    1) "hi"
    2) "hello2"
    
  • linsert 将某一个具体的值插入列表某个元素的前后

    127.0.0.1:6379> lrange list 0 -1
    1) "hi"
    2) "hello2"
    127.0.0.1:6379> linsert list After hello2 good	-->在hello2之后插入
    (integer) 3
    127.0.0.1:6379> lrange list 0 -1
    1) "hi"
    2) "hello2"
    3) "good"
    127.0.0.1:6379> linsert list before hello2 good	-->在hello2之前插入
    (integer) 4
    127.0.0.1:6379> lrange list 0 -1
    1) "hi"
    2) "good"
    3) "hello2"
    4) "good"
    
  • 小结

    • list实际是一个链表,before , after,left ,right 都可以插入值

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

    • 如果key 存在,新增内容

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

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

    可以用来做! 消息队列(Lpush Rpop) 左进右出 ,栈(Lpush Lpop)左进左出

Set

  • ssad给集合添加值

    smembers查看当前集合元素

    sismember查看集合是否含有某元素, 有的话返回1 没有就是0

    scard获取当前集合的个数

    screm 移除集合中某个元素

    127.0.0.1:6379> sadd mylist 1	-->给集合添加值
    (integer) 1
    127.0.0.1:6379> sadd mylist 2	-->给集合添加值
    (integer) 1
    127.0.0.1:6379> sadd mylist zxc	-->给集合添加值
    (integer) 1
    127.0.0.1:6379> sadd mylist asd	-->给集合添加值
    (integer) 1
    127.0.0.1:6379> SMEMBERS mylist	-->查看当前集合元素
    1) "zxc"
    2) "asd"
    3) "2"
    4) "1"
    127.0.0.1:6379> SISMEMBER mylist 1 -->判断1是否在集合mylist中		
    (integer) 1
    127.0.0.1:6379> SISMEMBER mylist 3 -->判断3是否在集合mylist中	
    (integer) 0z
    127.0.0.1:6379> scard mylist -->获取集合中元素个数
    (integer) 4
    127.0.0.1:6379> SREM mylist 2
    (integer) 1
    127.0.0.1:6379> SMEMBERS mylist	-->查看当前集合元素
    1) "zxc"
    2) "asd"
    3) "2"
    4) "1"
    127.0.0.1:6379> SMEMBERS mylist	-->移除mylist中的元素"2"
    1) "zxc"
    2) "asd"
    3) "1"
    
  • SRANDMEMBER 随机从集合中筛选一个数据

    127.0.0.1:6379> SRANDMEMBER mylist	-->随机抽取
    "asd"
    127.0.0.1:6379> SRANDMEMBER mylist	-->随机抽取
    "asd"
    127.0.0.1:6379> SRANDMEMBER mylist	-->随机抽取
    "2"
    127.0.0.1:6379> SRANDMEMBER mylist	-->随机抽取
    "zxc"
    127.0.0.1:6379> SRANDMEMBER mylist	-->随机抽取
    "1"
    127.0.0.1:6379> SRANDMEMBER mylist	-->随机抽取
    "2"
    
  • spop 随机删除一个元素

    127.0.0.1:6379> SMEMBERS mylist
    1) "zxc"
    2) "asd"
    3) "1"
    127.0.0.1:6379> SPOP mylist	-->随机删除
    "zxc"
    127.0.0.1:6379> SPOP mylist	-->随机删除
    "1"
    127.0.0.1:6379> SPOP mylist	-->随机删除
    "asd"
    
  • smove将一个指定的值移动到另外一个set集合中

    127.0.0.1:6379> smove myset yourset hello1 -->将 "hello1"从myset移动到yourset中
    (integer) 1
    127.0.0.1:6379> SMEMBERS myset
    1) "hello2"
    2) "hello5"
    3) "hello"
    4) "hello4"
    5) "hello6"
    6) "hello3"
    127.0.0.1:6379> smembers yourset
    1) "hello1"
    
  • SDIFF 查看2个集合的差集

    SINTER 查看2个集合的交集

    SUNION 查看2个集合的并集

    127.0.0.1:6379> smembers set1
    1) "1"
    2) "2"
    3) "3"
    4) "4"
    127.0.0.1:6379> smembers set2
    1) "3"
    2) "4"
    3) "5"
    4) "6"
    127.0.0.1:6379> sdiff set1 set2		-->差集 set1-set2
    1) "1"
    2) "2"
    127.0.0.1:6379> sdiff set2 set1		-->差集 set2-set1
    1) "5"
    2) "6"
    127.0.0.1:6379> SINTER set1 set2	-->交集
    1) "3"
    2) "4"
    127.0.0.1:6379> Sunion set1 set2	-->并集
    1) "1"
    2) "2"
    3) "3"
    4) "4"
    5) "5"
    6) "6"
    
  • 应用场景

    ​ 微博等社交平台,A用户将所有的关注的人放在一个set集合中,将他的粉丝也放在一个集合中,从而实现

Hash

  • hset 设置值

    hget获取值

    hmset批量设置值

    hmget 批量获取指定值

    hgetall 获取指定hashmap的值

    127.0.0.1:6379> hset myhash name zane 	-->set一个具体的 key-value
    (integer) 1
    127.0.0.1:6379> hget myhash name		-->get一个具体的 key-gvalue
    "zane"
    127.0.0.1:6379> hmset myhash age 20 sex male 
    OK
    127.0.0.1:6379> hmget myhash age  sex  
    1) "20"
    2) "male"
    127.0.0.1:6379> hgetall myhash	-->获取键值对
    1) "name"
    2) "zane"
    3) "age"
    4) "20"
    5) "sex"
    6) "male"
    
  • hdel 删除指定的kv

    127.0.0.1:6379> hdel myhash age
    (integer) 1
    127.0.0.1:6379> hget myhash age
    (nil)
    
  • hlen 查询集合有几组kv

    HEXISTS 查看集合的k是否存在

    hkeys 查看所有的key

    hvals 查看所有的value

    127.0.0.1:6379> hlen myhash
    (integer) 2
    127.0.0.1:6379> HEXISTS myhash age
    (integer) 0
    127.0.0.1:6379> HEXISTS myhash sex
    (integer) 1
    127.0.0.1:6379> hkeys myhash
    1) "name"
    2) "sex"
    127.0.0.1:6379> hvals myhash
    1) "zane"
    2) "male"
    
  • HINCRBY 指定增量

    hsetnx 创建一个集合 如果这个集合没有数据 就放入数据 返回1 如果有数据 那么返回0

    原理同String、

  • 应用场景

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

Zset(有序集合)

geospatial 地理位置

  • GEOADD 添加地理位置信息

    127.0.0.1:6379> GEOADD china:city 116.352963  40.409079 beijing
    (integer) 1
    127.0.0.1:6379> GEOADD china:city 116.413384 39.910925  shanghai
    (integer) 1
    127.0.0.1:6379> GEOADD china:city 104.072747 30.578994 chengdu
    (integer) 1
    #格式 geoadd 纬度 经度 名称
    

  • GEODIST 展现两点之间的距离

    127.0.0.1:6379> geodist china:city chengdu shanghai
    "1524928.5252"
    127.0.0.1:6379> geodist china:city chengdu shanghai km
    "1524.9285"
    127.0.0.1:6379> geodist china:city chengdu shanghai ft
    "5003046.3424"
    127.0.0.1:6379> geodist china:city chengdu shanghai mi
    "947.5490"
    

    单位(默认单位是米)

    • m米
    • km千米
    • mi英里
    • ft英尺
  • GEOPOS获取地理位置信息

    127.0.0.1:6379> geopos china:city chengdu  shanghai
    1) 1) "104.07274872064590454"
       2) "30.57899393079901529"
    2) 1) "116.41338318586349487"
       2) "39.9109247398676743"
    
  • GEORADIUS以给定的经纬度为中心。找出某一半径内所有元素

    127.0.0.1:6379> GEORADIUS china:city 110 30 1000 km	-->找出该点方圆1000km内的点
    1) "chengdu"
    127.0.0.1:6379> GEORADIUS china:city 110 30 1000 km withdist -->withdist附带显示距离
    1) 1) "chengdu"
       2) "572.8305"
    127.0.0.1:6379> GEORADIUS china:city 110 30 1000 km withcoord -->withcoord附带显示经纬度
    1) 1) "chengdu"
       2) 1) "104.07274872064590454"
          2) "30.57899393079901529"
    
  • GEORADIUSBYMEMBER 找出指定元素附近一定距离的元素

    127.0.0.1:6379> GEORADIUSBYMEMBER china:city beijing 1000 km
    1) "shanghai"
    2) "beijing"
    
  • GEOHASH 将二维的经纬度转化为一维的字符串,如果两个字符串越接近,则代表距离越近

    127.0.0.1:6379> geohash china:city beijing chengdu
    1) "wx4tzsjxuw0"
    2) "wm6jbnxrwc0"
    
  • 查看与删除

    127.0.0.1:6379> zrange china:city 0 -1	#查看
    1) "chengdu"
    2) "shanghai"
    3) "beijing"
    127.0.0.1:6379> zrem china:city beijing #删除
    (integer) 1
    127.0.0.1:6379> zrange china:city 0 -1	#查看
    1) "chengdu"
    2) "shanghai"
    

Hyperloglog

优点:占用内存小,2^64不同的元素技术,只需要12kb内存

  • pfadd :添加数据

    pfcount :查询数据

    pfmerge :合并数据

    127.0.0.1:6379> PFADD mykey  1 2 3 4 56  6 8 9 8 7  a s d f g h h #添加数据
    (integer) 1
    127.0.0.1:6379> pfcount mykey			#查询数据
    (integer) 15
    127.0.0.1:6379> PFADD mykey2  z x c v b n m#添加数据
    (integer) 1
    127.0.0.1:6379> pfmerge mykey0 mykey2 mykey#合并数据 (pfmerge 目标集合 源集合……)
    OK
    127.0.0.1:6379> pfcount mykey0#查询数据
    (integer) 22
    

Bitmaps(位图) 位存储

只要是2位数的数据结构就可以用,只有 0和1 两个状态

如:登录/未登录 活跃/不活跃 打卡/未打卡

  • setbit 设值 setbit key offset value

    getbit 取值 getbit key offset

    bitcount 查询 bitcount key [start end]

    127.0.0.1:6379> setbit sign 0 0
    (integer) 1
    127.0.0.1:6379> setbit sign 1 1
    (integer) 0
    127.0.0.1:6379> setbit sign 2 1
    (integer) 0
    127.0.0.1:6379> getbit sign 1
    (integer) 1
    127.0.0.1:6379> bitcount sign #统计打卡天数(value为1的元素数量)
    (integer) 2
    

事务

所有的命令在事务中,并没有直接被执行!只有发起执行命令的时候才会执行!

Redis的事务流程:

  • 开启事务 (multi)

  • 命令入队 ( )

  • 执行事务 (exec)/取消事务(discard)

    正常执行事务

    127.0.0.1:6379> multi #开启事务
    OK
    #命令入队
    127.0.0.1:6379(TX)> set k1 v1
    QUEUED
    127.0.0.1:6379(TX)> set k2 v2
    QUEUED
    127.0.0.1:6379(TX)> set k3 v3
    QUEUED
    127.0.0.1:6379(TX)> get k2
    QUEUED
    127.0.0.1:6379(TX)> del k3
    QUEUED
    127.0.0.1:6379(TX)> exec #执行事务
    1) OK
    2) OK
    3) OK
    4) "v2"
    5) (integer) 1
    127.0.0.1:6379> MULTI
    OK
    127.0.0.1:6379(TX)> DISCARD #取消事务
    OK
    

    编译型异常,实务中所有命令都不会被执行

    127.0.0.1:6379> multi 
    OK
    127.0.0.1:6379(TX)> set k1 v1 
    QUEUED
    127.0.0.1:6379(TX)> set k2 v2 
    QUEUED
    127.0.0.1:6379(TX)> setget k3 v3 
    (error) ERR unknown command `setget`, with args beginning with: `k3`, `v3`, 
    127.0.0.1:6379(TX)> set k4 v4 
    QUEUED
    127.0.0.1:6379(TX)> EXEC
    (error) EXECABORT Transaction discarded because of previous errors.
    127.0.0.1:6379> get k4
    (nil)
    

    运行时异常,错误的命令抛出异常,正确的命令正常执行

    127.0.0.1:6379> set k1 "v1"
    OK
    127.0.0.1:6379> multi
    OK
    127.0.0.1:6379(TX)> incr k1
    QUEUED
    127.0.0.1:6379(TX)> set k2 v2
    QUEUED
    127.0.0.1:6379(TX)> set k3 v3
    QUEUED
    127.0.0.1:6379(TX)> EXEC
    1) (error) ERR value is not an integer or out of range
    2) OK
    3) OK
    127.0.0.1:6379> get k1
    "v1"
    127.0.0.1:6379> get k2
    "v2"
    127.0.0.1:6379> get k3
    "v3"
    

监控 Watch

悲观锁
  • 认为什么时候都会出问题,无论进行什么事务都会加锁。
乐观锁
  • 认为什么时候都不会出问题,不上锁,更新数据时判断一下期间是否有人改动过数据
  • 获取version
  • 更新时比较version

Redis 监视测试

正常执行成功

127.0.0.1:6379> set money 100
OK
127.0.0.1:6379> set out 0
OK
127.0.0.1:6379> WATCH money	#监视money对象
OK
127.0.0.1:6379> multi 		#事务正常结束,数据期间未发生变动,此时正常执行成功!
OK
127.0.0.1:6379(TX)> DECRBY money 20
QUEUED
127.0.0.1:6379(TX)> incrby out 20
QUEUED
127.0.0.1:6379(TX)> EXEC
1) (integer) 80
2) (integer) 20

线程1

127.0.0.1:6379> get money
"80"
127.0.0.1:6379> set money 1555
OK

线程2

127.0.0.1:6379> WATCH money #监视
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> DECRBY money 10
QUEUED
127.0.0.1:6379(TX)> INCRBY out 10
QUEUED
127.0.0.1:6379(TX)> exec #执行前,另一个线程修改了money的值,此时会导致事务执行失败
(nil)
127.0.0.1:6379> get money
"1555"

解决办法:

127.0.0.1:6379> unwatch			#解锁
OK
127.0.0.1:6379> watch money		#再次监视,获取最新的version
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> DECRBY money 1
QUEUED
127.0.0.1:6379(TX)> incrby money 1
QUEUED
127.0.0.1:6379(TX)> EXEC		#比对监视的值是否发生变化
1) (integer) 1454
2) (integer) 1455

Jedis

1.导入依赖

    <dependencies>
        <!--导入jedis的包-->
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>3.6.0</version>
        </dependency>
        
        <!--导入fastjson-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.73</version>
        </dependency>

    </dependencies>

2.编码测试

锐单商城 - 一站式电子元器件采购平台