Redis基础知识(一)

Redis知识

Redis基础

环境:Windows

简介

问题现象

  • 海量用户
  • 高并发

关系型数据库(罪魁祸首)

  • 性能瓶颈:磁盘IO性能低下
  • 扩展瓶颈:数据关系复杂,扩展性差,不便于大规模集群

解决思路

  • 降低磁盘IO次数,越低越好
  • 去除数据间的关系,越简单越好

Nosql(Not-Only-Sql)

泛指非关系型数据库,作为关系型数据库的补充

一般的数据还是要存到关系型数据库中(硬盘中),而nosql是将数据存入到内存中。

作用:应用与海量用户和海量数据前提下的数据处理问题

特征:

  • 可扩容,可伸缩
  • 大数据下高性能
  • 灵活的数据模型(应对多种类型数据)
  • 高可用

常见的Nosql数据库:

  • Redis
  • MongoDB
  • HBase

应用场景:

解决方案一(电商场景)

image-20210713132608790

概念:Redis(Remote Dictionary Server)高性能键值对(key -value)数据库

特征:

  • 数据间没有必然的关联关系
  • 内部采用单线程机制进行工作
  • 高性能
  • 多数据类型支持
    • String类型
    • 数组类型List
    • 集合类型Set
    • 散列类型 hash表
    • 有序集合类型 sortedSet
  • 持久化支持(和java中将对象序列化相似,将对象存到硬盘中),进行数据灾难**(断电无法工作**)恢复

应用:

  • 任务队列(秒杀,抢购等)
  • 时效性信息控制(手机验证码时效性)
  • 为热点数据加速查询
  • 即时信息查询(排行榜信息,车来了公交信息,在线人数)
  • 分布式数据共享
  • 消息队列
  • 分布式锁

基本操作

信息添加

  • 功能:设置key、value数据

  • 命令

    set key  value
    
  • 范例

    set name  zhang
    

信息查询

  • 功能:根据key查询对应的value,如果不存在,返回空(nil)

  • 命令

    get key
    
  • 范例

    get name
    

清屏

  • 命令

    ctrl L
    

帮助

  • 功能: 获取帮助, 可以使用Tab键来切换

    help 命令名称
    help @组名
    

image-20210713135006738

退出

  • 命令

    quit
    exit
    

数据类型

业务数据的特殊性

作为缓存使用

  1. 原始业务功能设计
    • 秒杀
    • 618活动
    • 排队购票
  2. 运行平台监控到突发的高频访问数据
    • 突发时事新闻
  3. 高频,复杂的统计数据
    • 在线人数(直播)

附加功能

系统功能优化或升级

  • 单服务器升级集群
  • Session管理
  • Token管理

常见数据类型

  • string String
  • hash HashMap
  • list LinkedList
  • set HashSet
  • sortedSet TreeSet

redis自身是一个Map,按照key-value的形式存储数据。

数据类型指的是存储的数据类型,value中的数据类型,而key中的类型永远是String。

image-20210713140204985

String类型

基本操作

//设置String
set key value
//设置多个String
mset key1 value1 key2 value2...
//设置生命周期
setex key seconds value 

//得到String
get key 
//得到多个String
mget key1 key2...

//删除String
del key

//获取String的长度
strlen  key


//向字符串的后面追加字符,如果有就补在后面,如果没有就新建
append key value

image-20210713141820575

小闹钟:发送和返回时间。

大闹钟:存储的时间。

使用单个set和单mset,最终所需时间如上图显示,在发送同等数据的情况下,使用mset更加的高效。

扩展操作

String作为数值操作

//增长指令,只有当value为数字时才能增长
incr key  
incrby key increment   比如: incrby num 10 增加10
 
 //操作小数
incrbyfloat key increment  比如 :incrbyfloat num 1.2

//减少指令,有当value为数字时才能减少
decr key  

//操作小数
decrby key increment

