2021-06-18

Redis缓存数据库学习

一、Linux环境安装Redis数据库

1.1、下载安装包,上传到home目录下

在这里插入图片描述

1.2、解压安装包(这个放在/opt目录下)

解压命令:tar -zxvf 包名
在这里插入图片描述
解压完成:
在这里插入图片描述
查看解压后的文件:
在这里插入图片描述

1.3、安装gcc-c++环境(Redis是c写的)

命令:yum install gcc-c++
: make
在这里插入图片描述

make install
在这里插入图片描述

1.4、redis默认的安装目录程序在/usr下

在这里插入图片描述

1.5、将redis.conf拷贝到当前安装路径下的/bin/xconfig

绑定配置文件redis.conf
在这里插入图片描述

创建一个xconfig文件
拷贝文件
在这里插入图片描述

1.6、启动redis

修改配置文件,保证redis在后台启动

在这里插入图片描述
启动命令: redis-server
在这里插入图片描述
连接redis : 命令:redis-cli -p 6379
在这里插入图片描述
查看所有键值: 命令: keys *
在这里插入图片描述
查看redis的进程

在这里插入图片描述
关闭redis的服务
在这里插入图片描述
进程同时也关闭
在这里插入图片描述

二、redis-benchmark测试redis性能

redis-benchmark 参数
在这里插入图片描述

1.1、测试100个并发连接,100000个请求

命令:redis-benchmark -h localhost -p 6379 -c 100 -n 100000
在这里插入图片描述

三、redis的基础知识

在这里插入图片描述

1、redis数据库的基础操作

1、redis有16个数据库
在这里插入图片描述
默认使用第0个数据库
可使用select切换数据库 select 3
查看数据库大小 dbsize
查看所有键值:keys *
在这里插入图片描述
在这里插入图片描述
清空当前库 flushdb
在这里插入图片描述
清空所有数据库: flushall
在这里插入图片描述

2、redis是单线程的

在这里插入图片描述
在这里插入图片描述

四、关于RedisKey的基本命令

flushdb :清空当前库
flushall :清空所有库
set :设置键值 set name wxs
get 获取键值数据 get name
exists 键名 :判断键值是否存在
move 键名 1 :移除键
expire 键名 秒数 :倒计时多少秒后移除,设置key的过期时间
ttl 键名 :查看倒计时秒数,查看当前key的剩余时间
type 键名 :查看key的的类型

(integer) 0
127.0.0.1:6379> flushall
OK
127.0.0.1:6379> set name wxs
OK
127.0.0.1:6379> get name
“wxs”
127.0.0.1:6379> exist name
(error) ERR unknown command exist, with args beginning with: name,
127.0.0.1:6379> exists name
(integer) 1
127.0.0.1:6379> move name 1
(integer) 1
127.0.0.1:6379> keys *
(empty array)
127.0.0.1:6379> set name wxs
OK
127.0.0.1:6379> get name
“wxs”
127.0.0.1:6379> expire name 10s
(error) ERR value is not an integer or out of range
127.0.0.1:6379> expire name 10
(integer) 1
127.0.0.1:6379> ttl name
(integer) 6
127.0.0.1:6379> ttl name
(integer) 1
127.0.0.1:6379> ttl name
(integer) -2
127.0.0.1:6379> keys *
(empty array)
127.0.0.1:6379>
127.0.0.1:6379> type name
string
127.0.0.1:6379>
在这里插入图片描述

五、Redis的五种数据类型

1.String字符串类型(命令)

append 键名 “字符串” :追加字符串 追加字符串,如果key不存在,就相当于set
127.0.0.1:6379> append name “dxy”
(integer) 6
127.0.0.1:6379> get name
“wxsdxy”
127.0.0.1:6379>
##################################################
strlen 键名 :查看字符串长度
127.0.0.1:6379> strlen name
(integer) 6
127.0.0.1:6379> append name “qwe”
(integer) 9
127.0.0.1:6379> strlen name
(integer) 9
127.0.0.1:6379>
###############################################

