Redis学习

Redis学习

概述

Redis默认有16个数据库,用的是第0个

可以使用select进行数据库的切换 ;例如切换到3号数据库 select 3

dbsize :数据库的大小

keys * ,表示查看所有的key

flushall 清空全部

flushdb 清空当前数据库

官方说写数据可达到十一万每秒。读数据可以达到每秒十万

reids 是单线程

Redis是很快的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FO27zuqg-1630892826205)(C:\Users\叶佩林\AppData\Local\Temp\1630633245019.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gCuiyUQu-1630892826206)(C:\Users\叶佩林\AppData\Local\Temp\1630633541504.png)]

Redis-Key

五大基本数据类型

string类型
#redis 连接:
redis-cli -p 6379

#判断键值对是否存在  
exists key

#设置key的有效时间
 expire key seconds #是以秒为单位的
 #查看剩余时间
 ttl (所要查询的key名)
 # 例如这次的key名为 name
 ttl name
 
 #查看所有的key
 keys *
 
# 移除当前的key到另一个数据库
move key 1   #key这里是键名, 1是目标数据库 

# type 用这个查看key的类型
type name
# append key value  append命令是在这个key后面追加内容
127.0.0.1:6379> get name
"12"
127.0.0.1:6379> append name nihoa
(integer) 7
127.0.0.1:6379> get name
"12nihoa"
# 再次追加
127.0.0.1:6379> append name yeshen,ypl
(integer) 17
127.0.0.1:6379> get name
"12nihoayeshen,ypl"
# 使用append 后面的key不存在时,就相当于新创建一个key
127.0.0.1:6379> append sub llal
(integer) 4
127.0.0.1:6379> keys *
1) "sub"
2) "name"

# strlen 获取字符串长度
127.0.0.1:6379> strlen name
(integer) 17
# incr 值+1
127.0.0.1:6379> set views 0
OK
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"
#decr 自减1
# incrby设置步长
127.0.0.1:6379> decr views
(integer) 1
127.0.0.1:6379> incrby views 22
(integer) 23
# decrby 步长减少
127.0.0.1:6379> decrby views 15
(integer) 8
# getrange截取字符串
# getrange key start end
127.0.0.1:6379> strlen name
(integer) 17
127.0.0.1:6379> getrange name 1 3
"2ni"
# getrange查看所有的字符串  start 0   end  -1
127.0.0.1:6379> getrange name  0 -1
"12nihoayeshen,ypl"
# 字符串替换
127.0.0.1:6379> set id 132165
OK
127.0.0.1:6379> setrange id 2 ll
(integer) 6
127.0.0.1:6379> get id
"13ll65"

#####
#setex (set with expire)   #设置过期时间
#setnx (set if not exist)  #不存在设置

################################
# mset批量设置值

127.0.0.1:6379> mset k1 1 k2 2 k3 3
OK
127.0.0.1:6379> keys *
1) "k2"
2) "id"
3) "k1"
4) "views"
5) "name"
6) "k3"
7) "sub"

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

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

127.0.0.1:6379> mset user:1:name  zhagnsan user:1:age 2
OK
127.0.0.1:6379>
127.0.0.1:6379> mget user:1:name user:1:age
1) "zhagnsan"
2) "2"
################################

################################
# getset
127.0.0.1:6379> getset two isok
(nil)
127.0.0.1:6379> get two
"isok"
127.0.0.1:6379> getset two isNotok
"isok"
127.0.0.1:6379> get two
"isNotok"
################################
List类型
##所有的list命令都是以l开头的
# 在key为list中添加值
#获取所有的值还是lrange key start end 
127.0.0.1:6379> lpush list q
(integer) 1
127.0.0.1:6379> lpush list w
(integer) 2
127.0.0.1:6379> lpush ;iste
(error) ERR wrong number of arguments for 'lpush' command
127.0.0.1:6379> lpush list e
(integer) 3
127.0.0.1:6379> lrange list 0 -1
1) "e"
2) "w"
3) "q"
###############################
127.0.0.1:6379>  lrange list 0 1
1) "e"
2) "w"
###############################

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bZ5TRtHR-1630892826209)(C:\Users\叶佩林\AppData\Local\Temp\1630639716632.png)]

# 那么从这里就能看出lpush就是从左边进去,rpush就是从右边进去,
# 那么同理从左边出来就是lpop.从右边出来就是rpop

127.0.0.1:6379> lindex list 0
"w"
127.0.0.1:6379> lindex list 1
"q"
# 上面就是像数组一样去根据下标来获取他的值