注意:increment可以为正数也可以为负数
  • String在redis中默认是字符串类型,当遇到incrdecr操作时,会转换成数值进行计算。(前提是存入的是数值类型的String)

  • redis所有的操作都是原子性的,采用单线程处理所有的业务,命令是一个一个执行,因此不想需要考虑并发带来的影响。

tips1:

  • redis用于控制数据库表主键id,为数据库表主键提供生成策略,保障数据库表的主键唯一性
  • 此方案适用于所有数据库,且支持数据库集群

业务场景:投票时间的限制

//设置数据的生命周期,单位 秒
setex key seconds value
//设置数据的生命周期,单位 毫秒
psetex key milliseconds value

tips2

  • redis 控制数据的生命周期,通过数据是否失效控制业务行为,适用于所有具有时效性限定控制的操作

注意事项

image-20210713144113836

key的设置约定

image-20210713144710848

tips3

  • redis运用于各种结构性和非结构型高热度数据访问加速
Hash类型

image-20210713145212428

基本操作

//插入(如果已存在同名的field,会被覆盖)
hset key field value
hmset key field1 value1 field2 value2...
//插入(如果已存在同名的field,不会被覆盖)
hsetnx key field value

//取出
hget key field
hgetall key

//获取多个数据
hmget key field1 field2


//删除
hdel key field1 field2...

//获取field数量
hlen key

//查看是否存在
hexists key field

扩展操作

//获取哈希表中所有的字段名或字段值 
hkeys key
hvals key

//设置指定字段的数值数据增加指定范围的值 
hincrby key field increment 
hdecrby key field increment

注意事项

  • hash类型下的value只能存储字符串,不允许存储其他数据类型,不存在嵌套现象。如果数据未获取到, 对应的值为(nil)
  • 每个 hash 可以存储 2^32 - 1 个键值
  • hash类型十分贴近对象的数据存储形式,并且可以灵活添加删除对象属性。但hash设计初衷不是为了存储大量对象而设计的,切记不可滥用更不可以将hash作为对象列表使用
  • hgetall 操作可以获取全部属性,如果内部field过多,遍历整体数据效率就很会低,有可能成为数据访问瓶颈

应用场景

电商网站购物车设计

image-20210715130900678

127.0.0.1:6379> hmset shop1 sp 10 sp2 1
OK
127.0.0.1:6379> hmset shop2 sp 1  sp 2
OK
127.0.0.1:6379> hgetall shop1
1) "sp"
2) "10"
3) "sp2"
4) "1"
127.0.0.1:6379> hgetall shop2
1) "sp"
2) "2"

image-20210715132115181

127.0.0.1:6379> hmset shop3 sp:name 101 sp:info {.....}
OK
127.0.0.1:6379> hgetall shop3
1) "sp:nums" //商品编号:数量
2) "101"    //数量
3) "sp:info"  //商品:信息
4) "{.....}"
List类型
  • 数据存储需求:存储多个数据,并对数据进入存储空间的顺序进行区分
  • 需要的存储结构:一个存储空间保存多个数据,且通过数据可以体现进入顺序
  • list类型:保存多个数据,底层使用双向链表存储结构实现
  • 元素有序,且可重

image-20210715133439471

image-20210715133622532

//添加修改数据,lpush为从左边添加,rpush为从右边添加
lpush key value1 value2 value3...
rpush key value1 value2 value3...

//查看数据, 从左边开始向右查看. 如果不知道list有多少个元素,end的值可以为-1,代表倒数第一个元素
//lpush先进的元素放在最后,rpush先进的元素放在最前面
lrange key start end
//得到长度
llen key
//取出对应索引的元素
lindex key index

//获取并移除元素(从list左边或者右边移除)
lpop key
rpop key

扩展操作

//规定时间内获取并移除数据,b=block,给定一个时间,如果在指定时间内放入了元素,就移除
//key1,key2 :若干个列表
//timeout:单位:s
blpop key1 key2... timeout
brpop key1 key2... timeout

