【Redis】redis实例
来源:互联网 发布:dd3000软件 编辑:程序博客网 时间:2024/05/20 14:28
1、Redis和nosql简介,api调用
14.1/ nosql介绍
NoSQL:一类新出现的数据库(not only sql),它的特点:
1、 不支持SQL语法
2、 存储结构跟传统关系型数据库中的那种关系表完全不同,nosql中存储的数据都是KV形式
3、 NoSQL的世界中没有一种通用的语言,每种nosql数据库都有自己的api和语法,以及擅长的业务场景
4、 NoSQL中的产品种类相当多:
a) Mongodb 文档型nosql数据库,擅长做CMS系统(内容管理系统)
b) Redis 内存数据库,数据结构服务器,号称瑞士军刀(精巧),只要你有足够的想象力,它可以还给你无限惊喜
c) Hbase hadoop生态系统中原生的一种nosql数据库,重量级的分布式nosql数据库,用于海量数据的场景
d) Cassandra hadoop生态系统中原生的一种分布式nosql数据库,后起之秀
NoSQL和SQL数据库的比较:
1、适用场景不同:sql数据库适合用于关系特别复杂的数据查询场景,nosql反之
2、“事务”特性的支持:sql对事务的支持非常完善,而nosql基本不支持事务
3、两者在不断地取长补短,呈现融合趋势
14.2/ redis介绍
14.2.1 简述
Redis是一个高性能的kv对缓存和内存数据库(存的不像MySQL那样的表)
Redis的存储结构就是key-value,形式如下:
注: redis中的value内部可以支持各种数据结构类型,比如可以存入一个普通的string,还可以存list,set,hashmap,sortedSet(有序的set)
14.2.2 redis应用场景
A、用来做缓存(ehcache/memcached)——redis的所有数据是放在内存中的(内存数据库)
B、可以在某些特定应用场景下替代传统数据库——比如社交类的应用
C、在一些大型系统中,巧妙地实现一些特定的功能:session共享、购物车
只要你有丰富的想象力,redis可以用在可以给你无限的惊喜…….
14.2.3 redis的特性
1、redis数据访问速度快(数据在内存中)
2、redis有数据持久化机制(持久化机制有两种:1、定期将内存数据dump到磁盘;2、aof(append only file)持久化机制——用记日志的方式记录每一条数据更新操作,一旦出现灾难事件,可以通过日志重放来恢复整个数据库)
3、redis支持集群模式(容量可以线性扩展)
4、redis相比其他缓存工具(ehcach/memcached),有一个鲜明的优势:支持丰富的数据结构
14.3.Redis的api客户端连接
新建一个maven工程,导入jedis的maven依赖坐标
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.7.2</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
然后写一个类用来测试服务器跟客户端的连通性:
public class RedisClientConnectionTest {
public static void main(String[] args) {
// 构造一个redis的客户端对象
Jedis jedis = new Jedis("pinshutang.zicp.net", 6379);
String ping = jedis.ping();
System.out.println(ping);
}
}
15、Redis数据功能(String类型的数据处理)
15.1 String类型的数据
(常作为缓存使用)
1/插入和读取一条string类型的数据
redis notrue-centos:6379> set sessionid-0001 "zhangsan"
OK
redis notrue-centos:6379> get sessionid-0001
"zhangsan"
2/对string类型数据进行增减(前提是这条数据的value可以看成数字)
192.168.106.80:6379> DECR key
(integer) -1
192.168.106.80:6379> DECR key
(integer) -2
192.168.106.80:6379> DECR key
(integer) -3
192.168.106.80:6379> INCR key
(integer) -2
192.168.106.80:6379> INCR key
(integer) -1
192.168.106.80:6379> DECRBY key 4
(integer) -5
192.168.106.80:6379> DECRBY key -7
(integer) 2
192.168.106.80:6379> INCRBY key 2
(integer) 4
192.168.106.80:6379> INCRBY key -9
(integer) -5
3/一次性插入或者获取多条数据
192.168.106.80:6379> MSET key1 1 key2 2 key3 3
OK
192.168.106.80:6379> MGET key1 key2 key3
1) "1"
2) "2"
3) "3"
4/在插入一条string类型数据的同时为它指定一个存活期限
setex key seconds value
例如:
# bancao这条数据就只会存活10秒钟,过期会被redis自动清除
192.168.106.80:6379> setex bancao 10 testvalue
OK
192.168.106.80:6379> get bancao
"testvalue"
192.168.106.80:6379> get bancao
"testvalue"
192.168.106.80:6379> get bancao
(nil)
192.168.106.80:6379> get bancao
(nil)
案例:
其中maven项目的pom文件的内容如下:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn.toto.redis</groupId>
<artifactId>redistest</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<!-- <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId>
<version>2.7.2</version> <type>jar</type> <scope>compile</scope> </dependency> -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.8.0</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.7</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
代码:
package cn.toto.redis.client;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import org.junit.Before;
import org.junit.Test;
import com.google.gson.Gson;
import cn.toto.redis.bean.ProductInfo;
import redis.clients.jedis.Jedis;
public class StringStructureData {
private Jedis jedis = null;
@Before
public void init() {
//这里的是hadoop2可以用ip地址替换
jedis = new Jedis("hadoop2",6379);
}
@Test
public void testString() {
jedis.set("user02:name", "ruhua");
jedis.set("user03:name", "滑板鞋");
String u02 = jedis.get("user02:name");
String u03 = jedis.get("user03:name");
System.out.println(u02);
System.out.println(u03);
}
@Test
public void testObjectCache() throws Exception {
ProductInfo p = new ProductInfo();
p.setName("username");
p.setDescription("备注信息");
p.setCatelog("unknow");
p.setPrice(10.8);
//将对象序列化成字节数组
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);
//从对象读取流中取出对象
ProductInfo pResp = (ProductInfo) oi.readObject();
System.out.println(pResp);
}
@Test
public void testObjectToJsonCache() {
ProductInfo p = new ProductInfo();
p.setName("ABC");
p.setDescription("刘亦菲专用");
p.setCatelog("化妆品");
p.setPrice(10.8);
//利用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);
}
}
16、List数据结构(及Java调用处理)
16.1 List图示
16.2 List功能演示
#从头部(左边)插入数据
redis>LPUSH key value1 value2 value3
#从尾部(右边)插入数据
redis>RPUSH key value1 value2 value3
#读取list中指定范围的values
redis>LRANGE key start end
redis> lrange task-queue 0 -1 读取整个list
#从头部弹出一个元素
LPOP key
#从尾部弹出一个元素
RPOP key
#从一个list的尾部弹出一个元素插入到另一个list
RPOPLPUSH key1 key2 ## 这是一个原子性操作
例如下面的案例:
#从头部(左边)插入数据
192.168.106.81:6379> lpush task task0 task1 task2
(integer) 3
192.168.106.81:6379> lrange task 0 2
1) "task2"
2) "task1"
3) "task0"
192.168.106.81:6379> lrange task 0 -2
1) "task2"
2) "task1"
192.168.106.81:6379> lrange task 0 -1
1) "task2"
2) "task1"
3) "task0"
#从尾部(右边)插入数据
192.168.106.81:6379> rpush ids id0 id1 id2
(integer) 3
192.168.106.81:6379> lrange ids 0 -1
1) "id0"
2) "id1"
3) "id2"
192.168.106.81:6379> lpop ids
"id0"
192.168.106.81:6379> lpop ids
"id1"
192.168.106.81:6379> rpop task
"task0"
192.168.106.81:6379> rpoplpush task ids
"task1"
192.168.106.81:6379> lrange ids 0 -1
1) "task1"
2) "id2"
192.168.106.81:6379>
16.3 List的应用案例demo
1 需求描述
任务调度系统:
生产者不断产生任务,放入task-queue排队
消费者不断拿出任务来处理,同时放入一个tmp-queue暂存,如果任务处理成功,则清除tmp-queue,否则,将任务弹回task-queue
2 代码实现
1/生产者
——模拟产生任务
package cn.toto.redis.productAndCustomer;
import java.util.Random;
import java.util.UUID;
import redis.clients.jedis.Jedis;
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("hadoop3", 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 (Exception e) {
e.printStackTrace();
}
}
}
}
2/消费者
——模拟处理任务,并且管理暂存队列
package cn.toto.redis.productAndCustomer;
import java.util.Random;
import redis.clients.jedis.Jedis;
public class TaskConsumer {
public static void main(String[] args) {
Jedis jedis = new Jedis("hadoop3",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 (Exception e) {
e.printStackTrace();
}
}
}
}
上述机制是一个简化版,真实版的任务调度系统会更加复杂,如下所示:
(增加了一个专门用来管理暂存队列的角色,以便就算消费者程序失败退出,那些处理失败的任务依然可以被弹回task-queue)
17、Hash数据结构
17.1 Hash图示
Redis中的Hashes类型可以看成具有String Key和String Value的map容器
17.2 Hash功能演示
1、往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库中就形成了这样一条数据:
2、从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"
18、Set数据结构功能
集合的特点:无序、无重复元素
1、 插入一条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>
2、获取一条set数据的所有members
redis 127.0.0.1:6379> smembers frieds:zhangsan
1) "fengjie"
2) "baby"
3) "furong"
4) "bingbing"
5) "tingting"
6) "ruhua"
3、判断一个成员是否属于某条指定的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
4、求两个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"
5、 求交集,求并集
#求交集
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"
案例代码:
package cn.toto.redis.hashcart;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.junit.Before;
import org.junit.Test;
import redis.clients.jedis.Jedis;
public class BuyCartServiceImpl {
private Jedis jedis = null;
private static final String CART_PRIFIX = "cart:";
@Before
public void init() {
jedis = new Jedis("hadoop3",6379);
}
/**
* 添加商品到购物车
*/
@Test
public void testAddItemToCart() {
jedis.hset(CART_PRIFIX + "user02", "上衣", "2");
jedis.hset(CART_PRIFIX + "user02", "鞋子", "1");
jedis.hset(CART_PRIFIX + "user02", "毛衣", "3");
jedis.hset(CART_PRIFIX + "user02", "羽绒服", "4");
jedis.close();
}
/**
* 查看购物车信息,当本类中的其它单元测试执行完成之后,可以通过执行这个单元测试方法查看内容
* @author toto
* @date 2017-1-14
* @note begin modify by 涂作权 2017-1-14 原始创建
*/
@Test
public void testGetCartInfo() {
Map<String, String> cart = jedis.hgetAll(CART_PRIFIX + "user02");
Set<Entry<String, String>> entrySet = cart.entrySet();
for(Entry<String, String> ent : entrySet) {
System.out.println(ent.getKey() + ":" + ent.getValue());
}
jedis.close();
}
/**
* 编辑缓存中的内容
*/
@Test
public void editCart() {
//给蜡烛商品项的数量加1
jedis.hincrBy(CART_PRIFIX + "user02", "羽绒服", 1);
jedis.close();
}
/**
* 删除内存中上衣这个内容
*/
@Test
public void delItemFromCart() {
jedis.hdel(CART_PRIFIX + "user02", "上衣");
jedis.close();
}
}
生产者消费者:
生产者:
package cn.toto.redis.listqueue;
import java.util.Random;
import java.util.UUID;
import redis.clients.jedis.Jedis;
public class TaskProducer {
private static Jedis jedis = null;
public static void main(String[] args) throws Exception {
jedis = new Jedis("hadoop2",6379);
Random random = new Random();
while(true) {
int nextInt = random.nextInt(1000);
Thread.sleep(1000 + nextInt);
//生成一个任务的id
String taskid = UUID.randomUUID().toString();
jedis.lpush("task-queue", taskid);
System.out.println("生成了一个任务:" + taskid);
}
}
}
消费者:
package cn.toto.redis.listqueue;
import java.util.Random;
import redis.clients.jedis.Jedis;
/**
* @brief TaskProcessor.java 任务处理模块
*/
public class TaskProcessor {
private static Jedis jedis = null;
public static void main(String[] args) throws Exception {
Random random = new Random();
jedis = new Jedis("hadoop2",6379);
while(true) {
Thread.sleep(1500);
//从任务队列中取出一个任务,同时放入到暂存队列中
String taskid = jedis.rpoplpush("task-queue", "tmp-queue");
//处理任务
if (random.nextInt(19) % 9 == 0) {
//模拟失败
//失败的情况下,需要将任务从暂存队列弹回任务队列
jedis.rpoplpush("tmp-queue", "task-queue");
System.out.println("该任务处理失败:" + taskid);
} else {
//模拟成功
//成功的情况下,只需要将任务从暂存队列清除
jedis.rpop("tmp-queue");
System.out.println("任务处理成功:" + taskid);
}
}
}
}
Set的案例:
package cn.toto.redis.set;
import java.util.Set;
import redis.clients.jedis.Jedis;
public class TestSet {
public static void main(String[] args) {
Jedis jedis = new Jedis("hadoop2",6379);
jedis.sadd("friends:shuangshuang", "dandan","lulu","lili");
jedis.sadd("friends:laobi", "laowang","laodu","laoli","lili","lulu");
//判断一个成员是否属于指定的集合
Boolean isornot = jedis.sismember("friends:laobi", "shuangshuang");
System.out.println(isornot);
//求两个集合的差并交集
Set<String> ssDiffbb = jedis.sdiff("friends:shuangshuang","friends:laobi");
Set<String> ssUnionbb = jedis.sunion("friends:shuangshuang","friends:laobi");
Set<String> ssInterbb = jedis.sinter("friends:shuangshuang","friends:laobi");
//打印结果
for (String mb : ssUnionbb) {
System.out.println(mb);
}
}
}
19、sortedSet(有序集合)数据结构
19.1 sortedSet图示
sortedset中存储的成员都有一个附带的分数值
而redis就可以根据分数来对成员进行各种排序(正序、倒序)
1、 sortedSet存储内容示意图:
19.2 SortedSet功能演示
1、往redis库中插入一条sortedset数据
redis 127.0.0.1:6379> zadd nansheng:yanzhi:bang 70 liudehua 90 huangbo 100 weixiaobao 250 yangwei 59 xiaotao
(integer) 5
2、 从sortedset中查询有序结果
#正序结果
redis 127.0.0.1:6379> zrange nansheng: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"
3、 查询某个成员的名次
#在正序榜中的名次
redis 127.0.0.1:6379> zrank nansheng:yanzhi:bang xiaotao
(integer) 0
#在倒序榜中的名次
redis 127.0.0.1:6379> zrevrank nansheng:yanzhi:bang xiaotao
(integer) 4
4、修改成员的分数
redis 127.0.0.1:6379> zincrby nansheng:yanzhi:bang 300 xiaotao
"359"
redis 127.0.0.1:6379> zrevrank nansheng:yanzhi:bang xiaotao
(integer) 0
案例:
下面的这个先运行:
package cn.toto.redis.sortedset;
import java.util.Random;
import redis.clients.jedis.Jedis;
public class LolBoxPlayer {
public static void main(String[] args) throws Exception {
Jedis jedis = new Jedis("hadoop2",6379);
Random random = new Random();
String[] heros = {"易大师","德邦","剑姬","盖伦","阿卡丽","金克斯","提莫","猴子","亚索"};
while(true) {
int index = random.nextInt(heros.length);
//选择一个英雄
String hero = heros[index];
//开始玩游戏
Thread.sleep(1000);
//给集合中的该英雄的出场次数加1
//第一次添加的时候,集合不存在,zincrby方法会创建
jedis.zincrby("hero:ccl:phb", 1, hero);
System.out.println(hero + "出场了......");
}
}
}
下面的这个后运行:
package cn.toto.redis.sortedset;
import java.util.Set;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Tuple;
public class LolBoxViewer {
public static void main(String[] args) throws Exception {
Jedis jedis = new Jedis("hadoop2",6379);
int i = 1;
while(true) {
//每隔3秒查看一次榜单
Thread.sleep(3000);
System.out.println("第" + i + "次查看榜单-----------");
//从redis中查询榜单的前N名
Set<Tuple> topHeros = jedis.zrevrangeWithScores("hero:ccl:phb", 0, 4);
for (Tuple t : topHeros) {
System.out.println(t.getElement() + " " + t.getScore());
}
i++;
System.out.println("");
System.out.println("");
System.out.println("");
}
}
}
- 【Redis】redis实例
- redis 实例
- redis实例
- Redis---------springboot整合Redis实例
- redis入门实例
- 单机redis 主从实例
- redis php 实例一
- Redis-API实例
- redis使用实例
- Nginx+Lua+Redis实例
- redis php 实例
- Redis连接实例
- redis php 实例一
- redis多实例部署
- redis php 实例一
- redis php 实例二
- C++使用redis实例
- redis 主从配置实例
- antlr.collections.AST.getLine()I异常
- head、tail 命令和实时(real-time)更新
- malloc和free
- python3学习--3列表与元组
- Codeforces Round #416 C. Vladik and Memorable Trip (DP)题解
- 【Redis】redis实例
- python函数的作用域和名称空间
- 激光切割机上的步进电机和伺服电机有什么区别
- LeetCode 167. Two Sum II
- 基于proteus的51单片机仿真实例七十六、8-3编码芯片74HC148应用实例
- 动态生成XML文件
- 卡牌伎俩(Card Trick)
- 什么是Solr
- Web网站评论功能数据库设计和开发