(二)Redis数据类型,事务和Jedis操作Redis

【征服redis3】一文征服redis的jedis客户端 Jedis 是一个流行的 Java 编写的 Redis 客户端库,它提供了连接和操作 Redis 服务器的功能。简单易用:Jedis 提供了简洁的 API,方便开发人员使用,减少了连接和操作 Redis 的复杂性。高性能:Jedis 是通过直接与 Redis 服务器进行通信来实现操作的,因此具有较高的性能。支持多种数据类型:Jedis 支持操作 Redis 的各种数据类型,包括字符串、哈希、列表、集合、有序集合等。 阅读详情

注:笔记整理来源 B站UP主狂神说Java

Redis五大基本类型

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

String

127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> set key1 v1    设置值
OK
127.0.0.1:6379> get key1          获取值
"v1"
127.0.0.1:6379> keys *          获取所有的key
1) "key1"
127.0.0.1:6379> exists key1          判断一个key是否存在
(integer) 1
127.0.0.1:6379> append key1 "hello"     追加字符串,若key不存在,相当于set key
(integer) 7
127.0.0.1:6379> get kye1
(nil)
127.0.0.1:6379> strlen key1    获取key的长度
(integer) 7
127.0.0.1:6379> append key1 ",kuangshen"
(integer) 17
127.0.0.1:6379> strlen key1
(integer) 17
127.0.0.1:6379> get key1
"v1hello,kuangshen"

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> get views
"1"
127.0.0.1:6379> incrby views 10  以步长为10进行增长
(integer) 11
127.0.0.1:6379> get views
"11"
127.0.0.1:6379> decrby views 8  以步长为8进行递减
(integer) 3
127.0.0.1:6379> get views
"3"

127.0.0.1:6379> set key1 "hello,fly"
OK
127.0.0.1:6379> get key1
"hello,fly"
127.0.0.1:6379> getrange key1 0 4   字符串截取
"hello"
127.0.0.1:6379> getrange key1 0 -1
"hello,fly"

127.0.0.1:6379> setex key3 30 "hello"   设置过期时间
OK
127.0.0.1:6379> ttl key3
(integer) 26
127.0.0.1:6379> get key3
(nil)
127.0.0.1:6379> ttl key3
(integer) -2

127.0.0.1:6379> setnx mykey redis   mykey不存在,设置成功
(integer) 1                    设置成功返回1,失败返回0
127.0.0.1:6379> keys *
1) "key2"
2) "key1"
3) "mykey"
127.0.0.1:6379> setnx mykey mongodb  mykey存在,设置失败
(integer) 0
127.0.0.1:6379> get mykey
"redis"

127.0.0.1:6379> mset key1 v1 key2 v2 key3 v3    设置多个值
OK
127.0.0.1:6379> keys *
1) "key2"
2) "key1"
3) "key3"
127.0.0.1:6379> mget key1 key2 key3   获取多个值
1) "v1"
2) "v2"
3) "v3"
msetnx key1 v1 key4 v4
(integer) 0

127.0.0.1:6379> getset db redis          如果不存在,则返回nil
(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"

与CAS结构是相通的

拓展:
-----------
对象:
set user:1{name:zhangsan,age:3} 设置一个user:1 对象 值为json字符串来保存一个对象
这里的key是一个巧妙的设计: user:{id}:{filed} 如此设计在redis是完全ok的

127.0.0.1:6379> mset user:1:name zhangsan user:1:age 17
OK
127.0.0.1:6379> mget user:1:name user:1:age
1) "zhangsan"
2) "17"

String类似的使用场景:
value除了是字符串,也可以是数字
-计数器
-统计多单位的数量{uid:9282329:follow 0} 可以inc uid:9282329:follow
-----------

List (基本的数据类型)

在redis里,可以将redis 玩成,栈,队列,阻塞队列等.所有的list命令都是 l开头的


LPUSH RPUSH

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> lrange list 0 -1
1) "three"
2) "two"
3) "one"
127.0.0.1:6379> lrange list 0 1
1) "three"
2) "two"
127.0.0.1:6379> rpush list 1    将一个或多个值放入列表的尾部
(integer) 7
127.0.0.1:6379> rpush list 2
(integer) 8
127.0.0.1:6379> rpush list 3
(integer) 9
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "two"
3) "one"
4) "1"
5) "2"
6) "3"

LPOP RPOP

127.0.0.1:6379> rpop list  从后面移除一个
"3"
127.0.0.1:6379> lpop list  从前面移除一个
"three"

Lindex

127.0.0.1:6379> lindex list 1   获取index位置的值
"one"

Llen

127.0.0.1:6379> Llen list
(integer) 7

移除指定的值:Lrem

127.0.0.1:6379> lrem list 1 one   移除 1个 "one"
(integer) 1
127.0.0.1:6379> lrange list 0 -1
1) "two"
2) "3"
3) "2"
4) "1"
5) "1"
6) "2"

ltrim  修剪:list

 127.0.0.1:6379> lpush mylist hello1
(integer) 1
127.0.0.1:6379> lpush mylist hello2
(integer) 2
127.0.0.1:6379> lpush mylist hello3
(integer) 3
127.0.0.1:6379> ltrim mylist 1 2
OK
127.0.0.1:6379> lrange mylist 0 -1
1) "hello2"
2) "hello1"

rpoplpush 移除列表的最后一个元素并将其移动到新的列表中

