Redis学习结构

 Redis基础

Redis概述

Redis是一个开源,先进的key-value存储,并用于构建高性能,可扩展的应用程序的完美解决方案。

Redis从它的许多竞争继承来的三个主要特点:

ØRedis数据库完全在内存中,使用磁盘仅用于持久性。

Ø相比许多键值数据存储,Redis拥有一套较为丰富的数据类型。

ØRedis可以将数据复制到任意数量的从服务器。

Redis 优势

Ø异常快速:Redis的速度非常快,每秒能执行约11万集合,每秒约81000+条记录

Ø支持丰富的数据类型:String(字符串)、List(列表)、set(集合)、Sort Set(有序集合)、Hash(散列数据)

Ø操作都是原子性:所有Redis操作是原子的,这保证了如果两个客户端同时访问的Redis服务器将获得更新后的值。

Ø多功能实用工具:Redis是一个多实用的工具,可以在多个用例如缓存,消息,队列使用(Redis原生支持发布/订阅),任何短暂的数据,应用程序,如Web应用程序会话,网页命中计数等。

        Redis 部署

参考:https://blog.csdn.net/CherrieZhang/article/details/77677516

   Redis 持久化

两种持久化方案:RDB和AOF

1)RDB方式按照一定的时间间隔对数据集创建基于时间点的快照

2)AOF方式记录Server收到的写操作到日志文件,在Server重启时通过回放这些写操作来重建数据集。

该方式类似于MySQL中基于语句格式的binlog。当日志变大时Redis可在后台重写日志。

•RDB持久化配置

默认情况下,Redis保存数据集快照到磁盘,名为dump.rdb的二进制文件。可以设置让Redis在N秒内至少有M次数据集改动时保存数据集,或者你也可以手动调用SAVE或者BGSAVE命令。 
例如,这个配置会让Redis在每个60秒内至少有1000次键改动时自动转储数据集到磁盘   save 60 1000

•AOF持久化配置

1)修改redis.config配置文件,找到appendonly。默认是appendonly no。改成appendonly yes

2)再找到appendfsync 。默认是 appendfsync everysec

appendfsync always

#每次收到写命令就立即强制写入磁盘,最慢的,但是保证完全的持久化,不推荐使用

appendfsync everysec

#每秒钟强制写入磁盘一次,在性能和持久化方面做了很好的折中,推荐

appendfsync no

#完全依赖os,性能最好,持久化没保证

Jedis

Jedis是Java代码操控Redis的一个客户端工具。

Jedis API:https://blog.csdn.net/zhangguanghui002/article/details/78770071

Jedis池相关:

package redis.other;import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;/*** Describe: 请补充类描述*/
public class MyJedisPool {// jedis池public static JedisPool pool;// 静态代码初始化池配置static {//change "maxActive" -> "maxTotal" and "maxWait" -> "maxWaitMillis" in all examplesJedisPoolConfig config = new JedisPoolConfig();//控制一个pool最多有多少个状态为idle(空闲的)的jedis实例。config.setMaxIdle(5);//控制一个pool可分配多少个jedis实例,通过pool.getResource()来获取;//如果赋值为-1,则表示不限制;如果pool已经分配了maxActive个jedis实例,则此时pool的状态为exhausted(耗尽)。//在borrow一个jedis实例时,是否提前进行validate操作;如果为true,则得到的jedis实例均是可用的;config.setMaxTotal(1000 * 100);//表示当borrow(引入)一个jedis实例时,最大的等待时间,如果超过等待时间,则直接抛出JedisConnectionException;config.setMaxWaitMillis(5);config.setTestOnBorrow(true);config.setTestOnReturn(true);try {//如果你遇到 java.net.SocketTimeoutException: Read timed out exception的异常信息//请尝试在构造JedisPool的时候设置自己的超时值. JedisPool默认的超时时间是2秒(单位毫秒)pool = new JedisPool(config, "127.0.0.1", 6379, 20);} catch (Exception e) {throw new RuntimeException("redis 连接池初始化失败!");}}public static void main(String[] args) {// 从jedis池中获取一个jedis实例Jedis jedis = MyJedisPool.pool.getResource();// 添加key-value对象,如果key对象存在就覆盖该对象jedis.set("name", "maoxiangyi");jedis.set("company", "aaa");// 查取key的value值,如果key不存在返回nullString name = jedis.get("name");String company = jedis.get("company");System.out.println(company + ":" + name);// 删除key-value对象,如果key不存在则忽略此操作jedis.del("name");// 判断key是否存在,不存在返回false存在返回truejedis.exists("name");//关闭jedis链接,自动回收jedis.close();}
}

String

先讲个面试题吧:Redis对int类型数值进行加1操作如何实现?

