(二)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缓存配置,持久化,订阅发布,主从复制和缓存相关问题以及解决

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章