#####################################
# 获取list列表的长度
127.0.0.1:6379> lindex list 0
(nil)
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 three
(integer) 3
127.0.0.1:6379> llen list
(integer) 3
#####################################
# 移除指定的值,在这里我先添加了一个one ,现在里面有两个one ,然后我写了移除语句,移除了值为one,数量为1
127.0.0.1:6379> lpush list one
(integer) 4
127.0.0.1:6379> lrange list 0 -1
1) "one"
2) "three"
3) "two"
4) "one"
127.0.0.1:6379> lrem list 1 one
(integer) 1
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "two"
3) "one"
##################################
# ltrim 进行截取获得其中的内容  ltrim key start end
127.0.0.1:6379> lrange mylist 0 -1
1) "hello2"
2) "hello"
3) "hello1"
4) "hello3"
127.0.0.1:6379> ltrim mylist 1 2
OK
127.0.0.1:6379> lrange mylist 0 -1
1) "hello"
2) "hello1"

###################################
# 把一个list的最后一个元素添加到另一个的list中
#  rpoplpush source destination  source:原来的list  destination:要添加到的地方
127.0.0.1:6379> rpush mylist hello
(integer) 1
127.0.0.1:6379> rpush mylist hello1
(integer) 2
127.0.0.1:6379> rpush mylist hello2
(integer) 3
127.0.0.1:6379> rpoplpush mylist myotherlist
"hello2"
127.0.0.1:6379> keys *
1) "mylist"
2) "myotherlist"
127.0.0.1:6379> lrange myotherlist 0 -1
1) "hello2"

####################################
# 
127.0.0.1:6379> lpush list value  #list中添加值为value
(integer) 1
127.0.0.1:6379> lset list 0 item  #将0这个位置的value替换为item
OK
127.0.0.1:6379> lrange list 0 0   #查看list的值,已经改变 
1) "item"
####################################

######################################
#  linsert key BEFORE|AFTER pivot value
127.0.0.1:6379> rpush list lisi
(integer) 2
127.0.0.1:6379> linsert list before lisi lala
(integer) 3
127.0.0.1:6379> lrange lsit 0 -1
(empty list or set)
127.0.0.1:6379> lrange list 0 -1
1) "zhagnsan"
2) "lala"
3) "lisi

127.0.0.1:6379> linsert list after lisi wangwu
(integer) 4
127.0.0.1:6379> lrange list 0 -1
1) "zhagnsan"
2) "lala"
3) "lisi"
4) "wangwu"
######################################

小结

​ 左进右取可以当做队列来用

​ 左进左取当做栈来用

set类型
##########################################
# set 集合添加元素是 sadd key member [member ...]
# set 查看元素是smembers key
127.0.0.1:6379> sadd myset helloworld
(integer) 1
127.0.0.1:6379> sadd mysrt liuliu
(integer) 1
127.0.0.1:6379> smembers myset
1) "helloworld"
127.0.0.1:6379>

################################################
# sismember key member  检测集合中是否有这个值
127.0.0.1:6379> sadd myset world
(integer) 1
127.0.0.1:6379> sismember myset hello
(integer) 1
127.0.0.1:6379> sismember myset ok
(integer) 0
################################################


#################################################
# scard key  获取set类型的集合的元素个数
127.0.0.1:6379> scard myset
(integer) 3

# srem key member [member ...]  移除set类型的集合的特定值
127.0.0.1:6379> srem myset hello
(integer) 1
127.0.0.1:6379> scard myset
(integer) 2

# set是无序可重复集合
# srandmember key  
127.0.0.1:6379> srandmember myset 1
1) "world"
127.0.0.1:6379> srandmember myset 1
1) "helloworld"
127.0.0.1:6379> srandmember myset 1
1) "helloworld"
127.0.0.1:6379> srandmember myset 1
1) "helloworld"
127.0.0.1:6379> srandmember myset 1
1) "world"
127.0.0.1:6379> srandmember myset 1
1) "world"
127.0.0.1:6379> srandmember myset 1
1) "world"
#################################################
# smembers key 随机移除元素


#########################################################
# 将一个指定的值移动到另外一个集合中

# 语法:smove source destination member
127.0.0.1:6379> sadd myset hello
(integer) 1
127.0.0.1:6379> sadd myset hello2
(integer) 1
127.0.0.1:6379> sadd myset hello3
(integer) 1
127.0.0.1:6379> sadd myset ypl
(integer) 1
127.0.0.1:6379> sadd myset2 set
(integer) 1
127.0.0.1:6379> smove myset myset ypl
(integer) 1
127.0.0.1:6379> smembers myset2
1) "set"


#####################################
# 比较两个集合的差集
# 语法  sdiff key [key ...]
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 key2 b
(integer) 1
127.0.0.1:6379> sadd key2 c
(integer) 1
127.0.0.1:6379> sdiff key1 key2
1) "a"