incr 键名 : 加一
decr 键名 :减一
incrby 键名 长度 :加步长
decrby 键名 长度 :减步长
127.0.0.1:6379> incr views
(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>
127.0.0.1:6379> get views
“0”

127.0.0.1:6379> incrby views 10
(integer) 10
127.0.0.1:6379> get views
“10”
127.0.0.1:6379>
127.0.0.1:6379> decrby views 5
(integer) 5
127.0.0.1:6379>
#####################################################
替换字符串中的字母:指定开始的位置替换
setrange 键名 1 xx

127.0.0.1:6379> get name
“wxs”
127.0.0.1:6379> setrange name 1 xxx
(integer) 4
127.0.0.1:6379> get name
“wxxx”
127.0.0.1:6379>

###############################################################
setex 设置过期时间
setnx
如果没有值的情况下可以覆盖设值 在分布式锁中常被使用
127.0.0.1:6379> setex name 30 abc
OK
127.0.0.1:6379> ttl name
(integer) 25
127.0.0.1:6379> ttl name
(integer) -2
127.0.0.1:6379> get name
(nil)
127.0.0.1:6379> setnx name wxsd
(integer) 1 创建成功
127.0.0.1:6379> get name
“wxsd”
127.0.0.1:6379> setnx name sss name存在就创建失败
(integer) 0 创建失败
127.0.0.1:6379>

######################################################

设置多个批量设置
mset

mget
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
  4. “v1”
  5. “v2”
  6. “v3”
    127.0.0.1:6379>

#############################################
msetnx
127.0.0.1:6379> keys *

  1. “k2”
  2. “k3”
  3. “k1”
    127.0.0.1:6379> msetnx k1 v1 k4 v4 k1存在,k4不存在, 原子性操作,要么一起成功要么一起失败
    (integer) 0
    127.0.0.1:6379> keys *
  4. “k2”
  5. “k3”
  6. “k1”

对象:
user

set user:1{name:wxs,age:22}
这里的key是个巧妙的设计
mset user:1:name wxs user:1:age 22
mget user:1:name user:1age

127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> mset user:1:name wxs user:1:age 22
OK
127.0.0.1:6379> mget user:1:name user:1:age

  1. “wxs”
  2. “22”
    127.0.0.1:6379>
    ############################################################

getset
先get得到上层的值,后set设置新值
127.0.0.1:6379> getset db redis 如果存在值返回上层的值
(nil)
127.0.0.1:6379> get db
“redis”
127.0.0.1:6379> getset db mondb 如果存在值,获取原来的值,并设置新的值
“redis”
127.0.0.1:6379> get db
“mondb”
127.0.0.1:6379>

在这里插入图片描述

2、List列表类型

所有的List列表命令,都是以L开头的
在这里插入图片描述
#############################################################
命令:
lpush
lrange

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 throw
(integer) 3
127.0.0.1:6379> lrange list 0 -1 获取全部值

  1. “throw”
  2. “two”
  3. “one”
    127.0.0.1:6379> lrange list 0 1 获取后两个值,类似于栈先进后出
  4. “throw”
  5. “two”

rpush:
127.0.0.1:6379> rpush list right 从右侧插入值
(integer) 4
127.0.0.1:6379> lrange list 0 -1

  1. “throw”
  2. “two”
  3. “one”
  4. “right”
    127.0.0.1:6379>

###############################################################
移除命令:
lpop
左边移除
rpop 右边移除
127.0.0.1:6379> lrange list 0 -1 查询所有值

  1. “throw”
  2. “two”
  3. “one”
  4. “right”
    127.0.0.1:6379> lpop list 移除左侧值
  5. “throw”
    127.0.0.1:6379> rpop list 移除右侧值
    “right”
    127.0.0.1:6379> lrange list 0 -1
  6. “two”
  7. “one”
    127.0.0.1:6379>
    ###############################################################
    lindex 下标

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>
    ###############################################################
    llen 获取长度
    127.0.0.1:6379> llen list 获取list的长度
    (integer) 2
    127.0.0.1:6379>

###############################################################
移除指定的值
lrem
127.0.0.1:6379> lrange list 0 -1

  1. “two”
  2. “two”
  3. “one”
    127.0.0.1:6379> lrem list 1 one 从上倒下移除指定的1个值
    (integer) 1
    127.0.0.1:6379> lrange list 0 -1
  4. “two”
  5. “two”
    127.0.0.1:6379> lrem list 2 two 移除两个值,从上倒下依次移除指定的值
    (integer) 2
    127.0.0.1:6379> lrange list 0 -1
    (empty array)
    127.0.0.1:6379>
    ###############################################################
    ltrim 截取 通过下标截取
    127.0.0.1:6379> lpush list “hoole1”
    (integer) 1
    127.0.0.1:6379> lpush list “hollo2”
    (integer) 2
    127.0.0.1:6379> lpush list “hoole3”
    (integer) 3
    127.0.0.1:6379> lpush list “hool4”
    (integer) 4
    127.0.0.1:6379> lrange list 0 -1
  6. “hool4”
  7. “hoole3”
  8. “hollo2”
  9. “hoole1”
    127.0.0.1:6379> ltrim list 1 2 截取两个值
    OK
    127.0.0.1:6379> lrange list 0 -1
  10. “hoole3”
  11. “hollo2”
    ###############################################################
    rpoplpush 移除列表最后一个元素,放在新的列表中
    127.0.0.1:6379> lrange list 0 -1
  12. “dxy”
  13. “wxs”
  14. “hoole3”
  15. “hollo2”
    127.0.0.1:6379> rpoplpush list mylist
    “hollo2”
    127.0.0.1:6379> lrange mylist 0 -1
  16. “hollo2”
    127.0.0.1:6379>
    ###############################################################
    将列表中的元素更新
    lset

    127.0.0.1:6379> lpush list wxs
    (integer) 1
    127.0.0.1:6379> lrange list 0 -1
  17. “wxs”
    127.0.0.1:6379> lset list 0 dxy
    OK
    127.0.0.1:6379> lrange list 0 -1
  18. “dxy”
    127.0.0.1:6379>
    ###############################################################
    linsert 在指定key前面后面插入值
    127.0.0.1:6379> rpush list wxs
    (integer) 1
    127.0.0.1:6379> rpush list dxy
    (integer) 2
    127.0.0.1:6379> lrange list 0 -1
  19. “wxs”
  20. “dxy”
    127.0.0.1:6379> linsert list before wxs "value"
    (integer) 3
    127.0.0.1:6379> lrange list 0 -1
  21. “value”
  22. “wxs”
  23. “dxy”
    在这里插入图片描述

3、Set集合

127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> clear
127.0.0.1:6379> sadd myset wxs set添加值
(integer) 1
127.0.0.1:6379> smembers myset 查看set集合的值

  1. “wxs”
    127.0.0.1:6379> sismember myset wxs 是否存在这个值
    (integer) 1
    127.0.0.1:6379> scard myset 获取集合中的个数
    (integer) 1
    127.0.0.1:6379>
    127.0.0.1:6379> srem myset wxs 移除元素
    (integer) 1
    127.0.0.1:6379> smembers myset
    (empty array)
    127.0.0.1:6379>
    ###########################################################################
    set是个无序不重复
    127.0.0.1:6379> smembers myset
  2. “yzj”
  3. “wxs”
  4. “dxy”
    127.0.0.1:6379> srandmember myset 随机查询一个元素
    “dxy”
    127.0.0.1:6379> srandmember myset
    “yzj”
    127.0.0.1:6379>
    ###########################################################################
    随机移除一些元素
    127.0.0.1:6379> smembers myset
  5. “yzj”
  6. “wxs”
  7. “dxy”
    127.0.0.1:6379> spop myset 随机删除
    “yzj”
    127.0.0.1:6379> smembers myset
  8. “wxs”
  9. “dxy”
    127.0.0.1:6379>
    ###########################################################################
    127.0.0.1:6379> sadd myset1 dbcksa
    (integer) 1
    127.0.0.1:6379> smembers myset
  10. “wxs”
  11. “dxy”
    127.0.0.1:6379> smove myset myset1 wxs 将一个集合中的指定元素移入另一个集合中
    (integer) 1
    127.0.0.1:6379> smembers myset1
  12. “wxs”
  13. “dbcksa”
    127.0.0.1:6379>
    ###########################################################################
    共同关注(并集)
    差集
    交集
    并集

    127.0.0.1:6379> sadd key1 a
    (integer) 1
    127.0.0.1:6379> sadd key1 b
    (integer) 1
    127.0.0.1:6379> sadd key c
    (integer) 1
    127.0.0.1:6379> sadd key2 c
    (integer) 1
    127.0.0.1:6379> sadd key2 a
    (integer) 1
    127.0.0.1:6379> sadd key2 b
    (integer) 1
    127.0.0.1:6379> sadd key2 r
    (integer) 1
    127.0.0.1:6379> sdiff key1 key2 差集
    (empty array)
    127.0.0.1:6379> sinter key1 key2 交集
  14. “b”
  15. “a”
    127.0.0.1:6379> sunion key1 key2 并集
  16. “c”
  17. “b”
  18. “r”
  19. “a”
    127.0.0.1:6379>
    在这里插入图片描述

4、Hash哈希类型

1、键值加Map集合《key-value》
127.0.0.1:6379> hset myhash field1 kuangsheng 键+
(integer) 1
127.0.0.1:6379> hget myhash field1
“kuangsheng”
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 获取全部的键值对
  3. “field1”
  4. “hello”
  5. “field2”
  6. “world”
    127.0.0.1:6379>
    #################################################################
    127.0.0.1:6379> hdel myhash field1 删除指定字段
    (integer) 1
    127.0.0.1:6379> hgetall myhash
  7. “field2”
  8. “world”
    127.0.0.1:6379>
    ##################################################################
    127.0.0.1:6379> hlen myhash 当前长度
    (integer) 1
    127.0.0.1:6379>
    127.0.0.1:6379> hmset myhash field1 word field2 qaza field3 bwbuwbu
    OK
    127.0.0.1:6379> hgetall myhash
  9. “field2”
  10. “qaza”
  11. “field1”
  12. “word”
  13. “field3”
  14. “bwbuwbu”
    127.0.0.1:6379> hlen myhash
    (integer) 3
    127.0.0.1:6379>
    ###############################################################
    127.0.0.1:6379> hexists myhash field1 判断hash中的hash值是否存在
    (integer) 1
    127.0.0.1:6379>
    127.0.0.1:6379> hkeys myhash 查询所有的键
  15. “field2”
  16. “field1”
  17. “field3”
    127.0.0.1:6379> hvals myhash 显示所有的值
  18. “qaza”
  19. “word”
  20. “bwbuwbu”
    127.0.0.1:6379>
    #########################################################
    127.0.0.1:6379> hsetnx myhash field1 wxssss 当键值存在时,不会创建
    (integer) 0
    127.0.0.1:6379> hsetnx myhash field4 wxsdt 键值不存在时,创建
    (integer) 1
    ##########################################################
    hash变更的数据,user name age 尤其是用户信息等,经常变动的信息,hash更适合存储对象,String更适合存储字符串

5、Zset有序集合

在set的基础之上,增加一个值,Zset: set k1 v1 zset k1 score1 v1
127.0.0.1:6379> zadd myset 1 one 设置一个值
(integer) 1
127.0.0.1:6379> zadd myset 2 two 3 three 设置多个值
(integer) 2
127.0.0.1:6379> zrange myset 0 -1 查询所有值

  1. “one”
  2. “two”
  3. “three”
    127.0.0.1:6379>
    #####################################################
    排序如何实现
    127.0.0.1:6379> zadd scorey 5500 wxs
    (integer) 1
    127.0.0.1:6379> zadd scorey 5300 dxy 存储3个数据
    (integer) 1
    127.0.0.1:6379> zadd scorey 7800 wxsdd
    (integer) 1
    127.0.0.1:6379> zrangebyscore scorey -inf +inf 从小到大排序
  4. “dxy”
  5. “wxs”
  6. “wxsdd”
    127.0.0.1:6379> zrevrange scorey 0 -1 从大到小排序
  7. “wxsdd”
  8. “dxy”
    127.0.0.1:6379>
    127.0.0.1:6379> zrangebyscore scorey -inf +inf withscores 从小到大排序并携带数据
  9. “dxy”
  10. “5300”
  11. “wxs”
  12. “5500”
  13. “wxsdd”
  14. “7800”
    127.0.0.1:6379> zrangebyscore scorey -inf 5500 withscores 根据区间来查询数据,显示工资少于5500的员工的降序排列
  15. “dxy”
  16. “5300”
  17. “wxs”
  18. “5500”
    127.0.0.1:6379>
    #############################################################################
    移除元素
    127.0.0.1:6379> zrange scorey 0 -1 查询所有数据
  19. “dxy”
  20. “wxs”
  21. “wxsdd”
    127.0.0.1:6379> zrem scorey wxs 移除指定数据
    (integer) 1
    127.0.0.1:6379> zrange scorey 0 -1
  22. “dxy”
  23. “wxsdd”
    127.0.0.1:6379>
    127.0.0.1:6379> zcard scorey 获取有序集合中的个数
    (integer) 2
    127.0.0.1:6379>
    #######################################################
    127.0.0.1:6379> zadd myset 1 wxs
    (integer) 1
    127.0.0.1:6379> zadd myset 2 dxy
    (integer) 1
    127.0.0.1:6379> zadd myset 3 hevcv
    (integer) 1
    127.0.0.1:6379> zrange myset 0 -1
  24. “wxs”
  25. “dxy”
  26. “hevcv”
    127.0.0.1:6379> zcount myset 1 3 获取区间的值的个数
    (integer) 3
    127.0.0.1:6379> zcount myset 1 2
    (integer) 2
    127.0.0.1:6379>
    ####################################################################
    案例思路:
    set排序 、工资表排序、班级成绩排序等等
    普通消息 1 重要消息 2 带权重判断
    排行榜排序,Top N

六、三种特殊数据类型

1、geospatial地理位置详情

应用:朋友的定位,附近的人,打车距离计算
在这里插入图片描述
1、geoadd添加城市的经度纬度
两级是没法添加的,一般都是下载好,程序数据,通过java代码程序导入进去
在这里插入图片描述
127.0.0.1:6379> geoadd china:city 116.40 39.90 beijing 添加一个地理位置坐标
(integer) 1
127.0.0.1:6379>
127.0.0.1:6379> geopos china:city beijing 获取城市的经度,纬度

    1. “116.39999896287918091”
    2. “39.90000009167092543”
      127.0.0.1:6379>
      在这里插入图片描述
      2、两个人的距离
      在这里插入图片描述
      127.0.0.1:6379> geodist china:city beijing shanghai 北京和上海之间的距离
      “1067378.7564”
      127.0.0.1:6379>
      3、我附近的人(获得所有附近的人的地址,定位) 通过半径查询
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
      这个地理位置详情的底层实现原理就是Zset有序集合原理
      127.0.0.1:6379> zrange china:city 0 -1 查看地图中所有的元素
  1. “shanghai”
  2. “beijing”
    127.0.0.1:6379>
    127.0.0.1:6379> zrem china:city beijing 移除地图中某个数据
    (integer) 1
    127.0.0.1:6379> zrange china:city 0 -1
  3. “shanghai”
    127.0.0.1:6379>

2、Hyperloglog基数统计

在这里插入图片描述
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> pfadd mykey a b c d e f g h i j 添加10个元素
(integer) 1
127.0.0.1:6379> pfcount mykey
(integer) 10
127.0.0.1:6379> pfadd mykey2 i j z x c v b n m 添加9个元素
(integer) 1
127.0.0.1:6379> pfcount mykey2
(integer) 9
127.0.0.1:6379> pfmerge mykey3 mykey mykey2 合并元素,不允许重复出现
OK
127.0.0.1:6379> pfcount mykey3
(integer) 15
127.0.0.1:6379>

如果允许容错,一定可以使用

3、Bitmaps位图场景

位存储
应用场景:打卡、统计用户信息、活跃、不活跃、登录、未登录
BitMap位图 数据结构 都是操作二进制位来进行记录操作 只有0 和 1两个状态
365天=365bit 1字节=8bit 46个字节左右

记录周一到周日的打卡情况
打卡为1 未打卡为0 统计打卡天数是0的多少个,1的多少个
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 0
(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 0
(integer) 0
127.0.0.1:6379> setbit sign 6 0
(integer) 0
127.0.0.1:6379>
查看某一天的打卡情况:
127.0.0.1:6379> getbit sign 3 查看周四打卡
(integer) 1
127.0.0.1:6379>
统计操作,统计打卡的天数:
127.0.0.1:6379> bitcount sign 统计一周打卡的天数
(integer) 3
127.0.0.1:6379>

七、Redis基本的事务操作

Redis事务的本质:执行命令的集合,一个事务中的所有命令,都会被序列化,都会按顺序执行

redis单条命令保证原子性,事务不保证原子性

redid事务没有隔离级别的概念

在事务中所有的命令并不会直接执行,而是在发起执行命令时才会执行!!

一次性,顺序性,排他性
------------- set set set -----------
Redis事务:
开启事务(multi)
命令入队(…)
执行事务(exec)

###############################################################################

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)> get k2
QUEUED
127.0.0.1:6379(TX)> set k3 v3
QUEUED
127.0.0.1:6379(TX)> exec 在事务中所有的命令并不会直接执行,而是在发起执行命令时才会执行!! 执行事务

  1. OK
  2. OK
  3. “v2”
  4. OK
    127.0.0.1:6379>

###############################################################################

放弃事务:
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> set k5 v5
QUEUED
127.0.0.1:6379(TX)> discard 取消事务
OK
127.0.0.1:6379> get k5 事务中的命令不会被执行
(nil)
127.0.0.1:6379>

###############################################################################

编译型异常,命令出错,(事务中所有的命令都不会被执行)
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)> getset k3 命令出错
(error) ERR wrong number of arguments for ‘getset’ command
127.0.0.1:6379(TX)>
127.0.0.1:6379(TX)> set k4 v4
QUEUED
127.0.0.1:6379(TX)> set k5 v5
QUEUED
127.0.0.1:6379(TX)> exec 执行事务时报错,所有命令都不执行
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> get k5
(nil)
127.0.0.1:6379>

