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 *
- “k2”
- “k3”
- “k1”
127.0.0.1:6379> mget k1 k2 k3 - “v1”
- “v2”
- “v3”
127.0.0.1:6379>
#############################################
msetnx
127.0.0.1:6379> keys *
- “k2”
- “k3”
- “k1”
127.0.0.1:6379> msetnx k1 v1 k4 v4 k1存在,k4不存在, 原子性操作,要么一起成功要么一起失败
(integer) 0
127.0.0.1:6379> keys * - “k2”
- “k3”
- “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
- “wxs”
- “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 获取全部值
- “throw”
- “two”
- “one”
127.0.0.1:6379> lrange list 0 1 获取后两个值,类似于栈先进后出 - “throw”
- “two”
rpush:
127.0.0.1:6379> rpush list right 从右侧插入值
(integer) 4
127.0.0.1:6379> lrange list 0 -1
- “throw”
- “two”
- “one”
- “right”
127.0.0.1:6379>
###############################################################
移除命令:
lpop 左边移除
rpop 右边移除
127.0.0.1:6379> lrange list 0 -1 查询所有值
- “throw”
- “two”
- “one”
- “right”
127.0.0.1:6379> lpop list 移除左侧值 - “throw”
127.0.0.1:6379> rpop list 移除右侧值
“right”
127.0.0.1:6379> lrange list 0 -1 - “two”
- “one”
127.0.0.1:6379>
###############################################################
lindex 下标
127.0.0.1:6379> lrange list 0 -1
- “two”
- “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
- “two”
- “two”
- “one”
127.0.0.1:6379> lrem list 1 one 从上倒下移除指定的1个值
(integer) 1
127.0.0.1:6379> lrange list 0 -1 - “two”
- “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 - “hool4”
- “hoole3”
- “hollo2”
- “hoole1”
127.0.0.1:6379> ltrim list 1 2 截取两个值
OK
127.0.0.1:6379> lrange list 0 -1 - “hoole3”
- “hollo2”
###############################################################
rpoplpush 移除列表最后一个元素,放在新的列表中
127.0.0.1:6379> lrange list 0 -1 - “dxy”
- “wxs”
- “hoole3”
- “hollo2”
127.0.0.1:6379> rpoplpush list mylist
“hollo2”
127.0.0.1:6379> lrange mylist 0 -1 - “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 - “wxs”
127.0.0.1:6379> lset list 0 dxy
OK
127.0.0.1:6379> lrange list 0 -1 - “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 - “wxs”
- “dxy”
127.0.0.1:6379> linsert list before wxs "value"
(integer) 3
127.0.0.1:6379> lrange list 0 -1 - “value”
- “wxs”
- “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集合的值
- “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 - “yzj”
- “wxs”
- “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 - “yzj”
- “wxs”
- “dxy”
127.0.0.1:6379> spop myset 随机删除
“yzj”
127.0.0.1:6379> smembers myset - “wxs”
- “dxy”
127.0.0.1:6379>
###########################################################################
127.0.0.1:6379> sadd myset1 dbcksa
(integer) 1
127.0.0.1:6379> smembers myset - “wxs”
- “dxy”
127.0.0.1:6379> smove myset myset1 wxs 将一个集合中的指定元素移入另一个集合中
(integer) 1
127.0.0.1:6379> smembers myset1 - “wxs”
- “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 交集 - “b”
- “a”
127.0.0.1:6379> sunion key1 key2 并集 - “c”
- “b”
- “r”
- “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
- “hello”
- “world”
127.0.0.1:6379> hgetall myhash 获取全部的键值对 - “field1”
- “hello”
- “field2”
- “world”
127.0.0.1:6379>
#################################################################
127.0.0.1:6379> hdel myhash field1 删除指定字段
(integer) 1
127.0.0.1:6379> hgetall myhash - “field2”
- “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 - “field2”
- “qaza”
- “field1”
- “word”
- “field3”
- “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 查询所有的键 - “field2”
- “field1”
- “field3”
127.0.0.1:6379> hvals myhash 显示所有的值 - “qaza”
- “word”
- “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 查询所有值
- “one”
- “two”
- “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 从小到大排序 - “dxy”
- “wxs”
- “wxsdd”
127.0.0.1:6379> zrevrange scorey 0 -1 从大到小排序 - “wxsdd”
- “dxy”
127.0.0.1:6379>
127.0.0.1:6379> zrangebyscore scorey -inf +inf withscores 从小到大排序并携带数据 - “dxy”
- “5300”
- “wxs”
- “5500”
- “wxsdd”
- “7800”
127.0.0.1:6379> zrangebyscore scorey -inf 5500 withscores 根据区间来查询数据,显示工资少于5500的员工的降序排列 - “dxy”
- “5300”
- “wxs”
- “5500”
127.0.0.1:6379>
#############################################################################
移除元素
127.0.0.1:6379> zrange scorey 0 -1 查询所有数据 - “dxy”
- “wxs”
- “wxsdd”
127.0.0.1:6379> zrem scorey wxs 移除指定数据
(integer) 1
127.0.0.1:6379> zrange scorey 0 -1 - “dxy”
- “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 - “wxs”
- “dxy”
- “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 获取城市的经度,纬度
-
- “116.39999896287918091”
- “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 查看地图中所有的元素
- “shanghai”
- “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 - “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 在事务中所有的命令并不会直接执行,而是在发起执行命令时才会执行!! 执行事务
- OK
- OK
- “v2”
- 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 虽然第一条命令执行错误了,但是其他命令依然能够执行
- (error) ERR value is not an integer or out of range
- OK
- OK
- “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 执行事务
- (integer) 80 剩余80
- (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)
- “subscribe”
- “wxsshuo”
- (integer) 1
- “message”
- “wxsshuo”
- “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缓存穿透雪崩
添加一个过滤器解决