###########################################
# 比较两个集合的交集
# 语法 sinter key [key ...]
127.0.0.1:6379> sinter key1 key2
1) "b"
2) "c"
#########################################
# 两个集合的并集
# 语法 sunion key [key ...]
127.0.0.1:6379> sunion key1 key2
1) "b"
2) "c"
3) "a"

交集:共同好友,共同关注
hash类型
#####################################################
将hash想成一个Map集合,key-map键值对
##########################################################
# 存值 :hset key field value
# 取值 :hget key field value
127.0.0.1:6379> hset myhash field1 ypl
(integer) 1
127.0.0.1:6379> hget myhash field1
"ypl"

#####################################
# 批量存取hash值
# 语法: 存:hmset key field value [field value ...]
# 语法: 取: hmget key field [field ...]
127.0.0.1:6379> hmset myhash qq aa qqw aaa
OK
127.0.0.1:6379> hmget myhash qq qqw
1) "aa"
2) "aaa"
##############################################
# 获得所有hash键值对
# 语法 hgetall key
127.0.0.1:6379> hgetall myhash
1) "field1"
2) "ypl"
3) "qq"
4) "aa"
5) "qqw"
6) "aaa"

##################################
# 得到hash集合的长度
# 语法 :hlen key
127.0.0.1:6379> hlen myhash
(integer) 3

#############################################
# 只获得所有对应的field
# 语法: hkeys key
127.0.0.1:6379> hkeys myhash
1) "field1"
2) "qq"
3) "qqw"
# 只获得所有对应的value
# 语法:hvals key
127.0.0.1:6379> hvals myhash
1) "ypl"
2) "aa"
3) "aaa"

####################
# 设置自增自减
# incr decr

# 设置自增
127.0.0.1:6379> hset myhash filed3 5
(integer) 1
127.0.0.1:6379> hincrby myhash fileds 1
(integer) 1
127.0.0.1:6379> hvals myhash
1) "ypl"
2) "aa"
3) "aaa"
4) "5"
5) "1"
127.0.0.1:6379> hincrby myhash filed3 2
(integer) 7

#设置自减
127.0.0.1:6379> hincrby myhash filed3 -2
(integer) 5

##########################################
# 对是否存在进行一个判断
127.0.0.1:6379> hsetnx myhash ff 4
(integer) 1
127.0.0.1:6379> hsetnx myhash ff 9
(integer) 0

###########################
hash的应用:hash变更数据,user name age
hash更适合对象的存储
string适合字符串的存储
Zset

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

######################################
127.0.0.1:6379> zadd myset 1 one# 添加一个值
(integer) 1
127.0.0.1:6379> zadd myset 2 two
(integer) 1
127.0.0.1:6379> zadd myset 3 three
(integer) 1
127.0.0.1:6379> zadd myset 4 four 5 five# 添加多个值
(integer) 2

#######################################
# 排序:
# 语法: zrangebyscore key min max [WITHSCORES] [LIMIT offset cou  	
127.0.0.1:6379> zadd salary 2500 xiaohong
(integer) 1
127.0.0.1:6379> zadd salary 3000 hagnsan
(integer) 1
127.0.0.1:6379> zadd salary 4200 lisi
(integer) 1
127.0.0.1:6379> zrangebyscore salary -inf +inf
1) "xiaohong"
2) "hagnsan"
3) "lisi"

#################################################
# 从小到大排序并显示内容
# 语法 :zrangebyscore key min max withscores
127.0.0.1:6379> zrangebyscore salary -inf +inf withscores
1) "xiaohong"
2) "2500"
3) "hagnsan"
4) "3000"
5) "lisi"
6) "4200"	
###########################################
# 移除元素
# zremv key
# 查看有序集合有几个元素
# zcard key
# 查看所有元素
# zrange 0 -1

#######################################
# 逆序查看集合元素
# 语法 zrevrange key start end
127.0.0.1:6379>  zrevrange salary 0 -1
1) "hagnsan"
2) "xiaohong"
#################################################
# 获取指定区间的成员变量
# 语法 : zcount key min max
127.0.0.1:6379> zcount myset 1 3
(integer) 3

如果遇到自己的不知道的,可以查查官方文档

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

普通消息:1,重要消息

三种特殊数据类型

geospatial
## 添加位置
# 语法:  geoadd key longitude latitude member [longitude latitude member ...]
127.0.0.1:6379>geoadd china:city 116.40 39.90 beijing
(integer) 1
127.0.0.1:6379> geoadd china:city 121.47 31.231
(error) ERR wrong number of arguments for 'geoadd' command
127.0.0.1:6379> geoadd china:city 121.47 31.231 shanghai
(integer) 1
#两极无法添加
# 参数: key 纬度经度 名称

#geopos 获取地理位置
127.0.0.1:6379> geopos china:city beijing
1) 1) "116.39999896287918"
   2) "39.900000091670925"