###############################################################################

运行时异常,如果一个命令出现语法错误,后面的命令也可以正常执行,所有说没有原子性
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)> get k3
QUEUED
127.0.0.1:6379(TX)> exec 虽然第一条命令执行错误了,但是其他命令依然能够执行

  1. (error) ERR value is not an integer or out of range
  2. OK
  3. OK
  4. “v3”
    127.0.0.1:6379> get k2
    “v2”
    127.0.0.1:6379> get k3
    “v3”
    127.0.0.1:6379>

八、Redis实现乐观锁

悲观锁: 什么时候都会出现问题,无论做什么都会加锁

乐观锁: 认为什么时候都不会出现问题,什么时候都认为不会加锁,更新数据时都需要判断一下,是否这个数据被修改过
获取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 减少20元
QUEUED
127.0.0.1:6379(TX)> incrby out 20 消费20元
QUEUED
127.0.0.1:6379(TX)> exec 执行事务

  1. (integer) 80 剩余80
  2. (integer) 20 减少20
    127.0.0.1:6379>

测试多线程修改,使用Watch可以当作Redis的乐观锁操作
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 当另外线程修改值后,事务执行失败
(nil)
127.0.0.1:6379>

另外一个线程修改了值,
127.0.0.1:6379> get money
“80”
127.0.0.1:6379> set money 1000
OK
127.0.0.1:6379> exec
(error) ERR EXEC without MULTI
127.0.0.1:6379>