127.0.0.1:6379> lrange mylist 0 -1
1) "hello2"
2) "hello1"
127.0.0.1:6379> rpoplpush mylist myotherlist
"hello1"
127.0.0.1:6379> lrange mylist 0 -1
1) "hello2"
127.0.0.1:6379> lrange myotherlist 0 -1
1) "hello1"

LSET 指定下标更新值

127.0.0.1:6379> lset mylist 0 "hello3"
OK

linsert 往指定位置前或后面插入value值

127.0.0.1:6379> linsert mylist before(after) hello3 "other"
(integer) 2
127.0.0.1:6379> lrange mylist 0 -1
1) "other"
2) "hello3"

小结:
list其实是一个链表,before Node after, left ,right都可以插入值
如果key不存在,则创建新的链表
key存在,新增内容
如果移除了key,为空链表,则不存在
在两边插入,或者改动值,效率最高! 操作中间元素效率偏低
消息排队!消息队列(Lpush Rpop) 栈(Lpush lpop)

Set(集合)

set中的值不能重复

Sadd ,Smember , SisMember

127.0.0.1:6379> sadd myset "hello"   set集合添加元素
(integer) 1
127.0.0.1:6379> sadd myset "fly"
(integer) 1
127.0.0.1:6379> sadd myset "love fly"
(integer) 1
127.0.0.1:6379> SMEMBERS myset     查看指定set的所有值
1) "love fly"
2) "hello"
3) "fly"
127.0.0.1:6379> SISMEMBER myset hi     查看set是否包含该元素,有返回1 ,没有返回0
(integer) 0
127.0.0.1:6379> SISMEMBER myset hello
(integer) 1

Scard

127.0.0.1:6379> scard myset    获取set集合的中的个数
(integer) 3

Srem

127.0.0.1:6379> srem myset hello  移除set的元素
(integer) 1

Set无序,不重复集合,抽随机

127.0.0.1:6379> SRANDMEMBER myset    随机抽出一个元素
"love fly"
127.0.0.1:6379> SRANDMEMBER myset
"love fly"
127.0.0.1:6379> SRANDMEMBER myset
"love fly"
127.0.0.1:6379> SRANDMEMBER myset
"love fly"
127.0.0.1:6379> SRANDMEMBER myset
"fly"
127.0.0.1:6379> SRANDMEMBER myset 2   随机抽出指定个数的元素
1) "love fly"
2) "fly"

Spop 删除指定的key,随即删除key!

 127.0.0.1:6379> SPOP myset    随机删除set集合中的一些元素
"fly"

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

127.0.0.1:6379> smove myset newset fly   如果没有目标集合,会删除第一个集合的元素,不会创建目标集合
(integer) 0
127.0.0.1:6379> SMEMBERS newset
(empty array)
127.0.0.1:6379> SMEMBERS myset
1) "love fly"

Set集合场景:
微博,B站,共同关注(交集)
微博:A用户将所有关注的人放在一个set集合中!将粉丝也放在集合中
A用户和B用户的共同关注,共同爱好,二度好友(推荐好友)
数字集合类:
-差集

127.0.0.1:6379> sadd key a
(integer) 1
127.0.0.1:6379> sadd key b
(integer) 1
127.0.0.1:6379> sadd key c
(integer) 1
127.0.0.1:6379> sadd key1 d
(integer) 1
127.0.0.1:6379> sadd key1 c
(integer) 1
127.0.0.1:6379> sadd key1 e
(integer) 1
127.0.0.1:6379> SDIFF key key1   求差集
1) "b"
2) "a"
    -交集
127.0.0.1:6379> SINTER key key1  求交集
1) "c"
    -并集
127.0.0.1:6379> SUNION key key1
1) "b"
2) "c"
3) "d"
4) "a"
5) "e"

Hash(哈希,Map集合)

存储的是key - map !  value值为map集合
Hash本质和String 没有太大区别,还是一个key-value.只不过value值为 map(key-value)!

127.0.0.1:6379> hset myhash field fly   设置key-map值
(integer) 1
127.0.0.1:6379> hget myhash field   获取key-map值
"fly"
127.0.0.1:6379> hmset myhash field fly field hello 设置多个key-map值,重复设置会覆盖掉
OK
127.0.0.1:6379> hget myhash field 
"hello"
127.0.0.1:6379> hmget myhash field field1 获取多个key-map值
1) "fly"
2) "hello"
127.0.0.1:6379> hgetall myhash  获取所有值
1) "field"     field-fly  属于一个key-value 
2) "fly"
3) "field1"
4) "hello"
127.0.0.1:6379> hdel myhash field1   删除指定的一个value值
(integer) 1
127.0.0.1:6379> hgetall myhash
1) "field"
2) "fly"
127.0.0.1:6379> hmset myhash field1 1 field2 2
OK
127.0.0.1:6379> hlen myhash      获取长度
(integer) 3
127.0.0.1:6379> hexists myhash field    判断字段是否存
(integer) 1
127.0.0.1:6379> hkeys myhash  只获取key值
1) "field"
2) "field1"
3) "field2"
127.0.0.1:6379> hvals myhash  只获取value值
1) "fly"
2) "1"
3) "2"
127.0.0.1:6379> hincrby myhash field1 10 以指定步长增长 
(integer) 11
127.0.0.1:6379> hincrby myhash field1 -1 以指定步长减少(值为负值,就是递减) 
(integer) 10
127.0.0.1:6379> hgetall myhash
1) "field"
2) "fly"
3) "field1"
4) "11"
5) "field2"
6) "2"
127.0.0.1:6379> hsetnx myhash field f  如果存在,则设置失败,不存在则创建(分布式锁:成功version+1)
(integer) 0