我们知道Redis数据类型中没有int的,解释Redis数字操作:https://blog.csdn.net/chengqiuming/article/details/79118084

String类型基本操作:

package redis.string;import redis.clients.jedis.Jedis;import java.util.List;/*** Describe: 请补充类描述*/
public class StringMain {public static void main(String[] args) throws InterruptedException {//创建Jedis客户端Jedis jedis = new Jedis("127.0.0.1", 6379);//操作一个String字符串jedis.set("name", "liudehua"); //插入一个名字,叫做刘德华System.out.println(jedis.get("name")); //读取一个名字//对string类型数据进行增减,前提是kv对应的值是数字jedis.set("age", "17");//给用户刘德华设置年龄,17岁jedis.incr("age");//让用户刘德华年龄增加一岁System.out.println(jedis.get("age")); //打印结果 18jedis.decr("age");//让刘德华年轻一岁System.out.println(jedis.get("age"));//在18的基础上,减一岁,变回17//一次性插入多条数据 。为江湖大侠设置绝杀技能jedis.mset("AAA", "Mysql数据库的操作", "BBB", "熟悉LINXU操作系统", "CCC", "熟悉SSH、SSM框架及配置", "DDD", "熟悉Spring框架,mybatis框架,Spring IOC MVC的整合,Spring和Mybatis的整合");List<String> results = jedis.mget("AAA", "BBB", "CCC", "DDD");for (String value : results) {System.out.println(value);}//设置字段的自动过期jedis.setex("wumai", 10, "我们活在仙境中"); //让仙境保持10秒钟while (jedis.exists("wumai")) {System.out.println("真是天上人间呀!");Thread.sleep(1000);}System.out.println();//对已经存在的字段设置过期时间jedis.set("wumai", "我们活在仙境中");jedis.expire("wumai", 10); //让天上人间的感觉保持更长的时间while (jedis.exists("wumai")) {System.out.println("真是天上人间呀!");Thread.sleep(1000);}}
}

对象的保存:

package redis.string;import com.google.gson.Gson;
import org.junit.Test;
import redis.clients.jedis.Jedis;import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Map;/*** Describe: 保存Product对象到redis中*/
public class ProductService {@Testpublic void saveProduct2Redis() throws Exception {//初始化刘德华的基本信息Person person = new Person("刘德华", 17);//将刘德华的信息保存到Redis中Jedis jedis = new Jedis("127.0.0.1", 6379);//直接保存对象的toString方法,这种方法不反序列化对象jedis.set("user:liudehua:str", person.toString());System.out.println(jedis.get("user:liudehua:str"));//保存序列化之后的对象jedis.set("user:liudehua:obj".getBytes(), getBytesByProduct(person));byte[] productBytes = jedis.get("user:liudehua:obj".getBytes());Person pByte = getProductByBytes(productBytes);System.out.println(pByte.getName()+"  " +pByte.getAge());//保存Json化之后的对象jedis.set("user:liudehua:json", new Gson().toJson(person));String personJson = jedis.get("user:liudehua:json");Person pjson = new Gson().fromJson(personJson, Person.class);System.out.println(pjson.getName()+"  "+ pjson.getAge());}/*** 从字节数组中读取Java对象** @param productBytes* @return* @throws Exception*/public Person getProductByBytes(byte[] productBytes) throws Exception {ByteArrayInputStream byteInputStream = new ByteArrayInputStream(productBytes);ObjectInputStream objectInputStream = new ObjectInputStream(byteInputStream);return (Person) objectInputStream.readObject();}/*** 将对象转化成Byte数组** @param product* @return* @throws Exception*/public byte[] getBytesByProduct(Person product) throws Exception {ByteArrayOutputStream ba = new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(ba);oos.writeObject(product);oos.flush();return ba.toByteArray();}
}

应用场景:String数据类型实现计数功能

因为Redis都是原子性操作,可应用于多线程情景下实现计数功能。

package redis.string;import redis.clients.jedis.Jedis;import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;/*** Describe: 擂台比武*/
public class Counter {/*** 计算 武林大会 三个擂台的比武次数** @param args*/public static void main(String[] args) {//创建一个固定大小的线程池,3个擂台ExecutorService executorService = Executors.newFixedThreadPool(10);//擂台1:天龙八部executorService.submit(new Arena("biwu:totalNum","天龙八部"));//擂台2:神雕侠侣executorService.submit(new Arena("biwu:totalNum","神雕侠侣"));//擂台3:倚天屠龙记executorService.submit(new Arena("biwu:totalNum","倚天屠龙记"));//报幕人员,一秒统计一次总共比了多少场executorService.submit(new BaoMu("biwu:totalNum"));}
}package redis.string;import redis.clients.jedis.Jedis;import java.util.Random;/*** Describe: 擂台*/
public class Arena implements Runnable {private Random random = new Random();private String redisKey;private Jedis jedis;private String arenaName;public Arena(String redisKey, String arenaName) {this.redisKey = redisKey;this.arenaName = arenaName;}public void run() {jedis = new Jedis("127.0.0.1",6379);String[] daxias = new String[]{"郭靖", "黄蓉", "令狐冲", "杨过", "林冲","鲁智深", "小女龙", "虚竹", "独孤求败", "张三丰", "王重阳", "张无忌", "王重阳", "东方不败", "逍遥子", "乔峰", "虚竹", "段誉", "韦小宝", "王语嫣", "周芷若", "峨眉师太", "慕容复"};while (true) {try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}int p1 = random.nextInt(daxias.length);int p2 = random.nextInt(daxias.length);while (p1 == p2) { //如果两个大侠出场名字一样,换一个人p2 = random.nextInt(daxias.length);}System.out.println("在擂台" + arenaName + "上   " + daxias[p1] + " VS " + daxias[p2]);jedis.incr(redisKey);}}
}package redis.string;import redis.clients.jedis.Jedis;import java.util.concurrent.Callable;/*** Describe: 报幕人员*/
public class BaoMu implements Runnable {private Jedis jedis;private String redisKey;public BaoMu(String redisKey) {this.redisKey = redisKey;}public void run() {jedis = new Jedis("127.0.0.1",6379);while (true) {try {Thread.sleep(1000);System.out.println("===================当前总共比武次数为:" + jedis.get(redisKey));} catch (Exception e) {System.out.println("擂台被损坏..."+e);}}}
}

Hash数据类型

Hash基本操作,区别Redis的key和Hash的key不是同一个概念

package redis.map;import redis.clients.jedis.Jedis;import java.util.List;
import java.util.Map;
import java.util.Set;/*** Describe: 请补充类描述*/
public class MapMain {public static void main(String[] args) {Jedis jedis = new Jedis("127.0.0.1", 6379);jedis.del("daxia:jingzhongyue");//创建一个对象jedis.hset("daxia:jingzhongyue", "姓名", "不为人知");jedis.hset("daxia:jingzhongyue", "年龄", "18");jedis.hset("daxia:jingzhongyue", "技能", "杀人于无形");//打印对象Map<String, String> jingzhongyue = jedis.hgetAll("daxia:jingzhongyue");System.out.println("hgetAll  大侠的基本信息:");for (Map.Entry entry : jingzhongyue.entrySet()) {System.out.println(entry.getKey() + ":-----------------" + entry.getValue());}System.out.println();//获取大侠的所有字段信息Set<String> fields = jedis.hkeys("daxia:jingzhongyue");System.out.println("hkeys  ");for (String field : fields) {System.out.print(field + "  ");}System.out.println();//获取大侠的所有值的信息List<String> values = jedis.hvals("daxia:jingzhongyue");System.out.println("hvals " );for (String value : values) {System.out.print(value + "  ");}System.out.println();//值获取大侠的年龄,进行研究String age = jedis.hget("daxia:jingzhongyue", "年龄");System.out.println("对大侠的年龄有质疑:" + age);//给大侠的年龄增加十岁jedis.hincrBy("daxia:jingzhongyue", "年龄", 10);System.out.println("经过验核,大侠的实际年龄为:" + jedis.hget("daxia:jingzhongyue", "年龄"));System.out.println();//删除大侠的姓名jedis.hdel("daxia:jingzhongyue", "姓名");for (Map.Entry entry : jedis.hgetAll("daxia:jingzhongyue").entrySet()) {System.out.println(entry.getKey() + ":" + entry.getValue());}}
}

应用场景:Hash数据类型实现购物车,一个购物车对应一个Map集合。

package redis.map;import com.google.gson.Gson;
import redis.clients.jedis.Jedis;
import redis.string.StringMain;import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;/*** Describe: 购物车*/
public class Cart {private Jedis jedis;public Cart() {jedis = new Jedis("127.0.0.1", 6379);}public Cart(Jedis jedis) {this.jedis = jedis;}/*** 修改购物车中的商品** @param userName  用户名* @param productId 商品编号* @param num       操作商品的数量*/public void updateProduct2Cart(String userName, String productId, int num) {jedis.hincrBy("shop:cart:" + userName, productId, num);}/*** 获取用户购物车的商品信息** @param userName* @return*/public List<Product> getProductsByUserName(String userName) {List<Product> products = new ArrayList<Product>();Map<String, String> productMap = jedis.hgetAll("shop:cart:" + userName);if (productMap == null || productMap.size() == 0) {return products;}for (Map.Entry entry : productMap.entrySet()) {Product product = new Product();product.setId((String) entry.getKey());//获取用户购物车中商品的编号int num = Integer.parseInt((String) entry.getValue());//获取用户购物车中商品的数量product.setNum(num > 0 ? num : 0);//如果商品数量大于0,返回正常的值,如果商品小于0,初始化为0complementOtherField(product);//补全商品的其他信息products.add(product);}return products;}private void complementOtherField(Product product) {String productId = product.getId();String productJsonStr = jedis.get("shop:product:" + productId);Product productJson = (Product) new Gson().fromJson(productJsonStr, Product.class);if (productJson != null) {product.setName(productJson.getName());product.setPrice(productJson.getPrice());}}public static void main(String[] args) {//初始化商品的信息initData();//创建购物车对象Cart cart = new Cart();//创建用户String userName = "liudehua";//往用户购物车中添加商品cart.updateProduct2Cart(userName, "1645080454", 10);cart.updateProduct2Cart(userName, "1788744384", 1000);cart.updateProduct2Cart(userName, "1645139266", -1000);//打印当前用户的购物车信息List<Product> products = cart.getProductsByUserName(userName);for (Product product : products) {System.out.println(product);}}private static void initData() {System.out.println("========================初始化商品信息===========================");Jedis jedis = new Jedis("127.0.0.1", 6379);//准备数据Product product1 = new Product("1645139266", "战地鳄2015秋冬新款马甲可脱卸帽休闲时尚无袖男士羽绒棉外套马甲", new BigDecimal("168"));Product product2 = new Product("1788744384", "天乐时 爸爸装加厚马甲秋冬装中年大码男士加绒马夹中老年坎肩老年人", new BigDecimal("40"));Product product3 = new Product("1645080454", "战地鳄2015秋冬新款马甲可脱卸帽休闲时尚无袖男士羽绒棉外套马甲", new BigDecimal("230"));//将数据写入到Redisjedis.set("shop:product:" + product1.getId(), new Gson().toJson(product1));jedis.set("shop:product:" + product2.getId(), new Gson().toJson(product2));jedis.set("shop:product:" + product3.getId(), new Gson().toJson(product3));//打印所有产品信息Set<String> allProductKeys = jedis.keys("shop:product:*"); //获取所有的商品信息for (String key : allProductKeys) {String json = jedis.get(key);Product product = new Gson().fromJson(json, Product.class);//从字符串中解析出对象System.out.println(product);}System.out.println("========================用户购物车信息如下===========================");}
}package redis.map;import java.math.BigDecimal;/*** Describe:商品类*/
public class Product {private String id;//商品编号private String name;//商品名称private BigDecimal price;//商品价格private int num;//商品数量public Product() {}public Product(String id, String name, BigDecimal price) {this.id = id;this.name = name;this.price = price;}public String getId() {return id;}public void setId(String id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public BigDecimal getPrice() {return price;}public void setPrice(BigDecimal price) {this.price = price;}public int getNum() {return num;}public void setNum(int num) {this.num = num;}@Overridepublic String toString() {return "Product{" +"id='" + id + '\'' +", name='" + name + '\'' +", price=" + price +", num=" + num +'}';}
}

List

List基本操作:List左右端均可以操作,相当于双向队列。

package redis.list;import redis.clients.jedis.BinaryClient;
import redis.clients.jedis.Jedis;import java.util.List;/*** 天龙八部外传-麦当劳风云*/
public class ListMain {public static void main(String[] args) {//创建一个Redis的客户端Jedis jedis = new Jedis("127.0.0.1", 6379);jedis.del("柜台1");//鸠摩智,虚竹,段誉,乔峰 排队买肯德基jedis.lpush("柜台1", "乔峰", "段誉", "虚竹", "鸠摩智");for (String name : jedis.lrange("柜台1", 0, -1)) {System.out.print(name + "  ");}System.out.println();//剧情:新来一个人 王语嫣,插队,到第一名。jedis.rpush("柜台1", "王语嫣");List<String> list = jedis.lrange("柜台1", 0, -1);for (String name : list) {System.out.print(name + "  ");}System.out.println();//剧情:鸠摩智很不高兴,正好慕容复来了,说:慕容兄,你插我前面jedis.linsert("柜台1", BinaryClient.LIST_POSITION.AFTER, "鸠摩智", "慕容复");List<String> list1 = jedis.lrange("柜台1", 0, -1);for (String name : list1) {System.out.print(name + "  ");}System.out.println();//剧情:看到慕容复插队大家很生气,正好阿紫和游坦之。让阿紫和游坦之依次插到虚竹的后面jedis.linsert("柜台1", BinaryClient.LIST_POSITION.BEFORE, "虚竹", "阿紫");jedis.linsert("柜台1", BinaryClient.LIST_POSITION.BEFORE, "阿紫", "游坦之");List<String> list2 = jedis.lrange("柜台1", 0, -1);for (String name : list2) {System.out.print(name + "  ");}System.out.println();//剧情:插队不文明,为了遏制这种不文明的现象,大决决定打一架。  鸠摩智被打跑了。jedis.lpop("柜台1");for (String name : jedis.lrange("柜台1", 0, -1)) {System.out.print(name + "  ");}System.out.println();//剧情:慕容复一看情况不好,以表哥的身份忽悠王语嫣,把王语嫣打伤。jedis.rpop("柜台1");for (String name : jedis.lrange("柜台1", 0, -1)) {System.out.print(name + "  ");}System.out.println();//剧情:在大家打架的时候,我偷偷插队,买了肯德基。jedis.rpush("柜台1", "井中月");for (String name : jedis.lrange("柜台1", 0, -1)) {System.out.print(name + "  ");}System.out.println();//剧情;等我买了肯德基,慕容复被打跑了jedis.lpop("柜台1");for (String name : jedis.lrange("柜台1", 0, -1)) {System.out.print(name + "  ");}System.out.println();//剧情:星宿老怪 突然来了,把 阿紫和游坦之同时弄走了。String result = jedis.ltrim("柜台1", 2, 5);if ("OK".equals(result)) {for (String name : jedis.lrange("柜台1", 0, -1)) {System.out.print(name + "  ");}}System.out.println("");//剧情:这时候,乔峰三人发现了我,与我大战三百回合,我全身而退String res = jedis.ltrim("柜台1", 0, 2);if ("OK".equals(res)) {for (String name : jedis.lrange("柜台1", 0, -1)) {System.out.print(name + "  ");}}}
}

应用场景:网络爬虫

package redis.list;import org.jsoup.Jsoup;
import org.jsoup.helper.StringUtil;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import redis.clients.jedis.Jedis;import java.util.Date;
import java.util.List;public class Crawler {//定义需要爬取的url listprivate static final String redisUrlsWillKey = "crawler:urls:will";//如果需要去重的话,可以使用set保存已经爬起过的urlpublic static void main(String[] args) throws Exception {//准备UrlString startUrl = "https://www.huxiu.com/article/259690.html";String domain = "http://www.huxiu.com/";//获取文章UrlgetUrls(startUrl, domain);//处理url,下载文章的内容并打印parserUrl();}private static void parserUrl() throws Exception {Jedis jedis = new Jedis("127.0.0.1", 6379);//从右边弹出一个urlwhile (true) {String url = jedis.rpop(redisUrlsWillKey);try {Article article = parser(url);System.out.println(article);} catch (Exception e) {
//                jedis.lpush(redisUrlsWillKey, url);}}}private static Article parser(String url) throws Exception {Document articleDocument = Jsoup.connect(url).get();Article article = new Article();// 封装作者的信息Elements author = articleDocument.getElementsByClass("author-name");article.setAuthor(StringUtil.isBlank(author.text()) ? "jingzhongyue": author.text());// 抽取文章日期Elements date = articleDocument.getElementsByClass("article-time");article.setDate(StringUtil.isBlank(date.text()) ? new Date(): DateUtil.getDate(date.text()));// 抽取文章标题Elements title = articleDocument.getElementsByTag("title");article.setTitle(title.text());// 抽取文章编号// http://www.huxiu.com/article/124698/1.htmlString id = url.substring(29);int index = id.indexOf("/");id = id.substring(0, index);article.setId(id);// 抽取文章正文StringBuffer stringBuffer = new StringBuffer();Elements contents = articleDocument.getElementsByAttribute("id");for (Element element : contents) {String idTag = element.attr("id");if ("article_content".equals(idTag)) {Elements childs = element.children();Elements pElements = childs.tagName("p");for (Element element2 : pElements) {stringBuffer.append(element2.text());}}}return article;}private static void getUrls(String startUrl, String domain) throws Exception {Jedis jedis = new Jedis("127.0.0.1", 6379);Document document = Jsoup.connect(startUrl).get();Elements elements = document.getElementsByAttribute("href");for (Element element : elements) {String endUrl = element.attr("href");if (endUrl.contains("article")) {String url = domain + endUrl;System.out.println(url);jedis.lpush(redisUrlsWillKey, url);}}}}

Set

Set基本操作:无序、无重复元素

package redis.set;import redis.clients.jedis.Jedis;import java.util.Set;/*** Describe: 请补充类描述*/
public class SetMain {public static void main(String[] args) {Jedis jedis = new Jedis("127.0.0.1", 6379);//河南武林人物登记表---杜绝冒名顶替的情况String[] daxias = new String[]{"郭靖", "黄蓉", "令狐冲", "杨过", "林冲","鲁智深", "小女龙", "虚竹", "独孤求败", "张三丰", "王重阳", "张无忌", "王重阳", "东方不败", "逍遥子", "乔峰", "虚竹", "段誉", "韦小宝", "王语嫣", "周芷若", "峨眉师太", "慕容复", "郭靖", "乔峰", "王重阳"};//创建并设置一个set的值jedis.sadd("biwu:dengji", daxias);//获取一个set中所有的元素Set<String> daxiaSet = jedis.smembers("biwu:dengji");for (String name : daxiaSet) {System.out.print(name + " ");  //set集合的特点:无序、无重复元素}System.out.println();//判断一个成员是否属于某条指定的set数据boolean isComing = jedis.sismember("biwu:dengji", "井中月"); //判断大侠井中月是否到来if (!isComing) {System.out.println("大侠 井中月尚未登记.");}//计算一个set中有多少元素long totalNum = jedis.scard("biwu:dengji");System.out.println("有" + totalNum + " 位大侠已经登记了!");System.out.println();//大侠井中月没有来,是因为报名参与另外一个会议 国际武林大会String[] daxiaArr = new String[]{"王语嫣", "周芷若", "峨眉师太", "慕容复","郭靖", "乔峰", "井中月"};jedis.sadd("guoji:dengji", daxiaArr); //国际武林大会登记表Set<String> xindaxias = jedis.smembers("guoji:dengji");for (String name : xindaxias) {System.out.print(name + "--- ");  //集合的特点:无序、无重复元素}System.out.println();//计算两个Set之间的交集Set<String> users = jedis.sinter("biwu:dengji", "guoji:dengji");for (String name : users) {System.out.print(name + " ");}System.out.println();//计算两个Set之间的并集users = jedis.sunion("biwu:dengji", "guoji:dengji");for (String name : users) {System.out.print(name + " ");}System.out.println();System.out.println("井中月出来了");//计算两个集合的差集users = jedis.sdiff("biwu:dengji", "guoji:dengji");for (String name : users) {System.out.print(name + " ");}System.out.println();System.out.println();//将两个集合计算出来的差集保存起来,升级为超级Vipjedis.sdiffstore("vipdaxia","biwu:dengji", "guoji:dengji");for (String name : jedis.smembers("vipdaxia")) {System.out.print(name + " ");}}
}

应用场景:通过对两个集合的操作计算订单浏览、下单、支付等转化率

package redis.set;import redis.clients.jedis.Jedis;import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.Set;/*** Describe: 请补充类描述*/
public class Transform {public static void main(String[] args) {Jedis jedis = new Jedis("127.0.0.1", 6379);//浏览某商品的用户jedis.sadd("viewUsers", "郭靖", "黄蓉", "令狐冲", "杨过", "林冲","鲁智深", "小女龙", "虚竹", "独孤求败", "张三丰", "王重阳", "张无忌", "王重阳", "东方不败", "逍遥子", "乔峰", "虚竹", "段誉");//下单用户jedis.sadd("orderUsers", "郭靖", "黄蓉", "令狐冲", "杨过", "林冲","鲁智深", "小女龙", "虚竹", "独孤求败", "乔峰", "虚竹", "段誉");//支付用户jedis.sadd("paymentUsers", "郭靖", "黄蓉", "令狐冲", "杨过", "独孤求败", "段誉");//浏览过商品的用户,有哪些下单了。jedis.sinterstore("view2order", "viewUsers", "orderUsers"); //求两个集合的交集//计算浏览某商品的用户数量 和 既浏览又下单的用户的数量double viewUserNum = jedis.scard("viewUsers");double orderUserNum = jedis.scard("view2order");NumberFormat formatter = new DecimalFormat("0.00");Double x = new Double(orderUserNum / viewUserNum);System.out.print("订单" + orderUserNum + "/浏览" + viewUserNum + "转化:" + formatter.format(x) + "     他们是:");for (String name : jedis.smembers("view2order")) {System.out.print(name + "  ");}System.out.println();//浏览并且下单的用户,最终支付的转化jedis.sinterstore("order2Payment", "view2order", "paymentUsers"); //求两个集合的交集double paymentUserNum = jedis.scard("paymentUsers");x = new Double(paymentUserNum / orderUserNum);System.out.print("支付" + paymentUserNum + "/订单" + orderUserNum + "转化:" + formatter.format(x) + "     他们是:");for (String name : jedis.smembers("order2Payment")) {System.out.print(name + "  ");}System.out.println();//浏览并最终支付的用户的转化x = new Double(paymentUserNum / viewUserNum);System.out.print("支付" + paymentUserNum + "/浏览" + viewUserNum + "转化:" + formatter.format(x)+"    他们是:");for (String name : jedis.smembers("order2Payment")) {System.out.print(name + "  ");}System.out.println();}
}

 Sort Set

Sort Set基本操作

package redis.sortSet;import redis.clients.jedis.Jedis;import java.util.Set;/*** Describe: 请补充类描述*/
public class SortMain {public static void main(String[] args) {Jedis jedis = new Jedis("127.0.0.1", 6379);//往redis库中插入一条sortedset数据jedis.zadd("比武成绩", 10, "乔峰");jedis.zadd("比武成绩", 5, "王重阳");jedis.zadd("比武成绩", 7, "虚竹");jedis.zadd("比武成绩", 2, "王语嫣");jedis.zadd("比武成绩", 5, "段誉");jedis.zadd("比武成绩", 4, "峨眉师太");jedis.zadd("比武成绩", 20, "张三丰");//获取sortSet中所有的元素Set<String> names = jedis.zrange("比武成绩", 0, -1);for (String name : names) {System.out.println(name + "        排名: "//打印用户升序排行+ jedis.zrank("比武成绩", name) + "           赢的场次: "//打印用户的比武成绩+ jedis.zscore("比武成绩", name));}System.out.println("==============================");names = jedis.zrevrange("比武成绩", 0, -1);for (String name : names) {System.out.println(name + "         "+ jedis.zrevrank("比武成绩", name) + "            "+ jedis.zscore("比武成绩", name));}System.out.println("==============================");//修改用户的分数jedis.zincrby("比武成绩",100,"王语嫣");names = jedis.zrevrange("比武成绩", 0, -1);for (String name : names) {System.out.println(name + "         "+ jedis.zrevrank("比武成绩", name) + "            "+ jedis.zscore("比武成绩", name));}}
}

应用场景:天猫订单量和销售总额动态排行榜

package redis.sortSet;import redis.clients.jedis.Jedis;import java.util.Random;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;/*** Describe: 请补充类描述*/
public class Bang {public static void main(String[] args) {//创建线程池ExecutorService executorService = Executors.newFixedThreadPool(10);//创建销售线程-销售商品executorService.submit(new Sale());executorService.submit(new Sale());//创建报表线程-周期型计算排行榜executorService.submit(new BangView());}
}class Sale implements Runnable {//店铺销售排行榜private static final String amountBang = "tmall:amountBang";//店铺订单排行榜private static final String orderBang = "tmall:orderBang";//店铺名称private static final String[] shops = new String[]{"小米", "华为", "魅族", "苹果", "联想", "奇酷", "中兴", "一加", "oppo"};//Redis客户端private Jedis jedis = new Jedis("127.0.0.1", 6379);//随机获取店铺private Random random = new Random();//随机计算价格private Random priceRandom = new Random();public void run() {while (true) {try {int shopIndex = random.nextInt(shops.length);jedis.zincrby(amountBang, priceRandom.nextInt(2500), shops[shopIndex]);jedis.zincrby(orderBang, 1, shops[shopIndex]);Thread.sleep(1000);} catch (InterruptedException e) {System.out.println(e);}}}}class BangView implements Runnable {//店铺销售排行榜private static final String amountBang = "tmall:amountBang";//店铺订单排行榜private static final String orderBang = "tmall:orderBang";//Redis客户端private Jedis jedis = new Jedis("127.0.0.1", 6379);public void run() {while (true) {try {Thread.sleep(1000);System.out.println("==============店铺销售额排行==============================");Set<String> names = jedis.zrevrange(amountBang, 0, 4);for (String name : names) {System.out.println(name + "         "+ jedis.zrevrank(amountBang, name) + "            "+ jedis.zscore(amountBang, name));}System.out.println("==============店铺订单量排行==============================");names = jedis.zrevrange(orderBang, 0, 1);for (String name : names) {System.out.println(name + "         "+ jedis.zrevrank(orderBang, name) + "            "+ jedis.zscore(orderBang, name));}System.out.println();System.out.println();} catch (InterruptedException e) {e.printStackTrace();}}}}

Java大数据-Redis相关推荐

  1. 2019年美团,滴滴,蘑菇街Java大数据面经分享!

    作者:不清不慎!目前从事Java大数据开发相关的工作,对大数据spark等分布式计算领域有着浓厚的兴趣,欢迎一起交流,一起进步.本文为作者投稿,有兴趣投稿的同学,请在后台回复投稿! 大概在三月份开始面 ...

  2. Java大数据学习路线图

    Java大数据学习路线图 准备篇 适用/适合人群:适合基础小白 在这里还是要推荐下我自己建的大数据学习群:199427210,群里都是学大数据开发的,如果你正在学习大数据 ,小编欢迎你加入,大家都是软 ...

  3. java大数据培训,如何选择适合自己的培训机构?

    如何挑选Java大数据培训机构?对于有java的基础的人来说,可以视情况直接跳过java阶段的学习,那么学习时间就可以少一个多月时间,当然前提是基础足够扎实,如果你只是自学了一点java的知识,那么最 ...

  4. Java大数据:大数据开发必须掌握的四种数据库

    大数据的典型特征,包括数据量大.数据类型多.价值密度低等,而具备这样特征的数据,在进入到存储阶段时,就需要根据数据类型及场景,来匹配适当的数据存储解决方案.今天我们来讲讲Java大数据开发当中,必须掌 ...

  5. 零基础学Java大数据难不难

    java大数据如今在企业中用到的次数是非常多的,很多人都比较看好java技术,那么零基础学Java大数据难不难?想要学习java技术说难不难,说简单也不是很简单,来看看下面的详细介绍就知道了. 零基础 ...

  6. python大数据和java大数据的区别-未来Java、大数据、Python哪个前景更好,薪资更高?...

    都知道现在最火爆的是人工智能.大数据.而人工智能和大数据主要用的语言就是Java和Python.今天我们就来分析一下,当前java,python和大数据,哪个就业前景更好?自己该学哪一个? Java和 ...

  7. 原来Java大数据才是真正的高富帅!

    大数据时代,中国IT环境也将面临重新洗牌,不仅仅是企业,更是程序员们转型可遇而不可求的机遇. 国内大多数大型互联网公司的程序员被称作研发工程师,但实际上国内几乎没有研发项目,只能叫做开发.开发程序员的 ...

  8. Java大数据你该学哪个

    1.关于Java Java就是一门编程语言.实现同一个需求有上百种编程语言可以完成,Java之于大数据就是一种工具罢了. 2.关于大数据 大数据就是一个行业,实现同一个需求同样有多种工具可以选择,狭义 ...

  9. java大数据开发做什么你知道吗?大数据的职业发展规划

    ​​​​​​ 你想过自己的未来规划吗? java大数据程序员只需要学到技术就行吗? 1.如何成为大数据工程师 Java开发是IT行业的经典岗位,行业当中存在普遍的需求,Web开发.Android开发. ...

最新文章

  1. python pdf处理 图片_在Python中从PDF提取图像而无需重新采样?
  2. 【深度学习】吊打一切现有版本的YOLO!旷视重磅开源YOLOX:新一代目标检测性能速度担当!...
  3. 直播 | CMU博士后刘鹏飞:文本生成任务十大发展趋势(2020-2021)
  4. 服务器ftp网站怎么临时关闭,如何停止pyftpdlib FTP服务器?
  5. MyBatis的一级缓存、二级缓存演示以及讲解,序列化异常的处理
  6. Excel文件导入mysql数据库
  7. linux进程通信 bzero函数,处理Linux网络编程中的IP地址 — 通信产业...
  8. xp系统dns服务器有问题,xp系统dns错误的恢复方法
  9. 【语音识别】基于动态时间规整算法(DTW)实现中文语音识别系统含Matlab源码
  10. 迅影QQ视频查看v2.0 源码
  11. Windows Debugging
  12. 公平的席位分配(Q值方法)
  13. 前端页面img标签图片显示发生错误或者没有图片都显示默认的图片
  14. 任性安装苹果应用,安装包在手天下我有
  15. android 魅族定位权限,魅族Flyme5.2的权限问题
  16. [OpenCV实战]39 在OpenCV中使用ArUco标记的增强现实
  17. 老卫带你学---使用cv2.imwrite保存的图像是全黑的
  18. 健康贴示(尽力每日更新)2007-02-12
  19. 什么是物联网网关?及它的主要特点
  20. java制作管理系统视频_java语言制作管理系统视频教程

热门文章

  1. 【科普】干货!带你从0了解移动机器人(一)—— 什么是移动机器人
  2. 关于Java调用.NET WCF和Webservice以及javaWebService通用的一种方法
  3. html中页面缩放为何不居中,浏览器窗口放大缩小后页面内容居中解决方法
  4. 2022年的云革命:云转移、云模型和云未来
  5. 【网站搭建】Godaddy如何转移域名
  6. 计算机学院电脑技能讲座,作曲系举办“电脑使用那些事——计算机操作技能实战”讲座...
  7. 立体捕捉系统市场现状研究分析报告
  8. gopro7怎么回看视频_磨人的橡胶怎么了?暨橡胶走势深度解读
  9. 如何快速涨粉,如何使用智能剪辑工具在抖音快速涨粉
  10. 【改论文有感】给英语论文写作小白的有用提示!