如果修改值失败,就解锁,获取最新值
在这里插入图片描述

九、通过Jedis操作Redis

导入依赖:


redis.clients
jedis
3.3.0


com.alibaba
fastjson
1.2.70

编码测试:
连接数据库
操作命令
断开连接
public class Mytest {
public static void main(String[] args) {
Jedis jedis = new Jedis(“127.0.0.1”,6379);
System.out.println(jedis.ping());
}
}
输出:
在这里插入图片描述
常用API(五大数据类型)
String
List
Set
Hash
Zset
在这里插入图片描述
在这里插入图片描述

十、通过Jedis再次理解事务

package com.it.jedis;

import com.alibaba.fastjson.JSONObject;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Transaction;

/**

  • @Description
  • @ClassName testTX
  • @Date 2021/7/6 14:48
    **/

public class testTX {
public static void main(String[] args) {
Jedis jedis = new Jedis(“127.0.0.1”,6379);
JSONObject jsonObject=new JSONObject();
jsonObject.put(“hello”,“world”);
jsonObject.put(“name”,“tome”);
String result = jsonObject.toJSONString();
//开启事务
Transaction multi = jedis.multi();
try {
multi.set(“user1”,result);
multi.set(“user2”,result);
multi.exec(); //执行事务
}catch (Exception e){
multi.discard(); //放弃事务
e.printStackTrace();
}finally {
System.out.println(jedis.get(“user1”));
System.out.println(jedis.get(“user2”));
jedis.close(); //关闭连接
}

}

}