业务场景

微信朋友圈点赞,按照点赞顺序显示点赞好友信息

操作具有先后的数据控制

//移除指定元素 count:移除的个数 value:移除的值。 移除多个相同元素时,从左边开始移除
lrem key count value
127.0.0.1:6379> rpush 01 a b c d e
(integer) 5
127.0.0.1:6379> lrange 01 0 -1
1) "a"
2) "b"
3) "c"
4) "d"
5) "e"
127.0.0.1:6379> lrem 01 1 a
(integer) 1
127.0.0.1:6379> lrange 01 0 -1
1) "b"
2) "c"
3) "d"
4) "e"
127.0.0.1:6379>

注意事项

  • list中保存的数据都是string类型的,数据总容量是有限的,最多2^32 - 1 个元素 (4294967295)。
  • list具有索引的概念,但是操作数据时通常以队列的形式进行入队出队(rpush, lpop)操作,或以的形式进行入栈出栈(lpush, lpop)操作
  • 获取全部数据操作结束索引设置为-1 (倒数第一个元素)
  • list可以对数据进行分页操作,通常第一页的信息来自于list,第2页及更多的信息通过数据库的形式加载

日志的存储

使用redis中List类型来完成。

队列的形式或者栈的形式完成顺序的存储。

Set类型
  • 新的存储要求:存储大量的数据,在查询方面提供更高的效率
  • 需要的存储结构:能够保存大量的数据,高效的内部存储机制,便于查询
  • set类型:与hash存储结构完成相同,不同之处在于key用来存值,而value不存值(nil),并且值是不允许重复的。

image-20210715141512836

image-20210715141528531

基本操作

//添加元素
sadd key member1 member2...

//查看元素
smembers key

//移除元素
srem key member

//查看元素个数
scard key

//查看某个元素是否存在
sismember key member

扩展操作

//从set中任意选出count个元素.原set集合数量不变
srandmember key count

//从set中任意选出count个元素并移除,原set集合发生改变
spop key count

业务场景

image-20210715142243834

127.0.0.1:6379> srandmember users 3
1) "sh"
2) "js"
127.0.0.1:6379> srandmember users 1
1) "js"
127.0.0.1:6379> spop users
"js"
127.0.0.1:6379> srandmember users 2
1) "sh"

应用于随机推荐类信息检索,例如:热点歌单推荐。

image-20210715143054724

//求两个集合的交集、并集、差集
//交集
sinter key1 key2...
//并集
sunion key1 key2...
//差集
sdiff key1 key2...

//求两个set的交集、并集、差集,并放入另一个set中
sinterstore destination key1 key2...
sunionstore destination key1 key2...
sdiffstore destination key1 key2...

//求指定元素从原集合放入目标集合中
smove source destination key

应用于同类信息的关联搜索,二度关联搜索,深度关联搜索

一度搜索:显示共同好友、关注,

二度搜索:用户A发出,获取到好友用户B的游戏充值列表

统计网站的访问量(PV),独立访客(uv),独立IP(ip)

建立string类型,利用incrby统计日访问量

建立Set类型,记录不同cookie数量

建立Set类型,统计不同IP数量

应用于同类型数据的快速去重

注意事项

  • set类型不允许重复数据,已经存在的数据,不会允许后续相同数据加入进来。
  • set与hash的存储结构相同,但是无法启用hash中存储值的空间。
Sortd_Set类型
  • 不重但有序(score)
  • 新的存储需求:数据排序有利于数据的有效展示,需要提供一种可以根据自身特征进行排序的方式
  • 需要的存储结构:新的存储模型,可以保存可排序的数据
  • sorted_set类型:在set的存储结构基础上添加可排序字段

image-20210716142345635

score关键字是用来排序,并不是数据

基本操作

//插入元素, 需要指定score(用于排序)
zadd key score1 member1 score2 member2

