Redis五大基本数据类型和三大特殊数据类型

Redis

  • nosql讲解
  • 阿里巴巴架构演进
  • nosql数据模型
  • Redis入门
  • Redis安装(windows&linux)

Nosql概述

很多的数据类型用户的个人信息, 社交网络,地理位置。这些数据类型的存储不需要一个固定的格式 !不需要多月的操作就可以横向扩展的! Map<String,Object> 使用键值对来控制!

NOSQL特点

  1. 方便扩展(数据之间没有关系,很好扩展!)

  2. 大数据量高性能

  3. 数据类型是多样型的

  4. 传统RDBMS和nosql

    传统的RDBMS和nosql
    -结构化组织
    -SQL
    -数据和关系都存在单独的表中
    -操作,数据定义语言
    -严格一致性
    -基础事务
    
    nosql
    -不仅仅是数据
    -没有固定的查询语句
    -键值对存储,列存储,图形数据库(社交关系)
    -高性能,高可用,高扩展
    

    大数据时代的3V:主要是描述问题的

    ​ 1.海量 volume

    ​ 2.多样

    ​ 3.实时

    三高

    高并发

    高扩展

    高性能

安装

先安装 gcc-c++

yum install gcc-c++

make
make install

报错:

1 make[1]: *** [server.o] Error 1

原因是因为gcc版本过低,yum安装的gcc是4.8.5的。因此需要升级gcc,升级过程如下:

yum -y install centos-release-scl
yum -y install devtoolset-9-gcc devtoolset-9-gcc-c++ devtoolset-9-binutils
#这句是临时的
scl enable devtoolset-9 bash
#修改环境变量
echo "source /opt/rh/devtoolset-9/enable" >> /etc/profile
gcc -v

redis的默认安装路径/usr

[root@master redis-6.0.5]# cd /usr/
[root@master usr]# ls
bin  games    lib    libexec  sbin   src
etc  include  lib64  local    share  tmp
[root@master usr]# cd local/
[root@master local]# ls
bin  etc  games  include  lib  lib64  libexec  sbin  share  src
[root@master local]# cd bin/
[root@master bin]# ls
redis-benchmark  redis-check-rdb  redis-sentinel
redis-check-aof  redis-cli        redis-server
[root@master bin]# pwd
/usr/local/bin

测试

#测试:100并发 100000请求
redis-benchmark -h localhost -p 6379 -c 100 -n 100000

基础知识

redis默认有十六个数据库

默认使用的是第0个

可以使用select进行切换

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MGhcHnmO-1596033904628)(C:\Users\diudiu\AppData\Roaming\Typora\typora-user-images\image-20200720192839962.png)]

redis是单线程 (6379 粉丝效应)

明白redis是很快的,官方表示,redis是基于内存操作,CPU不是redis性能瓶颈,redis的瓶颈是根据机器的内存和网络带宽,既然可以使用单线程来实现,就使用单线程了!所以就使用了单线程

redis是C语言写的,官方提供的数据为100000的QPS,完全不比同样是使用key-value的memecache差!

redis为啥单线程还这么快

1误区1:高性能的服务器一定是多线程?

2误区2:多线程(cpu上下文切换)一定比单线程效率高

核心:redis是将所有的数据全部放在内存中的,所有说使用单线程去操作效率就是最高的,多线程(cpu上下文切换:耗时操作),对于内存系统来说,如果没有上下切换效率就是最高的!多次读写都在一个CPU上,在内存情况下这个就是最佳方案

五大数据类型

Redis是一个开源( BSD许可)的,内存中的数据结构存储系统,它可以用作 数据库缓存消息中间件MQ。它支持多种类型的数据结构,如字符串( strings),散列(hashes) ,列表(lists),集合(sets) ,有序集合( sortedsets)与范围查询,bitmaps,hyperloglogs 和地理空间( geospatial )索引半径查询。Redis 内置了复制( replication) , LUA脚本(Luascripting) , LRU驱动事件( LRU eviction) , 事务( transactions )和不同级别的磁盘持久化( persistence ) , 并通过Redis哨兵( Sentinel )和自动分区( Cluster )提供高可用性( high availability )。