#geodist 两个位置的距离
# 语法:
127.0.0.1:6379> geodist china:city beijing shanghai
"1067277.0208"

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-E85Yy9n0-1630892826213)(C:\Users\叶佩林\AppData\Local\Temp\1630758378213.png)]

#  根据指定位置,以及半径获得包含的城市,只能在所在集合中
# 语法:georadius key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST]

# 查看地图的所有元素
127.0.0.1:6379> zrange china:city 0 -1
1) "shanghai"
2) "beijing"
####################################
# 移除地图的元素
127.0.0.1:6379> zrem china:city beijing
(integer) 1
127.0.0.1:6379> zrange china:city 0 -1
1) "shanghai"
Hyperloglog

什么是基数

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

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

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

Redis Hyperloglog 基数统计的算法

优点:占用的内存是固定的,2^64不同的元素的技术

# 添加元素
# 语法 pfadd key element [element ...]
127.0.0.1:6379> pfadd mykey 1 2 3 4 5 6 9 55 44 33
(integer) 1
# 统计元素个数
# 语法 pfcount key
127.0.0.1:6379> pfcount mykey
(integer) 10
# 合并两个集合
# 语法 pfmerge destkey sourcekey [sourcekey ...]
 # 重复的不算
  
  
  #####
  如果允许容错,那么一定可以使用Hyperloglog
  如果不允许容错,就是用set或者自己的数据类型即可
Bitmaps

位存储

统计用户信息,活跃,不活跃!登录,未登录

bItmaps 位图,数据结构!都是操作二进制位来进行纪录,就只有和两个状态!

测试

可以使用bitmap来统计打卡天数

####################################################
# 设置值
 #语法 :setbit key offset value
 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> getbit sign 3
(integer) 0
127.0.0.1:6379> getbit sign 0
(integer) 1

#######################################
# 统计打卡天数
# 语法:bitcount sign
127.0.0.1:6379> bitcount sign
(integer) 2 #两天打卡

事务

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

一次性,顺序性,排他性!执行一些列的命令

---------------队列队列setsetset执行--------------

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

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

Redis单条命令是保存原子性的,但是事务不保证原子性

Redis的事务:

  • 开启事务(multi)
  • 命令入队( )
  • 执行事务

正常执行事务

####
# 入队的时候并不是一次执行完命令,而是exec后执行的命令
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set k1 v1
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> get k1
QUEUED
127.0.0.1:6379> set k3 v3
QUEUED
127.0.0.1:6379> exec
1) OK
2) OK
3) "v1"
4) OK

# 每次事务执行完就没了,再想执行事务就要重新开启
 
 
################################################### 放弃执行事务
127.0.0.1:6379> multi
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> set k4 v4
QUEUED
127.0.0.1:6379> discard# 取消执行事务
OK
127.0.0.1:6379> get k4# 事务队列中命令都不会被执行
(nil)

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

########################
# 
127.0.0.1:6379> set k1 v1
QUEUED
127.0.0.1:6379> set k2 vw
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
(nil)

运行时异常,如果事务队列中存在语法性,那么执行命令的时候,其他命令是可以正常执行的,错误命令抛出异常

#######################################
127.0.0.1:6379> set k1 v1
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> incr k1
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> set k3 v3
QUEUED
127.0.0.1:6379> exec # 这就是运行时异常
1) (error) ERR value is not an integer or out of range# 虽然第一小命令报错的,但是其他依旧执行成功了
2) OK
3) OK
127.0.0.1:6379> get k2
"v2"
127.0.0.1:6379> get k3
"v3"

监控

悲观锁

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

乐观锁

  • 很乐观,认为什么时候都不会出问题,所以不会上锁,更新数据的时候去判断一下,在此期间是否有人修改过这个数据
  • 获取version
  • 更新的时候比较version

Redis测监视测试

##################################
#监视money
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

Jedis

使用java来操作Redis

什么是Jedis,它是Redis推荐的Java连接来发工具!使用Java操作Redis中间件

  1. 先引入依赖

    <dependencies>
            <dependency>
                <groupId>redis.clients</groupId>
                <artifactId>jedis</artifactId>
                <version>3.2.0</version>
            </dependency>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>1.2.62</version>
            </dependency>
        </dependencies>
    
  2. 编码测试:

    • 连接数据库

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kbNa9YVB-1630892826215)(C:\Users\叶佩林\AppData\Local\Temp\1630852461012.png)]

      连接成功

    • 操作命令

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xxdpSYhA-1630892826216)(C:\Users\叶佩林\AppData\Local\Temp\1630852590393.png)]

    • 断开连接

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ftwGygBf-1630892826218)(C:\Users\叶佩林\AppData\Local\Temp\1630891550680.png)]