hash存储变更的数据:
user name age,尤其是用户信息的保存,经常变动的信息
hash更适合对象的存储,String更适合字符串存储

Zset(有序集合:Sort Set)

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

添加值 zadd key score(根据score排序) value

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"

排序 ZrangeByScore key min(最小值) max(最大值) withsocres(显示socre)

127.0.0.1:6379> ZRANGEBYSCORE salary -inf +inf withscores  从小到大排序
1) "gou"
2) "2000"
3) "fly"
4) "2500"
5) "lei"
6) "2600"

Zrevrange key start stop 从大到小排序

127.0.0.1:6379> zrevrange salary 0 -1
1) "lei"
2) "gou"

移除元素 Zrem

127.0.0.1:6379> zrem salary fly
(integer) 1
查看元素个数 Zcard
127.0.0.1:6379> zcard salary
(integer) 2

查询score在指定区间的数量 Zcount key min max

127.0.0.1:6379> zcount salary 0 2700
(integer) 2

应用场景:

如果工作中需要,可以查询官方文档!
*********************
set排序,可以存储班级成绩表,工资表排序,
普通消息(1),重要消息(2)
排行榜应用,TOP N测试
*********************

三种特殊数据类型

geospatial (地图,地理位置)

朋友的定位,附近的人,打车距离实现
redis的Geo  可以推算地理位置的信息(两地之间的距离,方圆几里的人)
可以查询一些测试数据
主要有6个命令:

GEOADD(添加地理位置) geoadd key longitude(经度) latitude(纬度) member
规则:地球两级(南北极)没办法添加,一般会下载城市数据,通过java程序读取文件导入
参数:key(经度,纬度,名称)
有效的经度 -85.05到85.05
有效的纬度 -180到 180

127.0.0.1:6379> geoadd china:city 116.40 39.30 beijing
(integer) 1
127.0.0.1:6379> geoadd china:city 121.47 31.32 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.08 22.54 shenzhen
(integer) 1
127.0.0.1:6379> geoadd china:city 120.15 30.28 hangzhou
(integer) 1
127.0.0.1:6379> geoadd china:city 108.94 34.26 xian
(integer) 1

GEODIST(Geo distince:获取给定两个位置之间的距离)
单位: 
-m 单位米
-km 单位千米
-mi 单位英里
-ft 单位千尺

127.0.0.1:6379> geodist china:city beijing shanghai   北京到上海的直线距离 m
"1008342.6601"
127.0.0.1:6379> geodist china:city beijing shanghai km   北京到上海的直线距离 km
"1008.3427"
127.0.0.1:6379> geodist china:city beijing chongqing km  北京到重庆的距离 km
"1414.4224"

GEOHASH(返回一个或者多个位置的GeoHash表示)

127.0.0.1:6379> GEOHASH china:city beijing
1) "wwfz8drghe0"       代表当前城市经纬度的字符串11位的hash,如果两个字符串越接近,那么距离就越近
    GEOPOS(获取指定地理位置的经度和纬度)
127.0.0.1:6379> geopos china:city xian
1) 1) "108.93999785184860229"
2) "34.25999964418929977"
127.0.0.1:6379> geopos china:city beijing
1) 1) "116.39999896287918091"
2) "39.30000117660147652"
127.0.0.1:6379> geopos china:city chongqing
1) 1) "106.49999767541885376"
2) "29.52999957900659211"
127.0.0.1:6379> geopos china:city shenzhen
1) 1) "114.08000081777572632"
2) "22.53999903789756587"
127.0.0.1:6379> geopos china:city hangzhou
1) 1) "120.15000075101852417"
2) "30.2800007575645509"
127.0.0.1:6379> 

GEORADIUS(以给定的经纬度为中心,找出某一半径内的元素)
微信找好友 附近的人?(获取附近的人的地址,定位) 通过半径来查询!

127.0.0.1:6379> GEORADIUS china:city 110 30 1000 km 以110 30为中心,半径1000km内的
1) "chongqing"
2) "shenzhen"
3) "hangzhou"
获取指定数量的人 200人
127.0.0.1:6379> GEORADIUS china:city 110 30 1000 km withcoord withdist count 1 获取1人
1) 1) "chongqing"
2) "341.9374"
3) 1) "106.49999767541885376"
2) "29.52999957900659211"

所有的数据都应录入 china:city中,才会使结果更加精确

GEORADIUSBYMEMBER(找出指定范围内的元素,中心点由给定的位置元素决定) 城市间的定位(导航)

127.0.0.1:6379> GEORADIUSBYMEMBER china:city beijing 1000 km
1) "beijing"
2) "xian"
127.0.0.1:6379> GEORADIUSBYMEMBER china:city shanghai 400 km
1) "hangzhou"
2) "shanghai"

GEO底层的实现原理就是Zset!
127.0.0.1:6379> type china:city
zset
就可以使用Zset命令来操作Geo

127.0.0.1:6379> zrange china:city 0 -1   查看地图全部元素
1) "chongqing"
2) "xian"
3) "shenzhen"
4) "hangzhou"
5) "shanghai"
6) "beijing"
127.0.0.1:6379> zrem china:city shenzhen  删除指定地图元素
(integer) 1
127.0.0.1:6379> zrange china:city 0 -1
1) "chongqing"
2) "xian"
3) "hangzhou"
4) "shanghai"
5) "beijing"

**

hyperloglog