十一、SpringBoot整合Redis

在这里插入图片描述
在这里插入图片描述
1、导入依赖
导入SpringBoot中,spring-data-redis

org.springframework.boot
spring-boot-starter-data-redis

2、配置连接:
spring:
redis:
host: 127.0.0.1
port: 6379
3、测试
package com.it;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;

@SpringBootTest
class Redis02SpringbootApplicationTests {
@Autowired
private RedisTemplate redisTemplate;
@Test
void contextLoads() {
redisTemplate.opsForValue().set(“mykey”,“wxs”); 设置值
System.out.println(redisTemplate.opsForValue().get(“mykey”)); 打印值
}
}

十二、自定义的RedisTemplate

编写一个自己的RedisTemplate
package com.it.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/**

  • @Description
  • @ClassName redisConfig
  • @Date 2021/7/6 17:59
    **/

@Configuration
public class redisConfig {
@Bean
@SuppressWarnings(“all”)
public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){
RedisTemplate<String,Object> template=new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);

   **/json序列化配置**
  Jackson2JsonRedisSerializer<Object> objectJackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
    objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
    objectJackson2JsonRedisSerializer.setObjectMapper(objectMapper);
    
    //String类型的序列化
    StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
    
    //key都使用String类型序列化
    template.setKeySerializer(stringRedisSerializer);
    template.setHashKeySerializer(stringRedisSerializer);
    
    //value使用json类型序列化
    template.setValueSerializer(objectJackson2JsonRedisSerializer);
    template.setHashValueSerializer(objectJackson2JsonRedisSerializer);
    template.afterPropertiesSet();
    return template;

}
}