事务测试

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EnLSGasE-1630892826220)(C:\Users\叶佩林\AppData\Local\Temp\1630892448385.png)]

springboot整合

springboot操作数据:spring-data jpa jdbc mongodb redis!

springdata也是个springboot齐名的项目!

整合测试

Redis学习

概述

Redis默认有16个数据库,用的是第0个

可以使用select进行数据库的切换 ;例如切换到3号数据库 select 3

dbsize :数据库的大小

keys * ,表示查看所有的key

flushall 清空全部

flushdb 清空当前数据库

官方说写数据可达到十一万每秒。读数据可以达到每秒十万

reids 是单线程

Redis是很快的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EZ7PNVYP-1630892827482)(C:\Users\叶佩林\AppData\Local\Temp\1630633245019.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UDCdmAEy-1630892827483)(C:\Users\叶佩林\AppData\Local\Temp\1630633541504.png)]

Redis-Key

五大基本数据类型

string类型
#redis 连接:
redis-cli -p 6379

#判断键值对是否存在  
exists key

#设置key的有效时间
 expire key seconds #是以秒为单位的
 #查看剩余时间
 ttl (所要查询的key名)
 # 例如这次的key名为 name
 ttl name
 
 #查看所有的key
 keys *
 
# 移除当前的key到另一个数据库
move key 1   #key这里是键名, 1是目标数据库 

# type 用这个查看key的类型
type name
# append key value  append命令是在这个key后面追加内容
127.0.0.1:6379> get name
"12"
127.0.0.1:6379> append name nihoa
(integer) 7
127.0.0.1:6379> get name
"12nihoa"
# 再次追加
127.0.0.1:6379> append name yeshen,ypl
(integer) 17
127.0.0.1:6379> get name
"12nihoayeshen,ypl"
# 使用append 后面的key不存在时,就相当于新创建一个key
127.0.0.1:6379> append sub llal
(integer) 4
127.0.0.1:6379> keys *
1) "sub"
2) "name"

# strlen 获取字符串长度
127.0.0.1:6379> strlen name
(integer) 17
# incr 值+1
127.0.0.1:6379> set views 0
OK
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"
#decr 自减1
# incrby设置步长
127.0.0.1:6379> decr views
(integer) 1
127.0.0.1:6379> incrby views 22
(integer) 23
# decrby 步长减少
127.0.0.1:6379> decrby views 15
(integer) 8
# getrange截取字符串
# getrange key start end
127.0.0.1:6379> strlen name
(integer) 17
127.0.0.1:6379> getrange name 1 3
"2ni"
# getrange查看所有的字符串  start 0   end  -1
127.0.0.1:6379> getrange name  0 -1
"12nihoayeshen,ypl"
# 字符串替换
127.0.0.1:6379> set id 132165
OK
127.0.0.1:6379> setrange id 2 ll
(integer) 6
127.0.0.1:6379> get id
"13ll65"

#####
#setex (set with expire)   #设置过期时间
#setnx (set if not exist)  #不存在设置

################################
# mset批量设置值

127.0.0.1:6379> mset k1 1 k2 2 k3 3
OK
127.0.0.1:6379> keys *
1) "k2"
2) "id"
3) "k1"
4) "views"
5) "name"
6) "k3"
7) "sub"

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

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

127.0.0.1:6379> mset user:1:name  zhagnsan user:1:age 2
OK
127.0.0.1:6379>
127.0.0.1:6379> mget user:1:name user:1:age
1) "zhagnsan"
2) "2"
################################

################################
# getset
127.0.0.1:6379> getset two isok
(nil)
127.0.0.1:6379> get two
"isok"
127.0.0.1:6379> getset two isNotok
"isok"
127.0.0.1:6379> get two
"isNotok"
################################
List类型
##所有的list命令都是以l开头的
# 在key为list中添加值
#获取所有的值还是lrange key start end 
127.0.0.1:6379> lpush list q
(integer) 1
127.0.0.1:6379> lpush list w
(integer) 2
127.0.0.1:6379> lpush ;iste
(error) ERR wrong number of arguments for 'lpush' command
127.0.0.1:6379> lpush list e
(integer) 3
127.0.0.1:6379> lrange list 0 -1
1) "e"
2) "w"
3) "q"
###############################
127.0.0.1:6379>  lrange list 0 1
1) "e"
2) "w"
###############################

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TlYCIlvL-1630892827484)(C:\Users\叶佩林\AppData\Local\Temp\1630639716632.png)]

# 那么从这里就能看出lpush就是从左边进去,rpush就是从右边进去,
# 那么同理从左边出来就是lpop.从右边出来就是rpop

127.0.0.1:6379> lindex list 0
"w"
127.0.0.1:6379> lindex list 1
"q"
# 上面就是像数组一样去根据下标来获取他的值