//查看元素(score升序), 当末尾添加withscore时,会将元素的score一起打印出来
zrange key start end (withscore)
//查看元素(score降序), 当末尾添加withscore时,会将元素的score一起打印出来
zrevrange key start end (withscore)

//移除元素
zrem key member1 member2...
127.0.0.1:6379> zadd scores 94 zs
(integer) 1
127.0.0.1:6379> zadd scores 80 ls
(integer) 1
127.0.0.1:6379> zadd scores 79 ww
(integer) 1
127.0.0.1:6379> zadd scores 22 zl
(integer) 1
127.0.0.1:6379> zrange scores 0 -1  withscores
1) "zl"
2) "22"
3) "ww"
4) "79"
5) "ls"
6) "80"
7) "zs"
8) "94"
127.0.0.1:6379> zrevrange scores 0 -1 withscores
1) "zs"
2) "94"
3) "ls"
4) "80"
5) "ww"
6) "79"
7) "zl"
8) "22"
127.0.0.1:6379> zrem socres zl
(integer) 0
127.0.0.1:6379> zrevrange scores 0 -1 withscores
1) "zs"
2) "94"
3) "ls"
4) "80"
5) "ww"
6) "79"
7) "zl"
8) "22"
//按条件获取数据, 其中offset为索引开始位置,count为获取的数目
zrangebyscore key min max [withscore] [limit offset count]
zrevrangebyscore key max min [withscore] [limit offset count]

//按条件移除元素
zremrangebyrank key start stop
zremrangebysocre key min max

   注意:min于max用于限定搜索查询的条件
    	start与stop用于限定查询范围,作用于索引,表示开始和结束索引
    	offset于count用于限定查询范围,作用于查询结果,表示开始位置和数		 据总量
    
    
//按照从大到小的顺序移除count个值
zpopmax key [count]
//按照从小到大的顺序移除count个值
zpopmin key [count]

//获得元素个数
zcard key

//获得元素在范围内的个数
zcount key min max

//求交集、并集放入destination中, 其中numkeys为交集或并集集合的数目,key1,key2代表要集合,它们会将集合中相同元素的值相加。
zinterstore destination numkeys key1 key2...
zunionstore destination numkeys key1 key2...
127.0.0.1:6379> zcard scores
(integer) 2
127.0.0.1:6379> zcount scores 20 100
(integer) 2
127.0.0.1:6379> zadd s1 100 a 50 b 30c
(error) ERR syntax error
127.0.0.1:6379> zadd s1 100 a 20 b 30 c
(integer) 3
127.0.0.1:6379> zadd s2 90 a 80 b 10 c
(integer) 3
127.0.0.1:6379> zadd s3 70 a 40 b  20 c
(integer) 3
127.0.0.1:6379> zinterstore ss 3 s1 s2 s3
(integer) 3
127.0.0.1:6379> zrange ss 0 -1 withscores
1) "c"
2) "60"
3) "b"
4) "140"
5) "a"
6) "260"
127.0.0.1:6379> zrange s1 0 -1 withscores
1) "b"
2) "20"
3) "c"
4) "30"
5) "a"
6) "100"

扩展操作

做数据的排序

比如:电影排行

//查看某个元素的索引(排名)
zrank key member
zrevrank key member

//查看某个元素索引的值
zscore key member
//增加某个元素索引的值
zincrby key increment member
127.0.0.1:6379> zadd movies 111 a1 222 a2 333 a3
(integer) 3
127.0.0.1:6379> zrank movies a1
(integer) 0
127.0.0.1:6379> zrevrank movies a1
(integer) 2
127.0.0.1:6379> zscore movies a1
"111"
127.0.0.1:6379> zscore movies a2
"222"
127.0.0.1:6379> zincrby movies 10 a1
"121"