redis-key

127.0.0.1:6379> keys *
(empty array)
127.0.0.1:6379> set age 1
OK
127.0.0.1:6379> keys *
1) "age"
127.0.0.1:6379> EXISTS age
(integer) 1
127.0.0.1:6379> EXISTS age1
(integer) 0
127.0.0.1:6379> MOVE age
(error) ERR wrong number of arguments for 'move' command
127.0.0.1:6379> MOVE age 1
(integer) 1
127.0.0.1:6379> set name qwc
OK
127.0.0.1:6379> get name
"qwc"
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) 5
127.0.0.1:6379> ttl name
(integer) 4
127.0.0.1:6379> ttl name
(integer) 3
127.0.0.1:6379> ttl name
(integer) 2
127.0.0.1:6379> ttl name
(integer) 1
127.0.0.1:6379> ttl name
(integer) 1
127.0.0.1:6379> ttl name
(integer) -2
127.0.0.1:6379> get name
(nil)

string(字符串)

##################################################################
127.0.0.1:6379> set key1 v1 #设置值
OK
127.0.0.1:6379> get key1 #获取值
"v1"
127.0.0.1:6379> keys *
1) "key1"
127.0.0.1:6379> EXISTS key1 #是否存在
(integer) 1
127.0.0.1:6379> APPEND key1 hello #追加
(integer) 7
127.0.0.1:6379> get key1
"v1hello"
127.0.0.1:6379> STRLEN key1 #获取长度
(integer) 7
127.0.0.1:6379> APPEND key1 ,qwc
(integer) 11
127.0.0.1:6379> get key1
"v1hello,qwc"
##################################################################
#i++
#步长 
127.0.0.1:6379> set views 0
OK
127.0.0.1:6379> get views
"0"
127.0.0.1:6379> incr views
(integer) 1
127.0.0.1:6379> incr views
(integer) 2
127.0.0.1:6379> get views
"2"
127.0.0.1:6379> DECR views
(integer) 1
127.0.0.1:6379> DECR views
(integer) 0
127.0.0.1:6379> DECR views
(integer) -1
127.0.0.1:6379> INCR views
(integer) 0
127.0.0.1:6379> INCRBY views 10
(integer) 10
127.0.0.1:6379> INCRBY views 10
(integer) 20
127.0.0.1:6379> INCRBY views 10
(integer) 30
127.0.0.1:6379> DECRBY views 5
(integer) 25
127.0.0.1:6379> DECRBY views 5
(integer) 20
127.0.0.1:63
##################################################################
#字符串范围range
127.0.0.1:6379> set key1 hello,kuagns 
OK
127.0.0.1:6379> GETRANGE key1 0 4
"hello"
127.0.0.1:6379> GETRANGE key1 0 -1
"hello,kuagns"
#替换
127.0.0.1:6379> set key2 abcdef
OK
127.0.0.1:6379> SETRANGE key2 1 xx
(integer) 6
127.0.0.1:6379> get key2
"axxdef"
127.0.0.1:6379> 
##################################################################
#setex(set with exoire) #设置过期时间
#setnx(set if not exist) #不存在在设置(在分布式锁中会常常使用! )
127.0.0.1:6379> setex key3 20 hello #设置key3 hello 20秒过期
OK
127.0.0.1:6379> ttl key3
(integer) 15
127.0.0.1:6379> SETNX mykey redis #不存在就设置
(integer) 1
127.0.0.1:6379> keys *
1) "mykey"
2) "key2"
3) "key1"
127.0.0.1:6379> SETNX mykey mogondb #存在就不能设置
(integer) 0
127.0.0.1:6379> get mykey
"redis"
127.0.0.1:6379> 
##################################################################
#mset
#mget
127.0.0.1:6379> mset key1 v1 k2 v2 k3 v3 #同时设置多个值
OK
127.0.0.1:6379> mget key1 k2 k3 #同时获取多个值
1) "v1"
2) "v2"
3) "v3"
127.0.0.1:6379> msetnx k2 v2 k4 v4 #msetnx是一个原子性操作,要么一起成功,要么一起失败
(integer) 0
127.0.0.1:6379> get k4
(nil)
127.0.0.1:6379> 