#####################################
# 获取list列表的长度
127.0.0.1:6379> lindex list 0
(nil)
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 three
(integer) 3
127.0.0.1:6379> llen list
(integer) 3
#####################################
# 移除指定的值,在这里我先添加了一个one ,现在里面有两个one ,然后我写了移除语句,移除了值为one,数量为1
127.0.0.1:6379> lpush list one
(integer) 4
127.0.0.1:6379> lrange list 0 -1
1) "one"
2) "three"
3) "two"
4) "one"
127.0.0.1:6379> lrem list 1 one
(integer) 1
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "two"
3) "one"
##################################
# ltrim 进行截取获得其中的内容  ltrim key start end
127.0.0.1:6379> lrange mylist 0 -1
1) "hello2"
2) "hello"
3) "hello1"
4) "hello3"
127.0.0.1:6379> ltrim mylist 1 2
OK
127.0.0.1:6379> lrange mylist 0 -1
1) "hello"
2) "hello1"

###################################
# 把一个list的最后一个元素添加到另一个的list中
#  rpoplpush source destination  source:原来的list  destination:要添加到的地方
127.0.0.1:6379> rpush mylist hello
(integer) 1
127.0.0.1:6379> rpush mylist hello1
(integer) 2
127.0.0.1:6379> rpush mylist hello2
(integer) 3
127.0.0.1:6379> rpoplpush mylist myotherlist
"hello2"
127.0.0.1:6379> keys *
1) "mylist"
2) "myotherlist"
127.0.0.1:6379> lrange myotherlist 0 -1
1) "hello2"

####################################
# 
127.0.0.1:6379> lpush list value  #list中添加值为value
(integer) 1
127.0.0.1:6379> lset list 0 item  #将0这个位置的value替换为item
OK
127.0.0.1:6379> lrange list 0 0   #查看list的值,已经改变 
1) "item"
####################################

######################################
#  linsert key BEFORE|AFTER pivot value
127.0.0.1:6379> rpush list lisi
(integer) 2
127.0.0.1:6379> linsert list before lisi lala
(integer) 3
127.0.0.1:6379> lrange lsit 0 -1
(empty list or set)
127.0.0.1:6379> lrange list 0 -1
1) "zhagnsan"
2) "lala"
3) "lisi

127.0.0.1:6379> linsert list after lisi wangwu
(integer) 4
127.0.0.1:6379> lrange list 0 -1
1) "zhagnsan"
2) "lala"
3) "lisi"
4) "wangwu"
######################################

小结

​ 左进右取可以当做队列来用

​ 左进左取当做栈来用

set类型
##########################################
# set 集合添加元素是 sadd key member [member ...]
# set 查看元素是smembers key
127.0.0.1:6379> sadd myset helloworld
(integer) 1
127.0.0.1:6379> sadd mysrt liuliu
(integer) 1
127.0.0.1:6379> smembers myset
1) "helloworld"
127.0.0.1:6379>

################################################
# sismember key member  检测集合中是否有这个值
127.0.0.1:6379> sadd myset world
(integer) 1
127.0.0.1:6379> sismember myset hello
(integer) 1
127.0.0.1:6379> sismember myset ok
(integer) 0
################################################


#################################################
# scard key  获取set类型的集合的元素个数
127.0.0.1:6379> scard myset
(integer) 3

# srem key member [member ...]  移除set类型的集合的特定值
127.0.0.1:6379> srem myset hello
(integer) 1
127.0.0.1:6379> scard myset
(integer) 2

# set是无序可重复集合
# srandmember key  
127.0.0.1:6379> srandmember myset 1
1) "world"
127.0.0.1:6379> srandmember myset 1
1) "helloworld"
127.0.0.1:6379> srandmember myset 1
1) "helloworld"
127.0.0.1:6379> srandmember myset 1
1) "helloworld"
127.0.0.1:6379> srandmember myset 1
1) "world"
127.0.0.1:6379> srandmember myset 1
1) "world"
127.0.0.1:6379> srandmember myset 1
1) "world"
#################################################
# smembers key 随机移除元素


#########################################################
# 将一个指定的值移动到另外一个集合中

# 语法:smove source destination member
127.0.0.1:6379> sadd myset hello
(integer) 1
127.0.0.1:6379> sadd myset hello2
(integer) 1
127.0.0.1:6379> sadd myset hello3
(integer) 1
127.0.0.1:6379> sadd myset ypl
(integer) 1
127.0.0.1:6379> sadd myset2 set
(integer) 1
127.0.0.1:6379> smove myset myset ypl
(integer) 1
127.0.0.1:6379> smembers myset2
1) "set"