什么是基数?
A{1,3,5,7,5,9}
B{1,3,5,7,8}
基数(不重复的元素) = 5 简介 redis2.8.9版本就更新了Hyperloglog数据结构! Redis Hyperloglog 基数统计的算法!
优点:占用的内存是固定的 2^64不同元素非技术,只需要12KB内存.从内存角度出发,hyperloglog为首选 网页的UV(Uniqe
Visitor:独立访客数 一个人访问一个网站多次,还是算作一个人)

传统的方式:set 保存用户的id,然后统计set中的元素数量作为标准判断
这个方式如果保存大量的用户id,占用内存过多,就会很麻烦!目的是为了计数,而不是保存id
0.81%的错误率! 统计UV的任务是可以忽略不计

测试使用

127.0.0.1:6379> pfadd mykey a b c d e f g h i j  创建第一组元素集
(integer) 1
127.0.0.1:6379> pfcount mykey  统计第一组元素基数数量
(integer) 10
127.0.0.1:6379> pfadd mykey2 i j z x c v b n m
(integer) 1
127.0.0.1:6379> pfcount mykey2
(integer) 9
127.0.0.1:6379> PFMERGE mykey3 mykey2 mykey 合并两组 mykey + mykey2 ->mykey3 
OK
127.0.0.1:6379> pfcount mykey3
(integer) 15

应用场景

进行页面统计
如果允许容错,一定可以使用Hyperloglog
不允许容错,就是用set或者自己的数据类型即可!

bitmap(位图)

位存储:都是操作二进制位来进行记录,非0即1 统计疫情感染人数: 0 0 0 0 0 1 1 0 (1为感染者) 统计用户信息,
活跃人数或者不活跃人数. 
登录或者未登录 学生365打卡. 365天=365bit 1字节=8bit 46个字节就可以存储(节省内存)
只要是有两个状态的,都可以使用bitmap(位图)

使用bitmaps记录周一到周日的打卡  setbit key offest value
周一:1 周二:1 周三:0 …

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 0
(integer) 0
127.0.0.1:6379> setbit sign 3 0
(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 1
(integer) 0

查看某一天是否有打卡 getbit key offest

127.0.0.1:6379> getbit sign 1
(integer) 1
127.0.0.1:6379> getbit sign 3
(integer) 0
统计打卡的天数     bitcount key [start end]
127.0.0.1:6379> bitcount sign 0 6
(integer) 5

Redis事务操作

什么是事务:一组命令一起执行的集合.
一个事务中的所有命令都会被序列化,在事务执行的时候,按照顺序执行!一次性,顺序性.排他性
---------------队列 set set set 执行----------------

要么同时成功,要么同时失败,原子性
redis事务不保证原子性!!!
redis单条命令是保证原子性的!!!
redis事务没有隔离级别概念!(不会出现幻读,脏读,不可重复读...)
所有的命令在事务中,并没有直接被执行!只有发起执行命令时,才会执行!

redis的事务:
-开启事务(multi)
-命令入队()
-执行事务(exec)

正常执行事务:

127.0.0.1:6379> multi  开启事务
OK
127.0.0.1:6379> set key1 v1
QUEUED
127.0.0.1:6379> set key2 v2
QUEUED
127.0.0.1:6379> set key3 v3
QUEUED
127.0.0.1:6379> get key2
QUEUED
127.0.0.1:6379> get key1
QUEUED
127.0.0.1:6379> exec   执行事务
1) OK
2) OK
3) OK
4) "v2"
5) "v1"
127.0.0.1:6379> multi  开启事务
OK
127.0.0.1:6379> set key1 v1
QUEUED
127.0.0.1:6379> set key2 v2
QUEUED
127.0.0.1:6379> set key4 v4
QUEUED
127.0.0.1:6379> DISCARD  取消事务
OK
127.0.0.1:6379> get key4 事务队列中的命令不会被执行
(nil)

编译异常(redis命令有误):事务中所有的命令都不会被执行

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 k4
(error) ERR wrong number of arguments for 'getset' command
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 v5   所有的命令都不会被执行
(nil) 

运行时异常(语法有误):事务存在语法问题,在执行的时候其他命令可以正常执行,
错误命令抛异常(所以无原子性)

127.0.0.1:6379> multi
OK
127.0.0.1:6379> set k2 "v2"
QUEUED
127.0.0.1:6379> incr k2
QUEUED
127.0.0.1:6379> exec
1) OK
2) (error) ERR value is not an integer or out of range

锁:Redis可以实现乐观锁, watch 监控!
悲观锁:很悲观,认为什么时候都会出问题,无论做什么都会加锁!影响性能
乐观锁:很乐观,认为什么时候都不会出问题,所以不会加锁!在更新数据的时候判断,在此期间是否有人修改过数据
1.获取version
2.更新的时候比较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
127.0.0.1:6379> mget money out
1) "80"
2) "20"

多线程:多个客户端操作

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
//线程2进来修改了money
127.0.0.1:6379> get money
"80"
127.0.0.1:6379> set money 1000
OK
127.0.0.1:6379> exec  提交事务发现meney被修改了,就会失败
(nil)

//事务执行失败需要先解锁,在获取最新的值
127.0.0.1:6379> unwatch  1.发现事务执行失败,先解锁
OK
127.0.0.1:6379> watch money 2.获取最新的值,再次监视,select version
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> decrby money 80
QUEUED
127.0.0.1:6379> incrby out 80
QUEUED
127.0.0.1:6379> exec   3.每次执行前,都要比对监视的值有没有发生变化
1) (integer) 920
2) (integer) 100

