Electricity supplier (7)

Disclaimer: This article is a blogger original article, follow the CC 4.0 BY-SA copyright agreement, reproduced, please attach the original source link and this statement.
This link: https://blog.csdn.net/weixin_44050355/article/details/100586857

Electricity supplier seventh day:
first, Product Details optimized
for the new merchandise, high heat merchandise, view product details of the user very much!
10,000 people visit 100 002 749 549} {
@ RequestMapping ( "{} skuId .html")
to access the database 10,000 times.

		新款商品上市的时候可能会产生高并发,对数据库造成冲击!
	解决方案:
		第一种:优化sql语句
			select fieldName,fieldName from skuInfo where id = skuId;
			索引的优化 spuId create index skuInfo on(spuId);
		第二种:加缓存	{redis}
			了解redis的数据类型
			每种数据类型的使用场景
			
	如何整合redis 到项目中!
		springredis redisTemplate 对象操作的命令,与原生态的命令不一致!redisTemplate有自己的一套api。
		
		原生的Jedis Jedis jedis = new Jedis("host",port);  jedis.set() ; jedis.get();
		
		采用Jedis 原生态
		
		1.	导入相应的jar 包
			查询数据在service 层,查询之后,将数据放入redis 。 所以我们需要将 redis 相应的jar 放入访问service。后续可能还有很多的service层
			所以将redis 放入service-util工具类
				        <dependency>
							<groupId>redis.clients</groupId>
							<artifactId>jedis</artifactId>
						</dependency>
		2.	需要获取Jedis 对象。
			2.1	以前spring的xml 形式 配置jedisPool beans.xml 
					// 连接池JedisPool
					// JedisPool jedisClient = new JedisPool(host,port,poolConfig);
					
					<bean id="jedisClient" class="redis.clients.jedis.JedisPool">
						<constructor-arg name="host" value="192.168.26.128"/>
						<constructor-arg name="port" value="6379"/>
						<constructor-arg name="poolConfig" ref="jedisPoolConfig"/>
					</bean>
					// 连接池的配置参数poolConfig
					<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
						<!-- 最大连接数 -->
						<property name="maxTotal" value="30" />
						<!-- 最大空闲连接数 -->
						<property name="maxIdle" value="10" />
						<!-- 每次释放连接的最大数目 -->
						<property name="numTestsPerEvictionRun" value="1024" />
						<!-- 释放连接的扫描间隔(毫秒) -->
						<property name="timeBetweenEvictionRunsMillis" value="30000" />
						<!-- 连接最小空闲时间 -->
						<property name="minEvictableIdleTimeMillis" value="1800000" />
						<!-- 连接空闲多久后释放, 当空闲时间>该值 且 空闲连接>最大空闲连接数 时直接释放 -->
						<property name="softMinEvictableIdleTimeMillis" value="10000" />
						<!-- 获取连接时的最大等待毫秒数,小于零:阻塞不确定的时间,默认-1 -->
						<property name="maxWaitMillis" value="1500" />
						<!-- 在获取连接的时候检查有效性, 默认false -->
						<property name="testOnBorrow" value="true" />
						<!-- 在空闲时检查有效性, 默认false -->
						<property name="testWhileIdle" value="true" />
						<!-- 连接耗尽时是否阻塞, false报异常,ture阻塞直到超时, 默认true -->
						<property name="blockWhenExhausted" value="false" />
					</bean>
			2.2	现在项目基于spring boot 推荐使用无配置所有的配置都推荐使用注解方式!
				在service-util 项目中创建RedisUtil  RedisConfig
				2.2.1	需要创建一个工具类 RedisUtil 
						
				2.2.2	需要创建一个工具类 的配置类 RedisConfig
						RedisConfig 作用是给initJedisPool 方法进行初始化参数设置 host,port,database
	3.	redis 整合业务
		3.1	数据以什么方式来存储!用哪种数据类型来存储!
			String :
				set(skuId,skuInfo);
				get(skuId);
				
				skuInfo{
					33
					小米手机
					1999
				}
				
				商品详情:
				set(33,skuInfoJson);
				
				String skuInfoJson = get(33)
				skuInfoJson 转换为对象 skuInfo 
			List :
			Set :
			Hash :
				hset(key,field,value);
				key: 唯一 skuId 
							
				skuInfo{
					33
					小米手机
					1999
					....
				}
				field: 字段名
					33	
					hset(33,id,33);
					hset(33,skuName,小米手机);
					hset(33,price,1999);
					
					hset(skuId,字段名);
					hset(skuId,字段名);
					hset(skuId,字段名);
					hset(skuId,字段名);
					
					
				hget(key,field);
				 hget(skuId,字段名)
				
					String Id = hget(33,id);
					String SkuName = hget(33,skuName);
					String price = hget(33,price);
					
					hget(skuId,字段名);
					hget(skuId,字段名);
					hget(skuId,字段名);
					hget(skuId,字段名);
					
			ZSet :
			
			
			推荐使用String!
			key:sku:skuId:info 
			
		3.2	注意获取数据的流程!
			如果缓存中有数据,则从缓存中获取,
			如何缓存中没有数据,则从数据库获取并放入缓存!
			
		3.3	redis 做缓存的时候,需要解决的一些问题!
			a.	如果redis 宕机了,如何处理!
					try-catch-finally
					最后只能从数据库查询!
			b.	面试redis时,常用的三个问题
				缓存击穿:
					指当缓存中的一个key 失效的时候。此时如果有大量用户进行访问! 则会对数据库造成冲击!
					
					解决方案:
									setnx();
					使用分布式锁: 	set(key,value,nx,px,timeout);
									
									redisson
									https://github.com/redisson/redisson/wiki/8.-%E5%88%86%E5%B8%83%E5%BC%8F%E9%94%81%E5%92%8C%E5%90%8C%E6%AD%A5%E5%99%A8
					
				缓存穿透:
					指查询一个根本不存在的数据,每次都会去查询数据库,则会造数据库压力。
					
					if(key){
						emptiy redis.get(key);
					}else{
						Object obj = finddb();
						if(obj!=null){
							redis.set(key,value);
						}else{
							// 如果是null ,则不需要放入数据
							jedis.set(key ,null)
						}
					}
					
					将缓存中放入一个空的值 null
					
				缓存雪崩:
					是在同一个时间点,缓存中的所有key 同时失效。此时当用户量庞大的时候,会直接对数据库造成一个冲击!
					flushall
					解决方案: 将key的过期时间调整,
					
	
第二,es 回顾,搭建一个全文检索项目
	全文检索,三级分类检索:数据来自于哪里?
		直接来源:elasticsearch 
		间接来源:mysql 
		
		mysql ----> elasticsearch 该过程叫商品上架!
	
		es---安装
		elsaticsearch 
		面试题:
		为什么要使用?
			select * from skuInfo where skuName like "%华为%" 索引失效!
			elsaticsearch 、 solr
				solr:基于数据固定不变的情况下使用。数据节点是不变,速度慢!
				elsaticsearch: 数据节点变化的。速度快。
				
				为什么会快?
				因为:倒排索引!
		
		怎么使用?
			1.	有分词器:
				通过分词器将查询的内容进行分词,组成不同的ids 。通过内容匹配找到对应的数据!
			结合项目中:
				***** ELK 框架
					elsaticsearch :全文检索
					logstash :收集日志
						在es 中配置一下logstash!
							es 中的检索日志都可以在kibana 中得到!
					kibana :查询数据
					
					
				1.	kibana。 编写dsl 语句查询es中的数据
		
	首页:
		1.	将资料中的
			css"
			img"
			js"
			json"
			放入nginx 做静态代理:
			
		2.	在nginx中配置 nginx.conf
		回顾:nginx.conf
		 location / {
				root   html;
				index  index.html index.htm;
			}
		root: nginx安装目录中的文件夹
		index:表示访问这个文件夹html目录下的index.html  index.htm
		/:表示html文件下的根目录

		
		server {
			  listen       80;
			  server_name  www.gmall.com;
			  location / {
					root front;
					index index.htm;
					}
			}
			
		3.	制作域名:
				修改hosts文件
				192.168.67.217 www.gmall.com

		4.	重启nginx
				/usr/local/nginx/sbin/nginx -s reload
				表示重新加载配置文件
		5.	开始访问www.gmall.com
				http://www.gmall.com/
				
		6.	制作商品详情页的域名
			// 代理一个域名 【item.gmall.com】表示返回当前本地的商品详情
			192.168.67.1 :vmnet8的ip地址
			本机的ip地址
			127.0.0.1
			localhost
			
			upstream item.gmall.com{
				server 192.168.67.1:8084;
			}

		  server {
			  listen       80;
			  # server_name  item.gmall.com;
			  location / {
					proxy_pass http://item.gmall.com;
					}
			}

	elsaticsearch 知识储备:
	
		安装es
			注意:elasticsearch.yml 中的配置!
				调整一下虚拟机内存的大小!
		安装kibanna
			nohup ./kibana &
			将kiban 运行的所有日志文件写入nohup 
			
		
		INDEX: 索引库
		TYPE: 表
		DOCUMENT: 行
		FIELD: 字段
	
		PUT: 新建
		GET: 查询
		DELETE: 删除
		POST: 修改	
		POST /INDEX/TYPE/ID/_UPDATE
		{
			"doc" :{
				"doubanScore":"7.0"
			}
		}
		
		dsl语句
			put /index
			get /index/type/_search 
			post /index/type/id/_update
			delete /index
			
			分页
			排序
			聚合
			过滤
			高亮
		
		自定义mapping {自定义一个数据库中的表结构}
			create table stu(
				id int primary key,
				name varchar(20),
				age int,
				sex varchar(1)
			)
			
		自定义mapping 属于自定义index下的type
		
		默认只有text会进行分词,keyword是不会分词的字符串。
		
		安装中文词库:
			直接将中文词库放入插件文件夹中,并解压,然后将其压缩包删除即可!
			
			安装完成重启:
			service elasticsearch restart 
		
	使用java 语言来操作es!
		a.	先导入操作es 的jar 包
			<dependency>
			   <groupId>org.springframework.boot</groupId>
			   <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
			</dependency>

			<!-- https://mvnrepository.com/artifact/io.searchbox/jest -->
			<dependency>
			   <groupId>io.searchbox</groupId>
			   <artifactId>jest</artifactId>
			</dependency>

			<!-- https://mvnrepository.com/artifact/net.java.dev.jna/jna -->
			<dependency>
			   <groupId>net.java.dev.jna</groupId>
			   <artifactId>jna</artifactId>
			 </dependency>


		b.	操作api ,利用api 对es 中的数据进行查询!
			从es 中将数据查询出来,能够在应用程序中打印出来!
			gmall-list-service 检索的服务项目

回顾商品详情:
	@RequestMapping("{skuId}.html")
	public String item(@PathVariable String skuId){
		// 调用服务层查询数据
		// 作用域保存!
		return "item"
	}
	
	
	总结:
		*1.	分布式锁:
			
		**2.	java 整合es !
			@Test
			public void testES() throws IOException {
				// 回顾jestClient 可以操作dsl 语句执行!
				// 定义dsl 语句
				String query = "{\n" +
						"  \"query\": {\n" +
						"    \"match\": {\n" +
						"      \"actorList.name\": \"张译\"\n" +
						"    }\n" +
						"  }\n" +
						"}";
				// 定义查询动作
				Search search = new Search.Builder(query).addIndex("movie_chn").addType("movie").build();
				// 执行dsl 语句 执行一个操作! jestResult
				SearchResult searchResult = jestClient.execute(search);
				// 返回结果jestResult 遍历里面的数据
				List<SearchResult.Hit<Map, Void>> hits = searchResult.getHits(Map.class);
				// 循环当前结合
				if (hits!=null && hits.size()>0){
					for (SearchResult.Hit<Map, Void> hit : hits) {
						Map map = hit.source;
						System.out.println(map.get("name")); // 红海行动
					}
				}
			}

Guess you like

Origin blog.csdn.net/weixin_44050355/article/details/100586857