String类型的数据
(常作为缓存使用)
插入和读取一条string类型的数据
127.0.0.1:6379> set sessionid-0001 "zhangsan"
OK
127.0.0.1:6379> get sessionid-0001
对string类型数据进行增减(前提是这条数据的value可以看成数字)
DECR key
INCR key
DECRBY key decrement
INCRBY key increment
127.0.0.1:6379> set a 1
OK
127.0.0.1:6379> get a
"1"
127.0.0.1:6379> decr a
(integer) 0
127.0.0.1:6379> incr a
(integer) 1
127.0.0.1:6379> incr a
(integer) 2
127.0.0.1:6379> get a
"2"
127.0.0.1:6379> incrby a 10
(integer) 12
127.0.0.1:6379> decrby a 10
(integer) 2
一次性插入或者获取多条数据
MGET key1 key2
MSET key1 value1 key2 value2 …..
127.0.0.1:6379> MSET A1 1 A2 2 A3 3
OK
127.0.0.1:6379> MGET A1 A2 A3
1) "1"
2) "2"
3) "3"
在插入一条string类型数据的同时为它指定一个存活期限
setex bancao 10 weige
### bancao这条数据就只会存活10秒钟,过期会被redis自动清除
将一个自定义的对象存入redis
应用:将一个自定义的对象比如product存入redis
实现方式一:将对象序列化成byte数组
/**
* 将对象缓存到redis的string结构数据中
* @throws Exception
*
*/
@Test
public void testObjectCache() throws Exception{
ProductInfo p = new ProductInfo();
p.setName("小米手机");
p.setDescription("小米发烧专用");
p.setCatelog("手机");
p.setPrice(6666);
//将对象序列化成字节数组
ByteArrayOutputStream ba = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(ba);
//用对象序列化流来将p对象序列化,然后把序列化之后的二进制数据写到ba流中
oos.writeObject(p);
//将ba流转成byte数组
byte[] pBytes = ba.toByteArray();
//将对象序列化之后的byte数组存到redis的string结构数据中
jedis.set("product:01".getBytes(), pBytes);
//根据key从redis中取出对象的byte数据
byte[] pBytesResp = jedis.get("product:01".getBytes());
//将byte数据反序列出对象
ByteArrayInputStream bi = new ByteArrayInputStream(pBytesResp);
ObjectInputStream oi = new ObjectInputStream(bi);
//从对象读取流中读取出p对象
ProductInfo pResp = (ProductInfo) oi.readObject();
System.out.println(pResp);
}
实现方式二:
将对象转成json字符串来存取
/**
* 将对象转成json字符串缓存到redis的string结构数据中
*/
@Test
public void testObjectToJsonCache(){
ProductInfo p = new ProductInfo();
p.setName("vivo手机");
p.setDescription("照亮你的美");
p.setCatelog("手机");
p.setPrice(5000);
//利用gson将对象转成json串
Gson gson = new Gson();
String pJson = gson.toJson(p);
//将json串存入redis
jedis.set("prodcut:02", pJson);
//从redis中取出对象的json串
String pJsonResp = jedis.get("prodcut:02");
//将返回的json解析成对象
ProductInfo pResponse = gson.fromJson(pJsonResp, ProductInfo.class);
//显示对象的属性
System.out.println(pResponse);
}
List数据结构
List图示
List功能演示
从头部(左边)插入数据
redis>LPUSH key value1 value2 value3
127.0.0.1:6379> LPUSH aaa aaa1 aaa2 aaa3
(integer) 3
从尾部(右边)插入数据
redis>RPUSH key value1 value2 value3
127.0.0.1:6379> RPUSH bbb bbb1 bbb2 bbb3
(integer) 3
读取list中指定范围的values
redis>LRANGE key start end
redis> lrange task-queue 0 -1 读取整个list
127.0.0.1:6379> LRANGE aaa 0 2
1) "aaa3"
2) "aaa2"
3) "aaa1"
127.0.0.1:6379> LRANGE bbb 0 2
1) "bbb1"
2) "bbb2"
3) "bbb3"
127.0.0.1:6379> LRANGE bbb 0 -1
1) "bbb1"
2) "bbb2"
3) "bbb3"
从头部弹出一个元素
LPOP key
127.0.0.1:6379> LPOP aaa
"aaa3"
127.0.0.1:6379> LRANGE aaa 0 2
1) "aaa2"
2) "aaa1"
从尾部弹出一个元素
RPOP key
127.0.0.1:6379> RPOP aaa
"aaa1"
127.0.0.1:6379> LRANGE aaa 0 -1
1) "aaa2"
从一个list的尾部弹出一个元素插入到另一个list
RPOPLPUSH key1 key2 ## 这是一个原子性操作
List的应用案例demo
需求描述
任务调度系统:
生产者不断产生任务,放入task-queue排队
消费者不断拿出任务来处理,同时放入一个tmp-queue暂存,如果任务处理成功,则清除tmp-queue,否则,将任务弹回task-queue。
代码实现
生产者——模拟产生任务
public class TaskProducer {
// 获取一个redis的客户端连接对象
public static Jedis getRedisConnection(String host, int port) {
Jedis jedis = new Jedis(host, port);
return jedis;
}
public static void main(String[] args) {
Jedis jedis = getRedisConnection("angelababy", 6379);
Random random = new Random();
// 生成任务
while (true) {
try {
// 生成任务的速度有一定的随机性,在1-2秒之间
Thread.sleep(random.nextInt(1000) + 1000);
// 生成一个任务
String taskid = UUID.randomUUID().toString();
// 往任务队列"task-queue"中插入,第一次插入时,"task-queue"还不存在
//但是lpush方法会在redis库中创建一条新的list数据
jedis.lpush("task-queue", taskid);
System.out.println("向任务队列中插入了一个新的任务: " + taskid);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
消费者——模拟处理任务,并且管理暂存队列
public class TaskConsumer {
public static void main(String[] args) {
Jedis jedis = new Jedis("angelababy", 6379);
Random random = new Random();
while (true) {
try {
// 从task-queue中取一个任务,同时放入"tmp-queue"
String taskid = jedis.rpoplpush("task-queue", "tmp-queue");
// 模拟处理任务
Thread.sleep(1000);
// 模拟有成功又有失败的情况
int nextInt = random.nextInt(13);
if (nextInt % 7 == 0) { // 模拟失败的情况
// 失败的情况下,需要将任务从"tmp-queue"弹回"task-queue"
jedis.rpoplpush("tmp-queue", "task-queue");
System.out.println("-------任务处理失败: " + taskid);
} else { // 模拟成功的情况
// 成功的情况下,将任务从"tmp-queue"清除
jedis.rpop("tmp-queue");
System.out.println("任务处理成功: " + taskid);
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Hash数据结构
Hash图示
Redis中的Hashes类型可以看成具有String Key和String Value的map容器
Hash功能演示
往redis库中插入一条hash类型的数据
redis> HSET key field value
举例:
redis 127.0.0.1:6379> hset user001:zhangsan iphone 6
(integer) 1
redis 127.0.0.1:6379> hset user001:zhangsan xiaomi 7
(integer) 1
redis 127.0.0.1:6379> hset user001:zhangsan meizu 8
(integer) 1
在redis库中就形成了这样一条数据:
从redis库中获取一条hash类型数据的value
取出一条hash类型数据中所有field-value对
redis 127.0.0.1:6379> hgetall user001:zhangsan
1) "iphone"
2) "6"
3) "xiaomi"
4) "7"
5) "meizu"
6) "8"
取出hash数据中所有fields
redis 127.0.0.1:6379> HKEYS user001:zhangsan
1) "iphone"
2) "xiaomi"
3) "meizu"
取出hash数据中所有的value
redis 127.0.0.1:6379> hvals user001:zhangsan
1) "6"
2) "7"
3) "8"
取出hash数据中一个指定field的值
redis 127.0.0.1:6379> hget user001:zhangsan xiaomi
"8"
为hash数据中指定的一个field的值进行增减
redis 127.0.0.1:6379> HINCRBY user001:zhangsan xiaomi 1
(integer) 8
从hash数据中删除一个字段field及其值
redis 127.0.0.1:6379> hgetall user001:zhangsan
1) "iphone"
2) "6"
3) "xiaomi"
4) "7"
5) "meizu"
6) "8"
redis 127.0.0.1:6379> HDEL user001:zhangsan iphone
(integer) 1
redis 127.0.0.1:6379> hgetall user001:zhangsan
1) "xiaomi"
2) "7"
3) "meizu"
4) "8"
Set数据结构功能
集合的特点:无序、无重复元素
插入一条set数据
redis 127.0.0.1:6379> sadd frieds:zhangsan bingbing baby fengjie furong ruhua tingting
(integer) 6
redis 127.0.0.1:6379> scard frieds:zhangsan
(integer) 6
redis 127.0.0.1:6379>
获取一条set数据的所有members
redis 127.0.0.1:6379> smembers frieds:zhangsan
1) "fengjie"
2) "baby"
3) "furong"
4) "bingbing"
5) "tingting"
6) "ruhua"
判断一个成员是否属于某条指定的set数据
redis 127.0.0.1:6379> sismember frieds:zhangsan liuyifei #如果不是,则返回0
(integer) 0
redis 127.0.0.1:6379> sismember frieds:zhangsan baby #如果是,则返回1
(integer) 1
求两个set数据的差集
#求差集
redis 127.0.0.1:6379> sdiff frieds:zhangsan friends:xiaotao
1) "furong"
2) "fengjie"
3) "ruhua"
4) "feifei"
#求差集,并将结果存入到另一个set
redis 127.0.0.1:6379> sdiffstore zhangsan-xiaotao frieds:zhangsan friends:xiaotao
(integer) 4
#查看差集结果
redis 127.0.0.1:6379> smembers zhangsan-xiaotao
1) "furong"
2) "fengjie"
3) "ruhua"
4) "feifei"
求交集,求并集
#求交集
redis 127.0.0.1:6379> sinterstore zhangsan:xiaotao frieds:zhangsan friends:xiaotao
(integer) 2
redis 127.0.0.1:6379> smembers zhangsan:xiaotao
1) "bingbing"
2) "baby"
#求并集
redis 127.0.0.1:6379> sunion frieds:zhangsan friends:xiaotao
1) "fengjie"
2) "tangwei"
3) "liuyifei"
4) "bingbing"
5) "ruhua"
6) "feifei"
7) "baby"
8) "songhuiqiao"
9) "furong"
10) "yangmi"
sortedSet(有序集合)数据结构
sortedSet图示
sortedset中存储的成员都有一个附带的分数值
而redis就可以根据分数来对成员进行各种排序(正序、倒序)
sortedSet存储内容示意图:
SortedSet功能演示
往redis库中插入一条sortedset数据
redis 127.0.0.1:6379> zadd nansheng:yanzhi:bang 70 liudehua 90 huangbo 100 weixiaobao 250 yangwei 59 xiaotao
(integer) 5
从sortedset中查询有序结果
#正序结果
redis 127.0.0.1:6379> zrange nanshen:yanzhi:bang 0 4
1) "xiaotao"
2) "liudehua"
3) "huangbo"
4) "weixiaobao"
5) "yangwei"
#倒序结果
redis 127.0.0.1:6379> zrevrange nanshen:yanzhi:bang 0 4
1) "yangwei"
2) "weixiaobao"
3) "huangbo"
4) "liudehua"
5) "xiaotao"
查询某个成员的名次
#在正序榜中的名次
redis 127.0.0.1:6379> zrank nanshen:yanzhi:bang xiaotao
(integer) 0
#在倒序榜中的名次
redis 127.0.0.1:6379> zrevrank nanshen:yanzhi:bang xiaotao
(integer) 4
修改成员的分数
redis 127.0.0.1:6379> zincrby nanshen:yanzhi:bang 300 xiaotao
"359"
redis 127.0.0.1:6379> zrevrank nanshen:yanzhi:bang xiaotao
(integer) 0
Redis应用案例(1)
案例:
Lol盒子英雄数据排行榜:
1、 在redis中需要一个榜单所对应的sortedset数据
2、 玩家每选择一个英雄打一场游戏,就对sortedset数据的相应的英雄分数+1
3、 Lol盒子上查看榜单时,就调用zrange来看榜单中的排序结果
Redis应用案例(2)
实现步骤:
1、 每来一个用户创建购物车,就对购物车中的每一件商品在redis中插入一条以商品名称为key的sortedset,成员为同时出现在购物车中的其他商品,分数为1
2、 每新产生一个购物车,就对车中的商品更新redis中的sortedset,将同时出现的商品的分数增1
3、 推荐时,用户放入一件商品到购物车,则从这件商品对应的sortedset中查询分数最高的同现商品,推荐给该用户。