使用watch可以当做redis的乐观锁操作!

Jedis操作redis

使用java操作redis
什么是jedis ? 
是官方推荐的java连接开发工具! 使用java操作redis

第一步:

<dependencies
<!-- 导入jedis的包-->>
    <dependency>
        <groupId>redis.clients</groupId>
        <artifactId>jedis</artifactId>
        <version>3.2.0</version>
    </dependency>

    <!--导入fastjson -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.62</version>
    </dependency>
</dependencies>

2.编码测试:
 -连接数据库
 -操作命令
 -断开连接

public class TestPing {
    public static void main(String[] args) {
        //1.创建一个Jedis对象
        Jedis jedis = new Jedis("127.0.0.1",6379);
        //Jedis的所有命令都是之前学习redis的命令
        //操作String hash set ZSet list geo hyperloglog bitmap
        System.out.println(jedis.ping());

    }
}

java对五大数据类型操作常用的API

操作redis-keys

Jedis jedis = new Jedis("127.0.0.1", 6379);

System.out.println("清空数据:"+jedis.flushDB());
System.out.println("判断某个值是否存在:"+jedis.exists("username"));
System.out.println("新增<username , fly>的键值对:"+jedis.set("username","fly"));
System.out.println("新增<password , 123>的键值对:"+jedis.set("password","123"));
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("取出值:"+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());

Sring:

Jedis jedis = new Jedis("127.0.0.1", 6379);

jedis.flushDB();
System.out.println("----增加数据----");
System.out.println(jedis.set("key1","value1"));
System.out.println(jedis.set("key2","value2"));
System.out.println(jedis.set("key3","value3"));
System.out.println("删除key2:"+jedis.del("key2"));
System.out.println("获取key2:"+jedis.get("key2"));
System.out.println("修改key1的值:"+jedis.set("key1","afterV1"));
System.out.println("获取key1的值:"+jedis.get("key1"));
System.out.println("在key3后面加入值:"+jedis.append("key3",",hello"));
System.out.println("key3的值:"+jedis.get("key3"));
System.out.println("增加多个key-value值:"+jedis.mset("k1","v1","k2","v2","k3","v3"));
System.out.println("获取多个key-value值:"+jedis.mget("k1","key1","k2","k3"));
System.out.println("删除多个值:"+jedis.del("k1","k2"));
System.out.println("获取多个值:"+jedis.mget("username","name","k3"));

jedis.flushDB();
System.out.println("----新增值防止覆盖----");
System.out.println(jedis.setnx("key1","value1"));
System.out.println(jedis.setnx("key2","value2"));
System.out.println(jedis.setnx("key2","value2-new"));
System.out.println(jedis.get("key1"));
System.out.println(jedis.get("key2"));

System.out.println("---新增值并设置有效时间---");
System.out.println(jedis.setex("key3",10,"倒计时"));
System.out.println(jedis.get("key3"));
try {
    Thread.sleep(10000);
} catch (InterruptedException e) {
    e.printStackTrace();
}
System.out.println(jedis.get("key3"));

System.out.println("---获取原值,更新为新值---");
System.out.println(jedis.getSet("key1", "newkey1"));
System.out.println(jedis.get("key1"));

System.out.println("获取key2的字符串:"+jedis.getrange("key2",2,4));
System.out.println("删除所有数据库的key值:"+jedis.flushAll());

List:

Jedis jedis = new Jedis("127.0.0.1", 6379);
jedis.flushDB();
System.out.println("添加list元素:"+jedis.lpush("Collection","List","Map","Vector"));
System.out.println("添加list元素:"+jedis.lpush("Collection","HashMap"));
System.out.println("添加list元素:"+jedis.lpush("Collection","TreeSet"));
System.out.println("Collection的内容(全部):"+jedis.lrange("Collection",0,-1));
System.out.println("Collection的内容[0,3]:"+jedis.lrange("Collection",0,3));
System.out.println("-----删除列表指定的值-----");
System.out.println("删除指定元素个数:"+jedis.lrem("Collection",2,"HashMap"));
System.out.println("删除下表[0,3]区间内的值:"+jedis.ltrim("Collection",0,3));
System.out.println("从列表左边出栈:"+jedis.lpop("Collection"));
System.out.println("从列表右边添加值:"+jedis.rpush("Collection","iterator"));
System.out.println("从列表右端出栈:"+jedis.rpop("Collection"));
System.out.println("获取指定下标的内容:"+jedis.lindex("Collection",2));
System.out.println("修改Collection下标为1的值"+jedis.lset("Collection",1,"ArrayList"));
System.out.println("------------------------");
System.out.println("Collection的长度:"+jedis.llen("Collection"));
System.out.println("获取Collection下标为2的值:"+jedis.lindex("Collection",2));
System.out.println("------------------------");
System.out.println("SortList:"+jedis.lpush("sortList","3","6","1","2","7","4"));
System.out.println("sortList排序(从小到大)排序前:"+jedis.lrange("sortList",0,-1));
System.out.println("sortList排序(从小到大)排序后:"+jedis.sort("sortList"));

Set:

Jedis jedis = new Jedis("127.0.0.1", 6379);
jedis.flushDB();