#对象
set user:1 {name:zhangshan,age:3}

127.0.0.1:6379> mset user:1:name zhangshan user:1:age 2
OK
127.0.0.1:6379> mget user:1:name user:1:age
1) "zhangshan"
2) "2"
##################################################################
getset #先get再set
127.0.0.1:6379> getset db redis #如果不存在值,则返回ni1
(nil)
127.0.0.1:6379> get db
"redis"
127.0.0.1:6379> getset db mongodb #如果存在值,获取原来的值,并设置新的值
"redis"
127.0.0.1:6379> get db
"mongodb"

数据结构是想通的

string类型的使用场景:value 除了是我们的字符串还可以是数字

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

list

127.0.0.1:6379> LPUSH list1 one
(integer) 1
127.0.0.1:6379> LPUSH list1 two
(integer) 2
127.0.0.1:6379> LPUSH list1 three
(integer) 3
127.0.0.1:6379> LRANGE list1 0 -1
1) "three"
2) "two"
3) "one"
127.0.0.1:6379> LRANGE list1 0 1
1) "three"
2) "two"
127.0.0.1:6379> RPUSH list1 right
(integer) 4
127.0.0.1:6379> LRANGE list1 0 -1
1) "three"
2) "two"
3) "one"
4) "right"

小结

●他实际上是一个链表, before Node after ,left , right都可以插入值
●如果key不存在,创建新的链表
●如果key存在,新增内容
●如果移除了所有值,空链表,也代表不存在!
●在两边插入或者改动值,效率最高!中间元素,相对来说效率会低一点

消息队列(lpush rpop),栈(lpush lpop)

set(集合)

set中的值不能重复,无序

############################################################################
127.0.0.1:6379> SADD myset hello  #set集合中添加元素
(integer) 1
127.0.0.1:6379> SADD myset qwc
(integer) 1
127.0.0.1:6379> SADD myset qwc
(integer) 0
127.0.0.1:6379> SADD myset qwc1
(integer) 1
127.0.0.1:6379> SADD myset qwc2
(integer) 1
127.0.0.1:6379> SMEMBERS myset #查看set的所有值
1) "qwc2"
2) "hello"
3) "qwc"
4) "qwc1"
127.0.0.1:6379> SISMEMBER myset hello #判断某一个值是不是在set集合中
(integer) 1
127.0.0.1:6379> SISMEMBER myset q
(integer) 0
############################################################################
7.0.0.1:6379> SCARD myset #获取set 集合中的元素个数
(integer) 4
127.0.0.1:6379> SREM myset qwc #移除某一个元素
(integer) 1
127.0.0.1:6379> SCARD myset
(integer) 3
127.0.0.1:6379> SMEMBERS myset
1) "qwc2"
2) "hello"
3) "qwc1"
############################################################################
set 无序不重复集合

127.0.0.1:6379> SRANDMEMBER myset #随机抽选出一个元素
"hello"
127.0.0.1:6379> SRANDMEMBER myset
"qwc2"
127.0.0.1:6379> SRANDMEMBER myset
"qwc1"
127.0.0.1:6379> SRANDMEMBER myset
"qwc2"
127.0.0.1:6379> SRANDMEMBER myset
"qwc2"
127.0.0.1:6379> SRANDMEMBER myset 2  #随机抽选出指定个数的元素
1) "hello"
2) "qwc2"
127.0.0.1:6379> SRANDMEMBER myset 2
1) "hello"
2) "qwc1"
127.0.0.1:6379> SRANDMEMBER myset 2
1) "qwc2"
2) "qwc1"
############################################################################
删除指定的key,删除随机key
127.0.0.1:6379> SMEMBERS myset
1) "qwc2"
2) "hello"
3) "qwc1"
127.0.0.1:6379> spop myset
"qwc1"
127.0.0.1:6379> SMEMBERS myset
1) "qwc2"
2) "hello"
127.0.0.1:6379> SMOVE myset qwc myset2
(integer) 0
127.0.0.1:6379> SMOVE myset myset2 qwc
(integer) 1
127.0.0.1:6379> SMEMBERS myset
1) "hello"
2) "world"
127.0.0.1:6379> SMEMBERS myset2
1) "qwc"
2) "set2"