注意事项

  • score保存的数据存储空间是64位,如果是整数范围是-9007199254740992~9007199254740992
  • score保存的数据也可以是一个双精度的double值,基于双精度浮点数的特征,可能会丢失精度,使用时候要慎重
  • sorted_set 底层存储还是基于set结构的,因此数据不能重复,如果重复添加相同的数据,score值将被反复覆盖,保留最后一次修改的结果

业务场景

观看影视会员到期需要处理的任务,通过sorted_set设施时间处理任务。

127.0.0.1:6379> zadd hy 172826 uid:1
(integer) 1
127.0.0.1:6379> zadd hy 37459239 uid:2
(integer) 1
127.0.0.1:6379> zadd hy 47389 uid:3
(integer) 1
127.0.0.1:6379> zrange hy 0 -1
1) "uid:3"
2) "uid:1"
3) "uid:2"
127.0.0.1:6379> zrange hy 0 -1 withscores
1) "uid:3"
2) "47389"
3) "uid:1"
4) "172826"
5) "uid:2"
6) "37459239"
//获取当前系统时间
time

应用于定时任务执行顺序管理或任务过期管理

任务/消息权重设定应用

​ 当任务或着消息待处理,形成了任务队列或消息队列时,对于高优先级的任务要保障对其优先处理,如何实现任务权重管理。

127.0.0.1:6379> zadd tasks 4 orderid:1
(integer) 1
127.0.0.1:6379> zadd tasks  6 orderid:2
(integer) 1
127.0.0.1:6379> zadd tasks 10 orderid:2
(integer) 0
127.0.0.1:6379> zrange tasks 0 -1  withscores
1) "orderid:1"
2) "4"
3) "orderid:2"
4) "10"
127.0.0.1:6379> zadd tasks 19 orderid:3
(integer) 1
127.0.0.1:6379> zrevrange tasks 0 -1 withscores
1) "orderid:3"
2) "19"
3) "orderid:2"
4) "10"
5) "orderid:1"
6) "4"

image-20210716154022557

127.0.0.1:6379> zadd tt 102004 order:id:1
(integer) 1
127.0.0.1:6379> zadd tt 101008 order:id:2
(integer) 1
127.0.0.1:6379> zrange tt 0 -1 withscores
1) "order:id:2"
2) "101008"
3) "order:id:1"
4) "102004"
类型数据实践案列

image-20210717132642264

//String类型 
127.0.0.1:6379> get 415
(nil)
127.0.0.1:6379> setex 415 60  1
OK
127.0.0.1:6379> get 415
"1"
127.0.0.1:6379> incr 415
(integer) 2
127.0.0.1:6379> incr 415
(integer) 3
127.0.0.1:6379> get 415
(nil)

image-20210717133159098

127.0.0.1:6379> get 415
(nil)
127.0.0.1:6379> setex 415 60 9223372036854775797
OK
127.0.0.1:6379> get 415
"9223372036854775797"
127.0.0.1:6379> incr 415
(integer) 9223372036854775798
127.0.0.1:6379> incr 415
(integer) 9223372036854775799
127.0.0.1:6379> incr 415
(integer) 9223372036854775800
127.0.0.1:6379> incr 415
(integer) 9223372036854775801
127.0.0.1:6379> incr 415
(integer) 9223372036854775802
127.0.0.1:6379> incr 415
(integer) 9223372036854775803
127.0.0.1:6379> incr 415
(integer) 9223372036854775804
127.0.0.1:6379> incr 415
(integer) 9223372036854775805
   //超出时常,如果在60s内,输入的次数超出限制,会抛出异常
127.0.0.1:6379> incr 415
(integer) 1
127.0.0.1:6379> incr 415
(integer) 2
127.0.0.1:6379> get 415
"2"

模拟微信消息发送时间排序

set用来存放置顶的消息

此时 300 用户向100 用户发送消息,需要判断是普通消息还是置顶消息

image-20210901145117114

接下来400,发消息,在100用户中400用户是置顶消息,因此400的消息放到置顶list中