System.out.println("往集合中添加元素------");
System.out.println(jedis.sadd("eleSet", "e1", "e2", "e3", "e4", "e5", "e6"));
System.out.println("Set中所有元素为:"+jedis.smembers("eleSet"));
System.out.println("删除一个元素e1:"+jedis.srem("eleSet","e1"));
System.out.println("Set中所有元素为:"+jedis.smembers("eleSet"));
System.out.println("删除2个元素e3,e4:"+jedis.srem("eleSet","e3","e4"));
System.out.println("Set中所有元素为:"+jedis.smembers("eleSet"));
System.out.println("随机移除集合中的一个元素:"+jedis.spop("eleSet"));
System.out.println("集合中的元素个数:"+jedis.scard("eleSet"));
System.out.println("e1是否存在集合中:"+jedis.sismember("eleSet","e1"));
System.out.println("e2是否存在集合中:"+jedis.sismember("eleSet","e2"));
System.out.println("---------------------");
System.out.println(jedis.sadd("eleSet1","e1","e2", "e3", "e4", "e5", "e6"));
System.out.println(jedis.sadd("eleSet2","e1","e0", "e9", "e6"));
System.out.println("删除eleSet1的e2,并移动到eleSet2中:"+jedis.smove("eleSet1","eleSet2","e2"));
System.out.println("eleSet1中的元素:"+jedis.smembers("eleSet1"));
System.out.println("eleSet2中的元素:"+jedis.smembers("eleSet2"));
System.out.println("----------集合运算--------");
System.out.println("eleSet1和eleSet2额交集:"+jedis.sinter("eleSet1","eleSet2"));
System.out.println("eleSet1和eleSet2额并集:"+jedis.sunion("eleSet1","eleSet2"));
System.out.println("eleSet1和eleSet2额差集:"+jedis.sdiff("eleSet1","eleSet2"));
jedis.sinterstore("eleSet3","eleSet1","eleSet2");
System.out.println("eleSet3的值:"+jedis.smembers("eleSet3"));

Hash:

Jedis jedis = new Jedis("127.0.0.1", 6379);
jedis.flushDB();
Map<String,String> map = new HashMap<String,String>();

map.put("key1","value1");
map.put("key2","value2");
map.put("key3","value3");
map.put("key4","value4");
//添加名(key)为hash的hash元素

jedis.hset("hash",map);
jedis.hset("hash","key5","value5");
System.out.println("hash所有键值对为:"+jedis.hgetAll("hash"));
System.out.println("hash的所有键为:"+jedis.hkeys("hash"));
System.out.println("hash的所有值为:"+jedis.hvals("hash"));
System.out.println("将key66保存的值加上一个整数,如果不存则创建key6:"+jedis.hincrBy("hash","key6",1));
System.out.println("hash所有键值对为:"+jedis.hgetAll("hash"));
System.out.println("删除一个或多个键值对:"+jedis.hdel("hash","key1","key6"));
System.out.println("hash所有键值对为:"+jedis.hgetAll("hash"));
System.out.println("hash所有键值对个数为:"+jedis.hlen("hash"));
System.out.println("判断hash是否存在key2:"+jedis.hexists("hash","key2"));
System.out.println("判断hash是否存在key3:"+jedis.hexists("hash","key3"));
System.out.println("获取hash中的值:"+jedis.hmget("hash","key3"));
System.out.println("获取hash中的值:"+jedis.hmget("hash","key3","key4"));

Redi缓存配置,持久化,订阅发布,主从复制和缓存相关问题以及解决

Redis 深度解析与 Java Jedis 实例 Redis 以其高性能、丰富的数据结构和灵活的用法而受到广泛关注。它支持多种数据类型,如字符串、哈希表、列表、集合和有序集合。Redis 将数据存储在内存中,这使得它能够快速地读写数据,非常适合用于缓存和实时数据处理。Jedis 是一个 Java 语言的 Redis 客户端,它提供了简单易用的 API 来与 Redis 服务器进行交互。Jedis 支持 Redis 的所有数据类型和命令,并提供了连接池管理、事务支持和管道操作等功能。 阅读详情

相关推荐

Redis入门(二)--- redis新增数据类型,jedis操作redis,springboot整合redis

文章目录4、Redis新增的数据类型4.1 Bitmaps4.1.1 基本命令4.1.2 实例4.1.3 Bitmaps和set的对比4.2 HyperLogLog4.2.1 基本命令4.2.2 实例4.3 Geospatial4.3.1 基本命令4.3.2 实例5、Jedis操作redis5.1 Jedis-String5.2 Jedis-List5.3 Jedis-Set5.4 Jedis-Hash5.5 Jedis-Zset6、Springboot整合Redis1、pom依赖2、配置config3、测

化身强盗的博客 2032

详解Redis基础数据类型Set增删查(带Java源码)

Redis集合操作只有增删查,并没有更新操作, 因此,向修改集合的数据,需要先删除数据,再新增, 同时,集合有自身的特定功能,有交集、并集和补集(差集)操作。

天然玩家的博客 3449

Jedis连接Redis操作全面指南

Redis(Remote Dictionary Server)是一个开源的高性能键值对存储数据库,广泛用于缓存解决方案,消息队列系统(如Redis Streams),以及在数据库、缓存和消息中间件等多种场景中。它的数据结构丰富,操作简单,支持多种数据类型的存储,包括字符串(strings)、列表(lists)、集合(sets)、有序集合(sorted sets)、哈希(hashes)、位图(bitmaps)、超日志(hyperloglogs)和地理空间索引(geospatial indexes)。

weixin_29840475的博客 743

Redis-数据类型-Geospatial(地理空间索引)

Redis-数据类型-Geospatial(地理空间索引)

小丁的博客 919

掌握Jedis:Java操作Redis的全面指南