############################################################################
微博,B站,共同关注! (并集)
数字集合类:
-差集 SDIFF
-交集 SINTER
-并集 SUNION
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 key1 c
(integer) 1
127.0.0.1:6379> SADD key1 d
(integer) 1
127.0.0.1:6379> SADD key2 c
(integer) 1
127.0.0.1:6379> SADD key2 d
(integer) 1
127.0.0.1:6379> SADD key2 e
(integer) 1
127.0.0.1:6379> SDIFF key1 key2
1) "b"
2) "a"
127.0.0.1:6379> SINTER key1 key2
1) "d"
2) "c"
127.0.0.1:6379> SUNION key1 key2
1) "c"
2) "a"
3) "b"
4) "d"
5) "e"

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

共同关注,共同爱好,二度好友,推荐好友

Hash(哈希)

Map集合,key-

set myhash field1 qwc

127.0.0.1:6379> HSET myhash field1 qinweichao #set一个具体的key-value
(integer) 1
127.0.0.1:6379> HGET myhash field1
"qinweichao"
127.0.0.1:6379> HMSET myhash field1 hello field2 word #set多个的key-value
OK
127.0.0.1:6379> HMGET myhash field1 field2 #获取多个字段值
1) "hello"
2) "word"
127.0.0.1:6379> HGETALL myhash #获取全部值
1) "field1"
2) "hello"
3) "field2"
4) "word"
127.0.0.1:6379> HDEL myhash field1 #删除指定key 对应的value也消失了
(integer) 1
127.0.0.1:6379> HGETALL myhash
1) "field2"
2) "word"
127.0.0.1:6379> HLEN myhash #获取长度
(integer) 1
127.0.0.1:6379> 
####################################################################
#只获得所有field
#只获得所有value
127.0.0.1:6379> keys *
1) "myhash"
127.0.0.1:6379> hkeys myhash
1) "field2"
127.0.0.1:6379> HVALS myhash
1) "word"
####################################################################
inc decr
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> HINCRBY myhash field3 -1
(integer) 5
127.0.0.1:6379> HSETNX myhash field4 hello #不存在可以设置
(integer) 1
127.0.0.1:6379> HSETNX myhash field4 world #存在不能设置
(integer) 0

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

Zset(有序集合)

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

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 salary 2500 a
(integer) 1
127.0.0.1:6379> ZADD salary 3000 b
(integer) 1
127.0.0.1:6379> ZADD salary 3500 c
(integer) 1
127.0.0.1:6379> ZRANGEBYSCORE salary -inf +inf
1) "a"
2) "b"
3) "c"
127.0.0.1:6379> ZRANGEBYSCORE salary +inf -inf
(empty array)
127.0.0.1:6379> ZRANGEBYSCORE salary 0 -1
(empty array)
127.0.0.1:6379> ZRANGEBYSCORE salary -inf +inf 
1) "a"
2) "b"
3) "c"
127.0.0.1:6379> ZRANGEBYSCORE salary -inf +inf withscores #升序排序
1) "a"
2) "2500"
3) "b"
4) "3000"
5) "c"
6) "3500"
127.0.0.1:6379> ZREVRANGEBYSCORE salary +inf -inf withscores #降序排序
1) "c"
2) "3500"
3) "b"
4) "3000"
5) "a"
6) "2500"
#############################################################
移除rem
127.0.0.1:6379> zrem salary a
(integer) 1
127.0.0.1:6379> ZRANGE salary 0 -1
1) "b"
2) "c"

