8、String类型的使用场景
String类似的使用场景: value除了是我们的字符串还可以是我们的数字!
- 计数器
- 统计多单位的数量 例如粉丝数量:uid:95256449:follow o
- 对象缓存
3.3、List(列表)
首先,list是一种基本的数据类型,在Redis中,我们可以把List完成,队列、栈、阻塞队列。
所有的list命令都是 l 开头的
1、添加 lpush 和 rpush
127.0.0.1:6379> lpush list Java # 将一个值或多个值插入到列表的头部(左 left) (integer) 1 127.0.0.1:6379> lpush list Python (integer) 2 127.0.0.1:6379> lpush list C/C++ (integer) 3 127.0.0.1:6379> lrange list 0 -1 1) "C/C++" 2) "Python" 3) "Java" 127.0.0.1:6379> lrange list 0 1 # 通过区间来获取具体的值 1) "C/C++" 2) "Python" 127.0.0.1:6379> rpush list JavaScript # 将一个值或多个值插入到列表的尾部(右 right) (integer) 4 127.0.0.1:6379> lrange list 0 -1 1) "C/C++" 2) "Python" 3) "Java" 4) "JavaScript"
2、移除 lpop 和rpop
127.0.0.1:6379> lrange list 0 -1 # 打印list元素 1) "C/C++" 2) "Python" 3) "Java" 4) "JavaScript" 127.0.0.1:6379> lpop list # 移除list的第一个元素 "C/C++" 127.0.0.1:6379> rpop list # 移除list的最后一个元素 "JavaScript" 127.0.0.1:6379> lrange list 0 -1 # 再次打印list元素 1) "Python" 2) "Java"
3、取值 lindex 和 列表长度
127.0.0.1:6379> lrange list 0 -1 1) "JavaScript" 2) "C/C++" 3) "Python" 4) "Java" 127.0.0.1:6379> lindex list 0 # 通过下表获取list的对应的值 "JavaScript" 127.0.0.1:6379> llen list # 获取list的元素个数 (integer) 4
4、移除指定的值,lrem
127.0.0.1:6379> lpush list JavaScript # 在向list添加一个相同的元素,注意可重复添加元素 (integer) 5 127.0.0.1:6379> lrange list 0 -1 # 查看所有list元素 1) "JavaScript" 2) "JavaScript" 3) "C/C++" 4) "Python" 5) "Java" 127.0.0.1:6379> lrem list 1 JavaScript # 移除list集合中指定个数的value,精确匹配 (integer) 1 127.0.0.1:6379> lrange list 0 -1 1) "JavaScript" 2) "C/C++" 3) "Python" 4) "Java"
5、ltrim 修剪,list 截断
127.0.0.1:6379> lpush list Java (integer) 1 127.0.0.1:6379> lpush list Python (integer) 2 127.0.0.1:6379> lpush list C/C++ (integer) 3 127.0.0.1:6379> lpush list JavaScript (integer) 4 127.0.0.1:6379> ltrim list 0 1 # 通过区间截取指定的元素,这个list已经被改变了。只剩下截取的元素 OK 127.0.0.1:6379> lrange list 0 -1 1) "JavaScript" 2) "C/C++"
6、组合命令,rpoplpush
移除list列表最后一个元素,并将他移动到新的列表中。
127.0.0.1:6379> lrange list 0 -1 # list列表中有两个元素 1) "JavaScript" 2) "C/C++" 127.0.0.1:6379> rpoplpush list Java # 删除list列表中的最后一个元素,并将此元素移动到新的Java列表 "C/C++" 127.0.0.1:6379> lrange list 0 -1 # 查看list列表元素 1) "JavaScript" 127.0.0.1:6379> keys * 1) "list" 2) "Java" 127.0.0.1:6379> lrange Java 0 -1 # 查看新列表元素 1) "C/C++"
7、lset
lset:将列表中指定下标的值,替换为另外一个值
127.0.0.1:6379> exists list # 判断这个列表是否存在 (integer) 1 127.0.0.1:6379> lset item 0 go # 不存在列表,我们去更新就会报错 (error) ERR no such key 127.0.0.1:6379> lpush list Java (integer) 2 127.0.0.1:6379> lrange list 0 0 1) "Java" 127.0.0.1:6379> lset list 0 Linux # 如果当前下标的值存在,就更新当前下标的值 OK 127.0.0.1:6379> lrange list 0 0 1) "Linux" 127.0.0.1:6379> lset list 2 golang # 如果当前下标不存在,也会报错 (error) ERR index out of range
8、linsert
linsert:将某个具体的value插入到列表中,某个元素的前面或者后面
127.0.0.1:6379> rpush list hello (integer) 1 127.0.0.1:6379> rpush list world (integer) 2 127.0.0.1:6379> lrange list 0 -1 1) "hello" 2) "world" 127.0.0.1:6379> linsert list before "world" "Java" # 将java元素插入到world元素的前面 (integer) 3 127.0.0.1:6379> lrange list 0 -1 1) "hello" 2) "Java" 3) "world" 127.0.0.1:6379> linsert list after "world" "welcome" # 将welcome元素插入到world元素后面 (integer) 4 127.0.0.1:6379> lrange list 0 -1 1) "hello" 2) "Java" 3) "world" 4) "welcome"
9、小结
他实际上是一个链表,before Node after , left , right都可以插入值
如果key不存在,创建新的链表
如果key存在,新增内容
如果移除了所有值,空链表,也代表不存在!
在两边插入或者改动值,效率最高!中间元素,相对来说效率会低一点~
消息排队!消息队列( Lpush Rpop ) ,栈( Lpush Lpop )
3.4、Set(集合)
set中的元素是无序不可以重复的!与Java中的set集合类型一样
1、基本的存值
127.0.0.1:6379> sadd myset "Java" # set集合里添加元素 (integer) 1 127.0.0.1:6379> sadd myset "hello" (integer) 1 127.0.0.1:6379> sadd myset "Python" (integer) 1 127.0.0.1:6379> smembers myset # 查看指定set的所有值 1) "hello" 2) "Python" 3) "Java" 127.0.0.1:6379> sismember myset "hello" # 判断某个元素是否存在set集合中 (integer) 1 127.0.0.1:6379> sismember myset "world" (integer) 0
2、获取set集合元素个数
127.0.0.1:6379> scard myset # 获取set集合中元素内容个数 (integer) 3
3、移除 rem
127.0.0.1:6379> smembers myset 1) "hello" 2) "Python" 3) "Java" 127.0.0.1:6379> srem myset "hello" # 移除set集合中指定元素 (integer) 1 127.0.0.1:6379> smembers myset 1) "Python" 2) "Java"
4、随机获取一个set集合元素
127.0.0.1:6379> smembers myset # 查看set所有元素 1) "JavaScript" 2) "Python" 3) "Java" 127.0.0.1:6379> srandmember myset # 随机获取一个set集合元素 "JavaScript" 127.0.0.1:6379> srandmember myset "Java" 127.0.0.1:6379> srandmember myset 2 # 随机获取指定个数的set集合元素 1) "JavaScript" 2) "Python"
5、随机删除set集合的元素
127.0.0.1:6379> smembers myset 1) "JavaScript" 2) "Python" 3) "Java" 127.0.0.1:6379> spop myset # 随机删除set集合里的元素 "Java" 127.0.0.1:6379> smembers myset 1) "JavaScript" 2) "Python"
6、将一个指定的值,移动到另外一个set集合中
127.0.0.1:6379> smembers myset 1) "JavaScript" 2) "Linux" 3) "Java" 4) "Python" 127.0.0.1:6379> smove myset myset2 "Linux" # 将myset 里的元素Linux,移动到myset2集合 (integer) 1 127.0.0.1:6379> smembers myset2 1) "Linux"
7、集合间的交集、差集、并集
# 数字集合 - sdiff 差集 - sinter 交集 - sunion 并集 127.0.0.1:6379> sadd myset1 Java (integer) 1 127.0.0.1:6379> sadd myset2 Python (integer) 1 127.0.0.1:6379> sadd myset1 Python (integer) 1 127.0.0.1:6379> sadd myset2 Linux # 添加元素 (integer) 1 127.0.0.1:6379> sdiff myset1 myset2 # myset1对myset2的差集 1) "Java" 127.0.0.1:6379> sdiff myset2 myset1 # myset2对myset1的差集 1) "Linux" 127.0.0.1:6379> sinter myset1 myset2 # 交集 (共同好友) 1) "Python" 127.0.0.1:6379> sunion myset1 myset2 # 并集 1) "Linux" 2) "Java" 3) "Python"
应用场景:
微博,A用户将所有关注的人放在一个set集合中!将它的粉丝也放在一个集合中!
共同关注,共同爱好,二度好友,推荐好友!(六度分割理论)
3.5、Hash(散列)
Map集合,key-map!时候这个值是一个map集合!本质和String类型没有太大区别,还是一个简单的key-vlaue !set myhash field kuangshen
1、存值与取值
127.0.0.1:6379> hset myhash filed1 alex # set 一个具体的key-value (integer) 1 127.0.0.1:6379> hget myhash filed1 # 获取一个字段值 "alex" 127.0.0.1:6379> hset myhash filed1 "hello" filed2 "world" # set多个key-value (integer) 1 127.0.0.1:6379> hmget myhash filed1 filed2 # 获取多个字段值 1) "hello" 2) "world" 127.0.0.1:6379> hgetall myhash # 获取hash全部的数据 1) "filed1" 2) "hellot" 3) "filed2" 4) "world" 127.0.0.1:6379> hdel myhash filed2 # 删除hash指定的key字段 (integer) 1 127.0.0.1:6379> hgetall myhash 1) "filed1" 2) "hellot"
2、获取hash长度
127.0.0.1:6379> hgetall myhash 1) "filed1" 2) "hellot" 3) "filed2" 4) "world" 127.0.0.1:6379> hlen myhash # 获取长度 (integer) 2
3、判断hash中指定字段是否存在
127.0.0.1:6379> hexists myhash filed1 # 判断hash中指定字段是否存在 (integer) 1 127.0.0.1:6379> hexists myhash filed3 (integer) 0
4、获取所有的filed与value
127.0.0.1:6379> hkeys myhash # 获取所有的filed 1) "filed1" 2) "filed2" 127.0.0.1:6379> hvals myhash # 获取所有的value 1) "hellot" 2) "world"
5、字段值自增与自减
- hincrby 自增 - hdecrby 自减 127.0.0.1:6379> hset myhash filed3 5 # filed3字段的值初始化为 5 (integer) 1 127.0.0.1:6379> hgetall myhash 1) "filed1" 2) "hellot" 3) "filed2" 4) "world" 5) "filed3" 6) "5" 127.0.0.1:6379> hincrby myhash filed3 1 # 字段值自增 1 (integer) 6 127.0.0.1:6379> hget myhash filed3 "6" 127.0.0.1:6379> hincrby myhash filed3 -1 # 字段值自减1 (integer) 5 127.0.0.1:6379> hsetnx myhash filed2 Java # 如果不存在,就能设置 (integer) 1 127.0.0.1:6379> hsetnx myhash filed2 Python # 如果存在,就不能设置 (integer) 0
6、hash的应用
hash变更的数据user name age,尤其是是用户信息之类的,经常变动的信息! hash更适合于对象的存储,String更加适合字符串存储!
3.6、Zset(有序集合)
在set的基础上,增加了一个值。sadd k1 v1 zadd k1 score v1
127.0.0.1:6379> zadd myset 1 C/C++ # 添加一个值 (integer) 1 127.0.0.1:6379> zadd myset 2 Java 3 Python # 添加多个值 (integer) 2 127.0.0.1:6379> zrange myset 0 -1 # 遍历 1) "C/C++" 2) "Java" 3) "Python"
1、排序的实现
127.0.0.1:6379> zadd salary 100 "C/C++" 300 "Java" 50 "Python" # 添加3门语言 (integer) 3 127.0.0.1:6379> zrangebyscore salary -inf +inf # 从小到大排序,显示全部值value 1) "Python" 2) "C/C++" 3) "Java" 127.0.0.1:6379> zrangebyscore salary -inf 200 1) "Python" 2) "C/C++" 127.0.0.1:6379> zrangebyscore salary -inf +inf withscores # 从小到大排序,显示全部的数据 1) "Python" 2) "50" 3) "C/C++" 4) "100" 5) "Java" 6) "300" 127.0.0.1:6379> zrevrange salary 0 -1 # 从大到小排序,并显示value 1) "Java" 2) "C/C++" 3) "Python"
2、移除元素
127.0.0.1:6379> zrange salary 0 -1 1) "Python" 2) "C/C++" 3) "Java" 127.0.0.1:6379> zrem salary "Java" # 移除有序集合中的指定元素 (integer) 1 127.0.0.1:6379> zrange salary 0 -1 1) "Python" 2) "C/C++"
3、获取有序集合长度
127.0.0.1:6379> zcard salary (integer) 2
4、获取区间的成员数量
127.0.0.1:6379> zrangebyscore myset -inf +inf withscores 1) "C/C++" 2) "1" 3) "Python" 4) "3" 5) "Java" 6) "5" 127.0.0.1:6379> zcount myset 1 4 # 获取指定区间的成员数量 (integer) 2
案例思路: set排序存储班级成绩表,工资表排序!普通消息。
1、重要消息
2、带权重进行判断!
排行榜应用实现,取Top N测试!
4、三种特殊的数据类型
4.1、geospatial 地理位置
朋友的定位、附近的人、打车的距离计算?
Redis 的 geo在 3.2版本就已经推出了,这个功能可以推算地理的位置信息!两地之间的距离,方圆几里的人等
在官网中只有6个命令:
GEOADD / geoadd
GEODIST / geodist
GEOHASH / geohash
GEOPOS / geopos
GEORADIUS / georadius
GEORADIUSBYMEMBER / georadiusbymember
城市经纬度查询网址:http://www.jsons.cn/lngcode/
1、geoadd 将指定的地理空间位置(经度、纬度度、名称)添加到指定的key
# geoadd 添加地理位置 # 规则:无法添加南北两极的地理位置,我们一般也会使用下载好的城市地理位置数据,使用Java程序导入 - 有效的经度从-180度到180度。 - 有效的纬度从-85.05112878度到85.05112878度。 # 当坐标位置超出上述指定范围时,该命令将会返回一个错误 127.0.0.1:6379> geoadd china:city 102.712251 25.040609 kunming # 添加单个城市地理位置 (integer) 1 127.0.0.1:6379> geoadd china:city 102.70786 25.03521 wuhua 102.71994 25.04053 panlong # 添加多个城市地理位置 (integer) 2
2、geopos 从key里返回所有给定位置元素的位置(经度和纬度)
127.0.0.1:6379> geopos china:city kunming # 昆明市经纬度(获得当前定位) 1) 1) "102.71225184202194214" 2) "25.04060791987412671" 127.0.0.1:6379> geopos china:city wuhua # 五华区经纬度 1) 1) "102.7078583836555481" 2) "25.0352089638047417"
3、geodist 返回两个给定位置之间的距离,如果两个位置之间的其中一个不存在, 那么命令返回空值。
# 单位 - m 表示单位为米。 - km 表示单位为千米。 - mi 表示单位为英里。 - ft 表示单位为英尺
127.0.0.1:6379> geodist china:city kunming wuhua # 返回昆明市到五华区的距离,默认单位是m "746.0779" 127.0.0.1:6379> geodist china:city kunming panlong m "774.7046" 127.0.0.1:6379> geodist china:city kunming wuhua km # 返回昆明市到五华区的距离,指定单位是km "0.7461"
4、georadius 以给定的经纬度为中心, 返回键包含的位置元素当中, 与中心的距离不超过给定最大距离的所有位置元素
单位:
- m 表示单位为米。
- km 表示单位为千米。
- mi 表示单位为英里。
- ft 表示单位为英尺
127.0.0.1:6379> georadius china:city 100 25 1000 km 1) "wuhua" 2) "kunming" 3) "panlong" 127.0.0.1:6379> georadius china:city 100 25 1000 km withdist # 以此经纬度为中心,返回方圆1000km 以内的城市并显示距离(单位为m) 1) 1) "wuhua" 2) "272.9508" 2) 1) "kunming" 2) "273.3968" 3) 1) "panlong" 2) "274.1714"
5、georadiusbymember 以指定位置元素为中心,返回与中心的距离不超过给定最大距离的所有位置元素
127.0.0.1:6379> georadiusbymember china:city kunming 10 km 1) "wuhua" 2) "kunming" 3) "panlong" 127.0.0.1:6379> georadiusbymember china:city kunming 100 m 1) "kunming"
6、geohash 返回一个或多个位置元素的 Geohash 表示
127.0.0.1:6379> geohash china:city "kunming" # 返回hash值(经纬度计算出来的11位字符串) 1) "wk3n3q8b0g0"
7、geo的底层实现原理其实就是Zset,我们可以使用Zset的命令来操作geo
127.0.0.1:6379> zrange china:city 0 -1 1) "wuhua" 2) "kunming" 3) "panlong" 127.0.0.1:6379> zrange china:city 0 -1 withscores # 遍历,显示所有数据 1) "wuhua" 2) "4021138656314992" 3) "kunming" 4) "4021138666681726" 5) "panlong" 6) "4021138669271381" 127.0.0.1:6379> zrem china:city wuhua # 删除元素 (integer) 1 127.0.0.1:6379> zrange china:city 0 -1 1) "kunming" 2) "panlong"
4.2、Hyperloglog
1、什么是基数?
A{1,3,5,7,8,7} B{1,3,5,7,8}
基数 (不重复的元素) = 5个 可以接受误差
2、Hyperloglog 简介
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 myset a b c d e f g i # 创建第一组元素 myset (integer) 1 127.0.0.1:6379> pfcount myset # 统计myset中的基数数量 (integer) 8 127.0.0.1:6379> pfadd myset2 g i j k l m # 创建第二组元素 myset2 (integer) 1 127.0.0.1:6379> pfcount myset2 # 统计myset2中基数的数量 (integer) 6 127.0.0.1:6379> pfmerge myset3 myset myset2 # 合并 myset 和 myset2 OK 127.0.0.1:6379> pfcount myset3 # 我们可以看到两组元素中,g 和 i 是重复的,只能记一次,所以myset3的基数是12 (integer) 12
3、小结
如果允许容错,那么一定可以使用Hyperloglog !
如果不允许容错,就使用set或者自己的数据类型即可!
4.3、Bitmaps 位图
1、位存储
应用场景:统计用户信息,活跃,不活跃!登录、未登录!打卡,365打卡!两个状态的,都可以使用!
Bitmaps位图,数据结构!都是操作 二进制位 来进行记录,就只有0和1两个状态!
365天= 365 bit1字节=8bit 46个字节左右!
2、测试Bitmaps
假设周一到周天以 0 1 2 3 4 5 6来表示,使用Bitmaps记录周一到周天的打卡,0 代表未打卡,1代表打卡。
127.0.0.1:6379> setbit sign 0 1 (integer) 0 127.0.0.1:6379> setbit sign 1 1 (integer) 0 127.0.0.1:6379> setbit sign 2 1 (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 1 (integer) 0 127.0.0.1:6379> setbit sign 6 0 # 表示周天未打卡 (integer) 0 127.0.0.1:6379> getbit sign 3 # 查看周3有没有打卡,返回1,表示已打卡 (integer) 1 127.0.0.1:6379> getbit sign 6 # 查看周6有没有打卡 (integer) 0
统计打卡天数
127.0.0.1:6379> bitcount sign # 查看打卡天数 (integer) 6
5、事务
5.1、Redis事务概述
Redis事务本质: 一组命令的集合!一个事务中的所有命令都会被序列化,在事务执行过程的中,会按照顺序执行!
一次性、顺序性、排他性!执行一些列的命令!
----- 队列 set set set 执行 -----
Redis事务没有没有隔离级别的概念!
所有的命令在事务中,并没有直接被执行!只有发起执行命令的时候才会执行 ! Exec
Redis单条命令式保存原子性的,但是事务不保证原子性!
Redis的事务:
- 开启事务(multi)
- 命令入队(书写命令)
- 执行事务(exec)
5.2、事务执行流程演示
127.0.0.1:6379> multi # 开启事务 OK 127.0.0.1:6379> set name "Java" # 命令入队 QUEUED 127.0.0.1:6379> set age "25" # 命令入队 QUEUED 127.0.0.1:6379> get name # 命令入队 QUEUED 127.0.0.1:6379> set gender 0 # 命令入队 QUEUED 127.0.0.1:6379> exec # 执行所写的命令 1) OK 2) OK 3) "Java" 4) OK
5.3、放弃事务
127.0.0.1:6379> multi # 开启事务 OK 127.0.0.1:6379> set k1 v1 # 命令入队 QUEUED 127.0.0.1:6379> get k1 QUEUED 127.0.0.1:6379> set k2 v2 QUEUED 127.0.0.1:6379> discard # 放弃事务 OK
5.4、事务编译时异常
事务编译异常:(代码有错,命令有错),事务中所有的命令都不会被执行
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> getset 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> exec # 执行事务报错 (error) EXECABORT Transaction discarded because of previous errors. 127.0.0.1:6379> get k1 # 事务中所有的命令都不会被执行 (nil)
5.5、事务运行时异常
事务运行时异常(i/o):如果事务队列中存在语法性,那么执行命令的时候,其他命令是可以正常执行的,错误命令抛出异常
127.0.0.1:6379> set name howie # 事务外设置一个非数字字符 OK 127.0.0.1:6379> multi # 开启事务 OK 127.0.0.1:6379> incr name # 进行自增1操作,执行的时候回报错 QUEUED 127.0.0.1:6379> set age 21 QUEUED 127.0.0.1:6379> get age QUEUED 127.0.0.1:6379> exec # 执行事务,虽然第一条命令报错了,但是并没有影响,后面命令执行 1) (error) ERR value is not an integer or out of range 2) OK 3) "21" 127.0.0.1:6379> get age "21"
5.6、监控 Watch
1、乐观锁与悲观锁
悲观锁∶
- 很悲观,认为什么时候都会出问题,无论做什么都会加锁!
乐观锁:
- 很乐观,认为什么时候都不会出问题,所以不会上锁!更新数据的时候去判断一下,在此期间是否有人修改过这个数据
- 获取version
- 更新的时候比较version
2、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 # 监视money OK 127.0.0.1:6379> multi OK 127.0.0.1:6379> decrby money 50 QUEUED 127.0.0.1:6379> incrby out 50 QUEUED 127.0.0.1:6379> exec # 执行之前另外一个线程,修改了money的值,这个时候,就会导致事务执行失败! (nil)
如果修改失败,获取最新值就好
127.0.0.1:6379> unwatch # 如果发现事务执行失败,就先解锁! OK 127.0.0.1:6379> watch money # 获取最新值,重新监控money,更新数据时,比较money就相同了 OK 127.0.0.1:6379> multi OK 127.0.0.1:6379> decrby money 50 QUEUED 127.0.0.1:6379> incrby out 50 QUEUED 127.0.0.1:6379> exec # 比对监视的值,事务执行成功 1) (integer) 150 2) (integer) 70
6、Jedis
我们要是Java来操作Redis!
6.1、什么是Jedis
是Redis官方推荐的Java连接开发工具,使用Java操作Redis的中间件,如果你要使用Java操作Redis,你要对Redis非常的熟悉!
6.2、测试
1、新建一个空项目,通过maven,新添一个module
2、导入相关依赖
<dependencies> <!--导入JRedis依赖--> <!-- https://mvnrepository.com/artifact/redis.clients/jedis --> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>3.2.0</version> </dependency> <!--导入FastJson依赖--> <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.73</version> </dependency> </dependencies>
3、编写代码进行测试
- 连接数据库
- 操作命令
- 断开连接
package com.howie.jedis; import redis.clients.jedis.Jedis; public class JedisTest { public static void main(String[] args) { // 主机号 + 端口号 Jedis jedis = new Jedis("127.0.0.1",6379); // 这里要确保windows系统里的Redis服务打开 // jedis所有命令就是我们所学习的那些指令 System.out.println(jedis.ping("hello world")); } } /* 用Jedis连接阿里云等服务器上的redis 1、配置redis.conf 1.设置访问redis的密码:requirepass 要设置密码 2.注释bind 127.0.0.1 (重启redis-server服务,进入redis后要先验证密码,用这个命令:auth 密码 ,然后ping一下看有没有配置成功) 2、idea访问时添加auth密码 Jedis jedis = new Jedis("服务器的外网ip",6379); jedis.auth("redis的密码"); System.out.println(jedis.ping()); (输出PONG的话就成功了) 3、有可能连接失败,可能原因: ①未开启安全组策略6379端口号 ②redis.conf配置文件里受到保护选项设置了yes ③防护墙未关闭 ④需要重启才能生效 */
输出:
6.3、常用的API
Redis-key
public class JedisTest { public static void main(String[] args) { // 主机号 + 端口号 Jedis jedis = new Jedis("127.0.0.1",6379); // jedis所有命令就是我们所学习的那些指令 System.out.println(jedis.ping("hello world")); System.out.println("清空数据:"+jedis.flushDB()); System.out.println("判断某个键是否存在: "+jedis.exists("username")); System.out.println("新增< 'username ', 'howie'>的键值对:"+jedis.set("username", "howie")); System.out.println("新增< 'password' , ' password'>的键值对:"+jedis.set("password","password")); System.out.print("系统中所有的键如下:"); Set<String> keys = jedis.keys("*"); System.out.println(keys) ; System.out.println("删除键password: "+jedis.del("password")); System.out.println("判断键password是否存在:"+jedis.exists("password")); System.out.println("查看键username所存储的值的类型:"+jedis.type("username")); System.out.println("随机返回key空间的一个: "+jedis.randomKey()); System.out.println("重命名key: "+jedis.rename("username", "name")); System.out.println("取出改后的name: "+jedis.get( "name" ) ); System.out.println("修改数据库: "+jedis.select(0)); System.out.println("删除当前选择数据库中的所有key: "+jedis.flushDB()); System.out.println("返回当前数据库中key的数目: "+jedis.dbSize()); System.out.println("删除所有数据库中的所有key: "+jedis.flushAll()); } }
1、String 2、List 3、Set 4、Hash 5、Zset
所有的API命令,就是我们对应的上面学习的指令,一个都没有变化。