十三、Redis.conf 配置文件

启动时通过配置文件来启动的
redis-server xconfig/redis.conf

单位换算:
在这里插入图片描述
包含其他配置文件:
在这里插入图片描述
网络和基本配置:
在这里插入图片描述
快照:
在这里插入图片描述
在这里插入图片描述
主从复制:
在这里插入图片描述
Security安全;
在这里插入图片描述
在这里插入图片描述
限制客户端:

在这里插入图片描述

十四、持久化之RDB操作

Redis是内存数据库,如果不将内存中的数据保存在磁盘中,断电既是失去数据,所有Redis提供了数据的持久化,Rdb持久化,AOF持久化
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
产生durmp.rdb文件
在这里插入图片描述
恢复rdb文件:
在这里插入图片描述
在这里插入图片描述

十五、持久化之AOF操作

将所有命令都记录下来,获取数据时,在全部执行一遍命令
在这里插入图片描述
默认 情况下是不开启的: 只需要将appendonly no 改为yes就开启了 aof持久化
在这里插入图片描述

需要重启服务,才能有aof文件

[root@localhost bin]# ls
appendonly.aof redis-benchmark redis-check-rdb redis.conf redis-server
dump.rdb redis-check-aof redis-cli redis-sentinel xconfig
[root@localhost bin]#