127.0.0.1:6379> ZCARD salary #获取个数
(integer) 2
127.0.0.1:6379> ZCOUNT salary 0 2000 #计数
(integer) 0
127.0.0.1:6379> ZCOUNT salary 0 3000
(integer) 1
127.0.0.1:6379> ZCOUNT salary 0 4000
(integer) 2

其余的一些API ,通过我们的学习吗,你们剩下的如果工作中有需要,这个时候你可以去查查看官方文档!

案例思路: set排序存储班级成绩表,工资表排序!

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

排行榜应用实现

三种特殊数据类型

geospatial地理位置

朋友的定位,附近的人,打车距离计算?
Redis的Geo在Redis3.2版本就推出了!
可以查询一些测试数据: http://www.jsons.cn/lngcodeinfo/0706D99C19A781A3/

geoadd

#geoadd 添加地理位置
#规则:两极无法自接添加,我们一般会下载城市数据,直接通过java程序一次性导入
#有效的经度从-180度到180度。
#有效的纬度从-85. 05112878度到85.05112878度。
#当坐标位置超出上述指定范围时,该命令将会返回一个错误。
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 shengzhen 120.16 30.24 hangzhou
(integer) 2

getpos

127.0.0.1:6379> GEOPOS china:city beijin
1) 1) "116.39999896287918091"
   2) "39.90000009167092543"
127.0.0.1:6379> GEOPOS china:city beijin shengzhen
1) 1) "116.39999896287918091"
   2) "39.90000009167092543"
2) 1) "114.04999762773513794"
   2) "22.5200000879503861"
127.0.0.1:6379> 

geodist

两人之间的距离!
单位:
●m表示单位为米。
●km表示单位为干米。
●mi表示单位为英里。
●ft表示单位为英尺。

127.0.0.1:6379> geodist china:city beijin shanghai km
"1067.3788"

georadius

我附近的人? ( 获得所有附近的人的地址,定位! )通过半径来查询!

127.0.0.1:6379> GEORADIUS china:city 110 30 1000 km
1) "chongqing"
2) "shengzhen"
3) "hangzhou"
127.0.0.1:6379> GEORADIUS china:city 110 30 500 km
1) "chongqing"

geohash

该命令将返回1 1个字符的Geohash字符串!

#将二维的经纬度转换为- -维的字符串,如果两个字符串越接近,那么则距离越近!
127.0.0.1:6379> GEOHASH china:city beijin chongqing
1) "wx4fbxxfke0"
2) "wm5xzrybty0"

GEO底层的实现原理其实就是zset

127.0.0.1:6379> ZRANGE china:city 0 -1 #查看地图全部元素
1) "chongqing"
2) "shengzhen"
3) "hangzhou"
4) "shanghai"
5) "beijin"
127.0.0.1:6379> zrem china:city beijin #删除地图指定元素
(integer) 1
127.0.0.1:6379> ZRANGE china:city 0 -1
1) "chongqing"
2) "shengzhen"
3) "hangzhou"
4) "shanghai"

hyperloglog

什么是基数?

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

基数(不重复的元素) =5

简介

Redis 2.8.9版本就更新了Hyperloglog数据结构!

Redis Hyperloglog 基数统计的算法

优点:占用的内存是固定,2^64不同的元素的技术,只要12KB内存!如果要从内存角度来比较的话Hyperloglog首选!

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

传统方式,set保存用户的id,然后就可以统计set中的元素数量作为标准判断

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

0.81%错误率!统计UV任务,可以忽略不计的!

测试使用

127.0.0.1:6379> PFadd mykey a b C defghij # 创建第一组元素mykey
(integer) 1
127.0.0.1:6379> PFCOUNT mykey # 统计mykey元素的基数数量
(integer) 10
127.0.0.1:6379> PFadd mykey2 i j z x cvbnm #创建第二组元素mykey2
(integer) 1
127.0.0.1:6379> PFCOUNT mykey2
(integer) 9
127.0.0.1:6379> PFMERGE mykey3 mykey mykey2 ##合并两组mykey mykey2 => mykey3并集
127.0.0.1:6379> PFCOUNT mykey3 #查看并集数
(integer) 15

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