#####################################
# 比较两个集合的差集
# 语法  sdiff key [key ...]
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 key2 b
(integer) 1
127.0.0.1:6379> sadd key2 c
(integer) 1
127.0.0.1:6379> sdiff key1 key2
1) "a"

###########################################
# 比较两个集合的交集
# 语法 sinter key [key ...]
127.0.0.1:6379> sinter key1 key2
1) "b"
2) "c"
#########################################
# 两个集合的并集
# 语法 sunion key [key ...]
127.0.0.1:6379> sunion key1 key2
1) "b"
2) "c"
3) "a"

交集:共同好友,共同关注
hash类型
#####################################################
将hash想成一个Map集合,key-map键值对
##########################################################
# 存值 :hset key field value
# 取值 :hget key field value
127.0.0.1:6379> hset myhash field1 ypl
(integer) 1
127.0.0.1:6379> hget myhash field1
"ypl"

#####################################
# 批量存取hash值
# 语法: 存:hmset key field value [field value ...]
# 语法: 取: hmget key field [field ...]
127.0.0.1:6379> hmset myhash qq aa qqw aaa
OK
127.0.0.1:6379> hmget myhash qq qqw
1) "aa"
2) "aaa"
##############################################
# 获得所有hash键值对
# 语法 hgetall key
127.0.0.1:6379> hgetall myhash
1) "field1"
2) "ypl"
3) "qq"
4) "aa"
5) "qqw"
6) "aaa"

##################################
# 得到hash集合的长度
# 语法 :hlen key
127.0.0.1:6379> hlen myhash
(integer) 3

#############################################
# 只获得所有对应的field
# 语法: hkeys key
127.0.0.1:6379> hkeys myhash
1) "field1"
2) "qq"
3) "qqw"
# 只获得所有对应的value
# 语法:hvals key
127.0.0.1:6379> hvals myhash
1) "ypl"
2) "aa"
3) "aaa"

####################
# 设置自增自减
# incr decr

# 设置自增
127.0.0.1:6379> hset myhash filed3 5
(integer) 1
127.0.0.1:6379> hincrby myhash fileds 1
(integer) 1
127.0.0.1:6379> hvals myhash
1) "ypl"
2) "aa"
3) "aaa"
4) "5"
5) "1"
127.0.0.1:6379> hincrby myhash filed3 2
(integer) 7

#设置自减
127.0.0.1:6379> hincrby myhash filed3 -2
(integer) 5

##########################################
# 对是否存在进行一个判断
127.0.0.1:6379> hsetnx myhash ff 4
(integer) 1
127.0.0.1:6379> hsetnx myhash ff 9
(integer) 0

###########################
hash的应用:hash变更数据,user name age
hash更适合对象的存储
string适合字符串的存储
Zset

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

######################################
127.0.0.1:6379> zadd myset 1 one# 添加一个值
(integer) 1
127.0.0.1:6379> zadd myset 2 two
(integer) 1
127.0.0.1:6379> zadd myset 3 three
(integer) 1
127.0.0.1:6379> zadd myset 4 four 5 five# 添加多个值
(integer) 2

#######################################
# 排序:
# 语法: zrangebyscore key min max [WITHSCORES] [LIMIT offset cou  	
127.0.0.1:6379> zadd salary 2500 xiaohong
(integer) 1
127.0.0.1:6379> zadd salary 3000 hagnsan
(integer) 1
127.0.0.1:6379> zadd salary 4200 lisi
(integer) 1
127.0.0.1:6379> zrangebyscore salary -inf +inf
1) "xiaohong"
2) "hagnsan"
3) "lisi"

#################################################
# 从小到大排序并显示内容
# 语法 :zrangebyscore key min max withscores
127.0.0.1:6379> zrangebyscore salary -inf +inf withscores
1) "xiaohong"
2) "2500"
3) "hagnsan"
4) "3000"
5) "lisi"
6) "4200"	
###########################################
# 移除元素
# zremv key
# 查看有序集合有几个元素
# zcard key
# 查看所有元素
# zrange 0 -1

#######################################
# 逆序查看集合元素
# 语法 zrevrange key start end
127.0.0.1:6379>  zrevrange salary 0 -1
1) "hagnsan"
2) "xiaohong"
#################################################
# 获取指定区间的成员变量
# 语法 : zcount key min max
127.0.0.1:6379> zcount myset 1 3
(integer) 3

如果遇到自己的不知道的,可以查查官方文档

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

普通消息:1,重要消息

三种特殊数据类型

geospatial
## 添加位置
# 语法:  geoadd key longitude latitude member [longitude latitude member ...]
127.0.0.1:6379>geoadd china:city 116.40 39.90 beijing
(integer) 1
127.0.0.1:6379> geoadd china:city 121.47 31.231
(error) ERR wrong number of arguments for 'geoadd' command
127.0.0.1:6379> geoadd china:city 121.47 31.231 shanghai
(integer) 1
#两极无法添加
# 参数: key 纬度经度 名称

