Redis3

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: Redis3

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命令,就是我们对应的上面学习的指令,一个都没有变化。

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
1月前
|
存储 监控 NoSQL
redis 相关知识
redis 相关知识
23 1
|
5月前
|
SQL NoSQL Redis
|
6月前
|
监控 NoSQL 算法
Redis为什么这么快
Redis为什么这么快
37 4
|
运维 NoSQL Shell
redis(2)
Redis Cluster 是 redis的分布式解决方案,在3.0版本正式推出 当遇到单机、内存、并发、流量等瓶颈时,可以采用Cluster架构方案达到负载均衡目的。 Redis Cluster之前的分布式方案有两种: 1)客户端分区方案: 优点分区逻辑可控,缺点是需要自己处理数据路由,高可用和故障转移等。 2)代理方案: 优点是简化客户端分布式逻辑和升级维护便利,缺点加重架构部署和性能消耗。 官方提供的 Redis Cluster集群方案,很好的解决了集群方面的问题
|
消息中间件 缓存 NoSQL
Redis总结
Redis总结
35 0
|
NoSQL Java Redis
Redis4
Redis4
43 0
|
NoSQL 安全 Unix
Redis (必看)
Redis 学习点滴 知识分享
85 0
|
存储 消息中间件 缓存
Redis总结(二)
redis 和 memcached 什么区别?为什么高并发下有时单线程的 redis 比多线程的memcached 效率要高?区别:1.mc 可缓存图片和视频。rd 支持除 k/v 更多的数据结构;2.rd 可以使用虚拟内存,rd 可持久化和 aof 灾难恢复,rd 通过主从支持数据备份;3.rd 可以做消息队列。原因:mc 多线程模型引入了缓存一致性和锁,加锁带来了性能损耗。redis 主从复制如何实现的?redis 的集群模式如何实现?redis 的 key 是如何寻址的?
103 0
|
存储 消息中间件 缓存
Redis的使用
Redis的使用
280 0
Redis的使用
|
存储 缓存 NoSQL
redis为什么这么快?
redis为什么这么快?