image-20210901145351183

200用户连续发送两次消息,都是普通消息,200第一次消息放入普通list,第二次消息放入list前会把之前的200消息去除,再放入,

image-20210901145653669

最后300用户又发了一次信息,发现原本list中有300信息,将其去除在加入到list中,放在200之后。

image-20210901145848845

最后100拿起手机查看消息,400为置顶位于最前,300消息最近在200之前

image-20210717134415007 image-20210717134434609
//List类型
127.0.0.1:6379> lpush 100 200
(integer) 1
127.0.0.1:6379> lrem 100 1 300
(integer) 0
127.0.0.1:6379> lpush 100 300
(integer) 2
127.0.0.1:6379> lrem 100 1 400
(integer) 0
127.0.0.1:6379> lpush 100 400
(integer) 3
127.0.0.1:6379> lrem 100 1 200
(integer) 1
127.0.0.1:6379> lpush 100 200
(integer) 3
127.0.0.1:6379> lrem 100 1 300
(integer) 1
127.0.0.1:6379> lpush 100 300
(integer) 3
127.0.0.1:6379> lrange 100 0 -1
1) "300"
2) "200"
3) "400"

Key通用命令

key通用操作

特征:

  • key是一个字符串,通过key获取redis中保存的数据

基本操作

//查看key是否存在
exists key

//删除key
del key

//查看key的类型
type key
127.0.0.1:6379> set str str
OK
127.0.0.1:6379> hset hash hash1 1
(integer) 1
127.0.0.1:6379> lpush list1 1
(integer) 2
127.0.0.1:6379> sadd set 1
(integer) 1
127.0.0.1:6379> zadd zset 1 zset1 2 zset2
(integer) 2
127.0.0.1:6379> type str
string
127.0.0.1:6379> type hash
hash
127.0.0.1:6379> type list1
list
127.0.0.1:6379> type set
set
127.0.0.1:6379> type zset
zset

扩展操作(时效性操作)

//设置生命周期
expire key seconds(秒)
pexpire key milliseconds(毫秒)
expire key timestamp   (时间戳)
pexpire key milliseconds-timestamp

//获取key的有效时间, 如果有有效时间则返回剩余有效时间, 如果为永久有效,则返回-1, 如果Key不存在则返回-2
ttl key
pttl key

//将有时限的数据设置为永久有效
persist key
127.0.0.1:6379> set str str
OK
127.0.0.1:6379> get str
"str"
127.0.0.1:6379> expire str 3
(integer) 1
127.0.0.1:6379> get str
"str"
127.0.0.1:6379> get str
(nil)
127.0.0.1:6379> expire str 30
(integer) 0
127.0.0.1:6379> ttl str
(integer) -2
127.0.0.1:6379> get str
(nil)
127.0.0.1:6379> set str str
OK
127.0.0.1:6379> expire str 30
(integer) 1
127.0.0.1:6379> ttl str
(integer) 26
127.0.0.1:6379> pttl str
(integer) 20303
127.0.0.1:6379> ttl str
(integer) 17
127.0.0.1:6379> persist str
(integer) 1
127.0.0.1:6379> ttl str
(integer) -1

(查询模式)

//根据key查询符合条件的数据
keys pattern

查询模式规则

image-20210717141459800

其他操作

//重命名key,为了避免覆盖已有数据,尽量少去修改已有key的名字,如果要使用最好使用renamenx
rename key newKey
renamenx key newKey

//对有所key排序,不会改变原数据
sort

//查看所有关于key的操作, 可以使用Tab快速切换
help @generic

数据库通用指令

数据库

image-20210717143740151

解决方案

  • Redis为每个服务提供有16个数据库,编号从0到15
  • 每个数据库之间的数据相互独立

Database 基本操作

//切换数据库 0~15
select index

//其他操作
quit
    //测试服务器
ping
echo massage

扩展操作