Jedis是Java语言实现的Redis客户端库,它是连接和操作Redis服务器的桥梁。Jedis的API设计简洁直观,能够让Java开发者方便地对Redis进行操作。它支持几乎所有的Redis命令,并且为不同的数据结构提供了丰富的方法实现。

weixin_33480380的博客 974

[运营] ext4分区遇到“Structure needs cleaning”问题,怎么解决 - 结构需要清理

摘要:当ext4文件系统出现"Structure needs cleaning"错误时,表明存在元数据损坏。解决方法包括:1)检查系统日志确认错误;2)卸载受影响分区;3)使用fsck.ext4分步骤修复(先测试模式-n,再保守修复-p,严重损坏时用-y强制修复);4)检查修复结果;5)重新挂载。若数据丢失可尝试从lost+found恢复。建议定期备份、避免异常关机并定期检查文件系统,以防硬件故障导致类似问题。修复前务必备份重要数据。

Rudon滨海渔村的博客 1362

Redis-Geospatial数据类型及其常用命令详解

Redis-Geospatial数据类型及其常用命令详解

喻师傅的学习笔记 1639

CSS字体样式全攻略

🧱 让文字有空间感,适合标题或LOGO。🖋️适合插画、创意工作者的个人页面。🔥 适合标题、品牌名,视觉冲击力强。🧘‍♀️适合极简设计、文化类网站。✨适合科技类网站、博客、作品集。🚀适合游戏、AI、科技类项目。🐰 适合儿童类网站或节日氛围。📖适合时尚、生活方式类内容。🌫️ 适合神秘、梦幻主题。🌃 夜店风、科技感十足。具体效果是文字会上下跳动。

dreams_dream的博客 1806

高效地理位置数据处理:Redis Geospatial Indexes详解

本文介绍了如何利用Redis的Geospatial Indexes数据结构进行高效的地理位置数据处理。通过Java和Jedis库的结合,本文详细讲解了如何添加地理位置数据、查询附近位置、计算距离以及获取某个对象的地理位置。Redis的Geospatial Indexes提供了一种高效且易用的方式来管理和查询地理位置数据,适用于共享单车定位、外卖配送、社交应用和物流配送等场景。文章通过具体的Java代码示例,展示了这些功能的实现方法,并解析了每一步的操作。

欢迎来到【技术拾光者】,在这里,我们专注分享编程教程、技术趋势、实战案例和优质资源。不定期举办技术问答、专家访谈和职业指导。加入我们,共同探索技术世界,提升技能,拓展职业道路! 1430

WangEditor 5.0版本dangerouslyInsertHtml方法的正确使用方式

WangEditor 5.0版本dangerouslyInsertHtml方法的正确使用方式

yang1067155909的专栏 4291

【TCAX相关】Python 官方手册下载页面(中文+英文)

Python 官方手册下载页面(中文+英文) 中文: https://docs.python.org/zh-cn/3.8/archives/ https://docs.python.org/zh-cn/3.6/archives/ 英文: https://www.python.org/doc/versions/ https://docs.python.org/3/archives/ https://www.python.org/ftp/python/doc/ ...

Seekladoom的博客 1012

Redis 集合(Set)方法使用详解

本文主要是介绍集合(Set)中常见方法的使用,包括对应的java使用方式,SADD、SREM、SMOVE、SMEMBERS、SCARD、SISMEMBER、SRANDMEMBER、SPOP、SINTER、SINTERSTORE、SUNION、SUNIONSTORE、SDIFF、SDIFFSTORE

嘉禾嘉宁papa 1万+

ACS运动控制器编程语言

ACS运动控制器采用SPiiPlusLanguage(SPL)作为核心编程语言,该语言基于C语法设计,内置丰富的运动控制指令,支持点位运动、插补等复杂控制。控制器提供专用开发工具SPiiPlusManager和ACSStudio,支持图形化编程与调试。同时兼容TCP/IP、EtherCAT等多种扩展接口,便于与上位机或PLC集成。使用时需注意实时性优先级、轴参数匹配等关键事项。官方文档和示例程序为开发者提供了完善的学习资源。

StevenChen的博客 626

Jedis的了解和使用、Jedis使用Redis事务

我们要使用java来操作redis什么是Jedis 是Redis官方推荐的java连接开发工具!使用Java操作Redis 中间件!(就是一个jar包)如果你要使用java操作redis,那么一定要对Jedis十分的熟悉!1、导入对应的依赖 2、编码测试 输出:说明连接成功 jedis所有方法和redis里的所有命令一模一样,没有任何改变,在redis上能操作的,使用jedis同样可以操作 执行结果: string的其他方法: 执行结果: 执行结果: 执行结果: 也是一样,在linux上执行的命令

dayuiicghaid的博客 1万+

CS 188 Project3(RL) Q10:Approximate Q-Learning

实现一个近似的Q-learning学习代理,它学习状态特征的权重,其中许多状态可能共享相同的特征。在qlearningAgents.py中的ApproximateQAgent类中编写实现,它是PacmanQAgent的子类。 注:近似Q-learning学习假设在状态和动作对上存在一个特征函数f(s,a),它产生一个向量f1(s,a) .. fi(s,a) .. fn(s,a)特征值。我们在fe...

大模型与Agent智能体 2657

12、探索新型高能量密度材料:FOX-7的化学进展