#geopos 获取地理位置
127.0.0.1:6379> geopos china:city beijing
1) 1) "116.39999896287918"
   2) "39.900000091670925"
#geodist 两个位置的距离
# 语法:
127.0.0.1:6379> geodist china:city beijing shanghai
"1067277.0208"

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aTdh0tDu-1630892827485)(C:\Users\叶佩林\AppData\Local\Temp\1630758378213.png)]

#  根据指定位置,以及半径获得包含的城市,只能在所在集合中
# 语法:georadius key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST]

# 查看地图的所有元素
127.0.0.1:6379> zrange china:city 0 -1
1) "shanghai"
2) "beijing"
####################################
# 移除地图的元素
127.0.0.1:6379> zrem china:city beijing
(integer) 1
127.0.0.1:6379> zrange china:city 0 -1
1) "shanghai"
Hyperloglog

什么是基数

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

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

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

Redis Hyperloglog 基数统计的算法

优点:占用的内存是固定的,2^64不同的元素的技术

# 添加元素
# 语法 pfadd key element [element ...]
127.0.0.1:6379> pfadd mykey 1 2 3 4 5 6 9 55 44 33
(integer) 1
# 统计元素个数
# 语法 pfcount key
127.0.0.1:6379> pfcount mykey
(integer) 10
# 合并两个集合
# 语法 pfmerge destkey sourcekey [sourcekey ...]
 # 重复的不算
  
  
  #####
  如果允许容错,那么一定可以使用Hyperloglog
  如果不允许容错,就是用set或者自己的数据类型即可
Bitmaps

位存储

统计用户信息,活跃,不活跃!登录,未登录

bItmaps 位图,数据结构!都是操作二进制位来进行纪录,就只有和两个状态!

测试

可以使用bitmap来统计打卡天数

####################################################
# 设置值
 #语法 :setbit key offset value
 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> getbit sign 3
(integer) 0
127.0.0.1:6379> getbit sign 0
(integer) 1

#######################################
# 统计打卡天数
# 语法:bitcount sign
127.0.0.1:6379> bitcount sign
(integer) 2 #两天打卡

事务

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

一次性,顺序性,排他性!执行一些列的命令

---------------队列队列setsetset执行--------------

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

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

Redis单条命令是保存原子性的,但是事务不保证原子性

Redis的事务:

  • 开启事务(multi)
  • 命令入队( )
  • 执行事务

正常执行事务

####
# 入队的时候并不是一次执行完命令,而是exec后执行的命令
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set k1 v1
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> get k1
QUEUED
127.0.0.1:6379> set k3 v3
QUEUED
127.0.0.1:6379> exec
1) OK
2) OK
3) "v1"
4) OK

# 每次事务执行完就没了,再想执行事务就要重新开启
 
 
################################################### 放弃执行事务
127.0.0.1:6379> multi
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> set k4 v4
QUEUED
127.0.0.1:6379> discard# 取消执行事务
OK
127.0.0.1:6379> get k4# 事务队列中命令都不会被执行
(nil)

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

########################
# 
127.0.0.1:6379> set k1 v1
QUEUED
127.0.0.1:6379> set k2 vw
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
(nil)

运行时异常,如果事务队列中存在语法性,那么执行命令的时候,其他命令是可以正常执行的,错误命令抛出异常

#######################################
127.0.0.1:6379> set k1 v1
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> incr k1
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> set k3 v3
QUEUED
127.0.0.1:6379> exec # 这就是运行时异常
1) (error) ERR value is not an integer or out of range# 虽然第一小命令报错的,但是其他依旧执行成功了
2) OK
3) OK
127.0.0.1:6379> get k2
"v2"
127.0.0.1:6379> get k3
"v3"

监控

悲观锁

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

乐观锁

  • 很乐观,认为什么时候都不会出问题,所以不会上锁,更新数据的时候去判断一下,在此期间是否有人修改过这个数据
  • 获取version
  • 更新的时候比较version

Redis测监视测试

##################################
#监视money
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

Jedis

使用java来操作Redis

什么是Jedis,它是Redis推荐的Java连接来发工具!使用Java操作Redis中间件

  1. 先引入依赖

    <dependencies>
            <dependency>
                <groupId>redis.clients</groupId>
                <artifactId>jedis</artifactId>
                <version>3.2.0</version>
            </dependency>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>1.2.62</version>
            </dependency>
        </dependencies>
    
  2. 编码测试:

    • 连接数据库

    • 操作命令

    • 断开连接

事务测试

springboot整合

springboot操作数据:spring-data jpa jdbc mongodb redis!

springdata也是个springboot齐名的项目!

整合测试

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值