//移动数据, 必须保证目的数据库中没有该数据
mov key db
    
//数据清除
//刷掉当前的数据
flushdb
//删除所有数据
flushall


//查看该库中数据总量
dbsize

Jedis

Jedis简介

编程语言与redis

  • java语言连接redis服务

    Jedis

    SpringData Redis

    Lettuce

  • C、c++、c#、Erlang等等

HelloWorld(Jedis)

Java操作引入Maven依赖

        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.9.0</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>

Java操作redis的步骤

  1. 连接redis
  2. 操作redis
  3. 关闭连接
    //1.连接redis,ip和端口号
    Jedis jedis =  new Jedis("127.0.0.1",6379);
    //2.操作redis,jedis中对数据操作的指令和redis中的指令是一样的。
    jedis.set("小白","hello");
    //3.关闭连接
    jedis.close();

获取数据

        //获取数据
        String str = jedis.get("小白");
        System.out.println(str);
//结果:hello

Jedis读写redis数据

案例要求

image-20210718131202763

//这里按照s来测试
package Jedis;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.exceptions.JedisDataException;

import static java.lang.Math.*;

public class Service {
    private String id;
    private int nums;
    public  Service(String id,int nums){
        this.id = id;
        this.nums = nums;
    }

    //控制单元
    public void service(){
        Jedis jedis =  new Jedis("127.0.0.1",6379);
        String value =  jedis.get("compid:"+id);
        //判断该值是否存在
        try {
            if (value == null){
                //不存在,创建该值并设置生命周期
                //设定允许10s内调用nums次
                jedis.setex("compid:"+id,10,Long.MAX_VALUE - nums+"");
            }else {
                //存在,自增,调用业务

                long nums1 =  jedis.incr("compid:"+id);

                business(nums-(Long.MAX_VALUE-nums1),id);
            }
        } catch (JedisDataException e){
            System.out.println("调用次数已经到达上限,请升级会员");
            return;
        }finally {
            jedis.close();
        }


    }
    //业务操作
    public void business(Long nums, String id){
        System.out.println("用户:"+id+" 业务操作执行"+nums);
    }
}

class MyThread extends Thread{
    Service sc ;
    public MyThread(String name,int nums){
        sc = new Service(name,nums);
    }

    @Override
    public void run() {
        while (true){
            sc.service();
            try {
                Thread.sleep((long) (500L + abs(random())));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

class Main{
    public static void main(String[] args) {
        MyThread myThread = new MyThread("初级用户",10);
        MyThread myThread1 = new MyThread("高级用户",20);
        myThread.start();
        myThread1.start();
    }
}

Jedis简易工具类开发

基于连接池获取链接

image-20210718140311964

配置文件

//全局配置
redis.host = 127.0.0.1
redis.port = 6379
redis.maxTotal = 30
redis.maxIdle = 10

简易工具类

public class JedisUtils {
    private static String host;
    private static Integer port;
    private static Integer maxTotal;
    private static Integer maxIdle;

    private static  JedisPool jedisPool = null;

    //静态代码块在类加载时,只加载一次
    static {
        //加载配置文件
        ResourceBundle rb = ResourceBundle.getBundle("redis");
        //服务地址
        host = rb.getString("redis.host");
        //端口号
        port = Integer.valueOf(rb.getString("redis.port"));
        //最大连接数
        maxTotal = Integer.valueOf(rb.getString("redis.maxTotal"));
        //最大活动连接数
        maxIdle = Integer.valueOf(rb.getString("redis.maxIdle"));

        JedisPoolConfig jpc = new JedisPoolConfig();
        jpc.setMaxTotal(maxTotal);
        jpc.setMaxIdle(maxIdle);
        jedisPool = new JedisPool(jpc,host,port);

    }


    public static Jedis getJedis(){
       return jedisPool.getResource();

    }
}

可视化客户端

Redis可视化工具

下载

image-20210718143009622

image-20210718143018947

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值