本文全面探讨了新型高能量密度材料FOX-7的化学进展,包括其独特的分子结构、优异的热稳定性、光谱性质以及爆炸性能。对比传统高爆炸药RDX,FOX-7展现出更低的敏感性和更高的安全性。文章还介绍了FOX-7的合成方法、异构体研究、与其结构相关的化合物以及富氮高能材料的最新发展。通过实验和计算方法,研究人员不断优化这类材料的性能,以满足军事和工业领域的高要求。

sea99的博客 353

Java使用Jedis操作Redis的5种数据类型

1、Java使用Jedis客户端 Jedis集成了Redis的相关命令操作,它是Java语言操作Redis数据库的桥梁。Jedis客户端封装了Redis数据库的大量命令,因此具有许多Redis操作API。可以阅读 《Jedis API 文档》。 1.1Jedis的获取 在使用Jedis之前,需要下载Jedis的相关JAR包。如果项目采用的是Maven环境,则需要在pom.xml文件中引入Jedis的配置,配置如下: <!-- Jedis客户端依赖 --> <dependency.

pan_junbiao的博客 5194

从 Chat 提示词到可运行 Fiori 应用,ADT for VS Code 正在把 RAP 开发带进 Agent 时代

本文探讨了在VS Code中使用AI辅助进行ABAP RAP开发的新模式。文章指出,传统RAP开发需要手工创建数据库表、CDS视图、行为定义等十多个关联对象,命名和关联关系容易出错。现在通过GitHub Copilot Agent Mode配合ADT MCP Server,开发者可用自然语言描述业务场景直接生成完整的RAP业务对象。这种生成式开发的核心价值在于:1)通过标准化工具接口(MCP)连接ABAP后端,确保生成符合规范的RAP对象;2)能正确处理多实体组合场景下的命名一致性和关联关系;3)保持生成结

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 89

Redis(二)对事务进行操作及Jedis

Redis对事务进行操作及Jedis

文帝的博客 1414

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

springBoot整合Redis(一、Jedis操作Redis)

在springboot环境下连接redis的方法有很多,首先最简单的就是直接通过jedis类来连接,jedis类就相当于是redis的客户端表示。但是因为现在比较常用的是:StringRedisTemplate和RedisTemplate,所以jedis只做简单的介绍。

kkkkatoq的博客 4358

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

redis之jedis的事务操作

#获取redis连接 Jedis jedis=new Jedis("127.0.0.1",6379); #开启jedis事务 Transaction multi=jedis.multi(); #添加数据到redis中 multi.set("ka", "va"); #jedis事务提交 multi.exec(); #jedis事务回滚 multi.discard(); #完整案例如下: ...

qq_35375529的博客 4365

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

使用JedisAPI操作Redis以及Jedis实现Redis事务

目录概括Jedis的基本使用1、导包2、测试ping3、测试Key4、测试String类型5、测试List类型6、测试Set类型7、测试Hash类型总结JedisPool(连接池)的使用介绍为什么要使用连接池?连接池的使用 概括 Jedis是Redis官方提供的Java连接开发工具,使用Java操作Redis的中间件,其实就是一个jar包,里面集成了 redis 的一些命令操作,封装了对 redis 命令的 Java 客户端,如果要使用Java操作Redis,那么一定要熟悉Jedis。 Jedis的基本使用

weixin_43246215的博客 1141

通过Jedis操作Redis的五种数据类型【二】

文章目录一、前言1.1 搭建项目1.2 选择相关依赖1.3 移除lettuce1.4 修改项目配置文件1.5 编写Redis相关配置类二、Jedis操作Redis的五种数据类型2.1 初始化连接Redis2.2 使用Jedis连接池操作Redis2.3 操作String类型数据2.4 操作Hash类型数据2.5 操作List类型数据2.6 操作set类型数据2.7 操作sorted set类型数据2.8 释放资源 Redis相关学习如下 一篇文章教你Redis的入门基本操作【一】 一、前言 准备前提工作

qq_44723773的博客 3823

Redis(简介和安装,常用数据类型和命令,Jedis客户端程序,SpringBoot整合Redis,配置文件解读,事务锁机制及案例,持久化,主从复制,集群操作)

NoSQL(NoSQL = Not Only SQL ),意即“不仅仅是SQL”,泛指非关系型的数据库。NoSQL 不依赖业务逻辑方式存储,而以简单的key-value模式存储。因此大大的增加了数据库的扩展能力。不遵循SQL标准。不支持ACID。远超于SQL的性能。1 能够独立完成redis数据库的安装和启动方式调试2 能够简单操作redis数据库。

小丁的博客 1736

Redis数据类型和持久化,Jedis

redis作用内存存储、持久化效率高,用于高速缓存发布订阅系统地图信息分析计时器,计数器(浏览量)

m0_52796363的博客 930

Redis 常用数据类型操作详解(Jedis版本)

本文介绍了Redis主要数据类型及其Java操作实践。涵盖String、Hash、List、Set和ZSet五种核心数据类型,详细说明每种类型的使用场景和Jedis客户端操作方法,包括缓存设置、计数器、消息队列等典型应用。文章还提供了环境配置指南、完整代码示例和性能优化建议,强调合理选择数据类型对Redis应用开发的重要性,并对比了Jedis与Lettuce客户端的差异。通过本文,开发者可以快速掌握Redis数据结构的实际应用技巧。

Java开发者,专注后端技术分享,深耕框架实战与架构优化,持续输出优质技术干货。 819
上一篇: (一)Redis介绍和Linux环境下安装
下一篇: (三)Redi缓存配置,持久化,订阅发布,主从复制和缓存相关问题以及解决
Java-fly
博客等级 码龄9年 13粉丝 31原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值