在appendonly.aof中保存了所有修改的命令

当appendonly.aof中数据被破坏时,启动不了服务器,可以使用redis-check-aof文件对缓存文件appendonly.aof进行修复
修复文件:
在这里插入图片描述
如果文件正常,重启Redis服务,查看数据恢复正常
在这里插入图片描述
在这里插入图片描述

优点和缺点:
在这里插入图片描述
如果文件大于64mb时,重新创建一个进程,来重写一个文件
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

十六、Redis发布订阅

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
1、订阅一个频道:
127.0.0.1:6379> subscribe wxsshuo
Reading messages… (press Ctrl-C to quit)

  1. “subscribe”
  2. “wxsshuo”
  3. (integer) 1
  4. “message”
  5. “wxsshuo”
  6. “wxsdxyvxsv” 发送消息后得到一个消息体

2、发送消息:
127.0.0.1:6379> publish wxsshuo wxsdxyvxsv
(integer) 1
127.0.0.1:6379>
在这里插入图片描述
应用场景:
实时消息系统
实时聊天室
订阅和关注

十七、Redis主从复制搭建集群(命令行配置)

在这里插入图片描述
在这里插入图片描述
主从复制,读写分离(写少,读多)负载均衡,减轻服务器的压力

环境配置:
只需要配置从库,不需要配置主库

查看主机的信息:
127.0.0.1:6379> info replication 查看当前库的信息
#Replication
role:master 主机
connected_slaves:0 从机为0
master_failover_state:no-failover
master_replid:35e1fd164d9f292aefe2fc3fa56a96cf49f8b2e2
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
127.0.0.1:6379>

搭建集群:一主二从
在这里插入图片描述
树状搭建
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
链路搭建:
在这里插入图片描述

十八、主机宕机后手动选择配置主机

在这里插入图片描述
在这里插入图片描述

十九、哨兵模式(Sentinel)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
如果主机回来了,在哨兵的模式下,只能当作从机,在哨兵模式下已经选了一个之前的从机做主机
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

二十、Redis缓存穿透雪崩

在这里插入图片描述
添加一个过滤器解决
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值