如果不允许容错,就使用set或者自己的数据类型即可

Bitmaps

位存储

统计疫情感染人数:01010

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

使用bitmap来记录周一到周日的打卡!

周一:1 ;周二:0

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vgAPSESX-1596033904639)(C:\Users\diudiu\AppData\Roaming\Typora\typora-user-images\image-20200721111442411.png)]

查看某一天是否打卡

127.0.0.1:6379> GETBIT sign 2
(integer) 1
127.0.0.1:6379> GETBIT sign 5
(integer) 0

统计打卡天数

127.0.0.1:6379> BITCOUNT sign
(integer) 4

事务

mysql:acid要么同时成功,要么同时失败,原子性!

redis单条保持原子性的,但是事务不保证原子性

redis事务本质:一组命令的集合!一个事务中的所有命令都会被序列化,在事务执行过程中,会按照顺序执行!

一次性、顺序性、排他性、

-----队列 set set set 执行----

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

所有的命令在事务中,并没有直接被执行!只有发起执行命令的时候才会执行! Exec
Redis单条命令式保存原子性的,但是事务不保证原子性!
redis的事务:
●开启事务( multi)
●命令入队( …)
●执行事务( exec)

正常执行事务!

127.0.0.1:6379> MULTI #开启事务
OK
#命令入队
127.0.0.1:6379> set k1 v2
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> get k2
QUEUED
127.0.0.1:6379> set k3 v3 
QUEUED
127.0.0.1:6379> exec #执行事务
1) OK
2) OK
3) "v2"
4) OK

放弃事务

127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set k1 v1
QUEUED
127.0.0.1:6379> set k4 v4
QUEUED
127.0.0.1:6379> DISCARD
OK
127.0.0.1:6379> get k4
(nil)

编译型异常(代码有问题!命令错误),事务中的命令都不会执行

127.0.0.1:6379> mu1ti
OK
127.0.0.1:6379> set k1 v1
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> set k3 v3 
QUEUED
127. 0.0.1:6379> getset k3|
(error) ERR wrong number of arguments for ' getset' command
127.0.0.1:6379> set k4 v4 
QUEUED
127.0.0.1:6379> set k5 v5
QUEUED
127.0.0.1:6379> exec 
(error) EXECABORT Transaction discarded because of previous errors .
127.0.0.1:6379> get k5
(ni1)

运行时异常( 1/0),如果事务队列中存在语法性,那么执行命令的时候,其他命令是可以正常执行的,

127.0.0.1:6379> set k1 "v1"
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> incr kl
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> set k3 v3
QUEUED
127.0.0.1:6379> get k3
QUEUED
127.0.0.1:6379> exec
1) Cerror) 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"

监控

悲观锁:

  • 很悲观,认为什么时候都会出问题,无论做什么都会加锁!

乐观锁:

  • 很乐观,认为什么时候都不会出问题,所以不会上锁!更新数据的时候去判断一下,在此期问是否有人修改过这个数据,
  • 获取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> DECRBY money 20
QUEUED
127.0.0.1:6379> INCRBY out 20
QUEUED
127.0.0.1:6379> exec
1) (integer) 80
2) (integer) 20

测试多线程修改值,使用watch可以当作redis的乐观锁操作!

127.0.0.1:6379> watch money
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> DECRBY money 10
QUEUED
127.0.0.1:6379> INCRBY out 10
QUEUED
127.0.0.1:6379> exec
(nil)
127.0.0.1:6379> 

如果修改失败,获取最新的值就行

Jedis

我们要使用Java来操作Redis

什么是Jedis是Redis官方推荐的java连接开发工具!使用ava操作Redis中间件!如果你要使用 java操作redis,那么一定要对jedis十分熟悉

测试

1.导入对应依赖

<!--导入jedis包-->
    <dependencies>
        <!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>3.3.0</version>
        </dependency>
<!--fastjson-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.72</version>
        </dependency>
    </dependencies>
©️2020 CSDN 皮肤主题: 游动-白 设计师:上身试试 返回首页