原创

elasticsearch-es-推荐搜索-关键学习笔记

ElasticSearch+Spark 构建高匹配度搜索服务+千人千面推荐系统

课程地址:http://coding.imooc.com/learn/list/391.html

elastic相关产品文档:https://www.elastic.co/guide/index.html

注意:

  1. 非重要的代码直接copy
  2. 相关笔记只是使用课程章节后的总结(首先直接copy)
  3. 第13章节的代码可能还会继续push(https://git.imooc.com/coding-391/dianpingjava)
  4. 开启分支管理

项目部署环境:

本次数据库和es环境直接使用腾讯云,注意不要开放git源码。

一、项目设计

1.1 BRD

全称:
Business Requirement Document

定义:
业务诉求方简略的表述自身想要达到的业务诉求的说明书

1.2 点评搜索推荐BRD样例

业务目的:
模仿大众点评应用提供用户线下服务的h5页面

业务场景:
让用户可以通过对应h5页面搜索想要的门店服务,并通过猜你喜欢的方式给用户做门店推荐

使用人员:
1.业务的运营人员
2.需要获得服务的c端用户

1.3 PRD

全称:
Product Requirement Document

定义:
产品经理通过业务方的业务需求说明书制定出可以提供给研发上手开发的明确的产品流程,需求,用户使用行为,前后台明确功能等说明书

1.4 点评搜索推荐PRD

需求背景:
模仿大众点评应用提供用户线下搜索推荐服务门店的需求

名词定义:
用户:使用仿点评应用h5搜索推荐页面的人员
运营后台:提供后台门店,商户,服务类目管理的后台网页
运营:使用运营后台配置门店,商户,服务类目的人员

运营后台功能:

1.运营登录功能:
输入用户名,密码登录运营后台

2.运营商家管理功能,包含:
商家创建:商户名,商家评分
商家列表查询:商户id,商户名,商户评分
商户启用禁用

3.服务类目管理功能,包含:
类目创建:名称,图标,排序
类目列表查询:类目id,名称,图标,排序

4.门店管理功能,包含:
门店创建:名字,人均价格,评分,地址,标签,营业时间
门店列表查询:门店id,名字,人均价格,评分,地址,标签,营业时间

H5 C端功能:

1.用户注册功能:手机号,密码注册

2.用户登录功能:手机号,密码登录

3.服务分类:服务类目按照运营后台预设的功能排序展示图标和名称

4.猜你喜欢:根据千人千面,用户的喜好推荐用户服务门店的功能,包含门店图片,名字,价格,评分,地址,标签,营业时间等

5.搜索:根据lbs和关键字搜索用户附近的服务门店,包含门店图片,名字,价格,评分,地址,标签,营业时间等,且可以根据服务类目,标签做筛选,通过价格做排序等

1.5 项目架构设计

业务模型:
根据产品需求prd文档做业务模型


业务模型

模型分为:
用户:有注册,登陆,浏览界面行为
商家:有入驻,更新,被评价,禁用行为
服务类型:有创建和更新排序行为
门店:有创建,定位,被搜索和被推荐行为

进一步确认系统模块架构
图片描述

主要分为

后端业务模块:用于业务功能模型搭建,统一鉴权接入
后端存储系统:用于数据库,canal管道数据同步,elasticsearch中间件建设
前端页面
搜索系统:用于搜索接入,语义构建,索引构建服务
推荐系统:用于推荐算法,推荐服务接入

1.6 技术选型

图片
图片描述


业务模型

二、应用SpringBoot构建基础项目

2.1 使用mybatis-generator生成java代码的核心步骤:

修改mybatis-generator.xml中的

 tableName="shop"  domainObjectName="ShopModel"

新建Maven的启动,nama填写:mybatis-generator, command-line填写:mybatis-generator:generate ,然后启动mybatis-generator。

2.2 接口全局异常处理

见 UserController#getUser() 注释

 这里抛出异常处理,默认会被tomcat层接收,并跳转到/error页面

 所以
 1、在启动类上 添加 @EnableAspectJAutoProxy(proxyTargetClass = true)
 2、GlobalExceptionHandler 去接收所有的controller抛出的异常

2.3 页面请求资源处理

1、
spring.resources.add-mappings=false 改成true

2、接入前端静态资源页面

spring.mvc.static-path-pattern=/static/**

3、在resources下新建static/test.html

4、访问 http://127.0.0.1:8010/static/test.html

5、接入thymeleaf(引入jar包)

spring.thymeleaf.prefix=classpath:/templates/

spring.thymeleaf.suffix=.html

6、访问测试:http://127.0.0.1:8010/user/index

如果提示:
Error resolving template [/index.html], template might not exist or might not be accessible

检测target/有没有生产模板文件,没有的话,执行maven clean.

There was an unexpected error (type=Internal Server Error, status=500).
Error resolving template [/admin/admin/index], template might not exist or might not be accessible by any of the configured Template Resolvers
ModelAndView modelAndView = new ModelAndView("admin/admin/index");//这里不能使用/开头,会导致打包后在服务上找不到路径
见《https://blog.csdn.net/liuchuanhong1/article/details/75352442》

2.4 用户服务搭建

相应代码:UserController.java

添加页码资源:前台在/static,后台运营在/templates文件夹中

前台 :

http://127.0.0.1:8010/static/index.html

https://es-dianping.jiangjiesheng.cn

运营平台:

http://127.0.0.1:8010/admin

2.5 运营后台服务搭建

ControllerAspect.java AOP切面编程实现admin登录校验

2.6 商户后台服务搭建

三、门店推荐V1.0

 基于经纬度实现的推荐
 select
 <include refid="Base_Column_List" />
 ,ceil(1 + 1000*(2 * 6378.137* ASIN(SQRT(POW(SIN(PI() * (#{latitude} - latitude) / 360), 2) + COS(PI() * #{latitude} / 180)
 * COS(latitude* PI() / 180) * POW(SIN(PI() * (#{longitude} - longitude) / 360), 2))))) AS distance
 from shop order by (0.95*1/log10(distance)+ 0.05*remark_score/5)  DESC

注意打分支

完成日期:20191109

其他经验:

1.
Error resolving template [/index.html], template might not exist or might not be accessible

检测target/有没有生产模板文件,没有的话,执行maven clean.
  1. 如果始终找不到jar包,勾选 always update snapshots后更新maven。

四、ElasticSearch基础

4.1 ElasticSearch原理

4.1.1 搜索的原理

es是什么
协议:http or transport

索引index :数据库Database

类型Type :表Table

文档Document :行数据Row

Field :Column

Mapping :Schema

Everything is indexed :index

Query DSL :SQL

GET http://... : SELECT * FROM table ...

PUT http://... : UPDATE table SET

索引:

搜索中的数据库或表定义

构建文档时候的索引创建

基本过程示例:

mysql(id:1 name=xiaoming is chinese) <--> 构建索引 <--> document:1 name:xiaoming is chinese <--> 分词 --> 索引存储 <--
分词 <-- 搜索关键字

索引是以词为单位做基本的搜索单元,依靠分词器构建分词,用分词构建倒排索引

TF/IDF打分

TF:词频,这个document文档包含了多少个这个次,包含越多表明越相关

DF:文档频率 包含该词的文档总数目。
IDF: DF取反

4.1.2 ElasticSearch及Kibana环境搭建(不能有中文路径)

https://www.elastic.co/cn/

https://www.elastic.co/cn/downloads/elasticsearch/ 目前最新是7.7版本,学习视频是7.3版本,相关版本之间也要对应

https://www.elastic.co/cn/downloads/kibana/ 也要去下载 7.3 版本

【由于在linux上wget官网版本下载很慢,所以使用 https://thans.cn/mirror/elasticsearch.html 】

本次直接在linux服务器上操作安装、调用
4.1.2.1
本地资源:目前在iCloud中的/开发安装包 文件件中 

elasticsearch下载:
【太慢】wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.3.0-linux-x86_64.tar.gz
【很快】wget https://elasticsearch.thans.cn/downloads/elasticsearch/elasticsearch-7.3.0-linux-x86_64.tar.gz

kibana下载
wget https://artifacts.elastic.co/downloads/kibana/kibana-7.3.0-linux-x86_64.tar.gz

es和kibana服务器端下载路径 /deploy-path/searchDic/elastic-search
解压路径 /deploy-path/searchDic/elastic-search/elasticsearch-7.3.0

MAC实用SSH连接远程服务器,并实现文件上传下载.

4.1.2.2 启动elasticsearch

关键:
1、按-d参数启动(另kibana使用 &)
2、chown -R elasticsearch 改变所有者
3、不要以root用户启动
4、结束后 tail -n 500 dianping-app.log

需要后台启动,关闭shell窗口后可用。-d好像起不起来,使用 & ,另外使用tail -f xxx.log 查看日志。

   su elasticsearch 
    /deploy-path/searchDic/elastic-search/elasticsearch-7.3.0/bin/elasticsearch &(加-d 是后台启动,但是启动失败)

启动很慢,并保错 can not run elasticsearch as root --> https://www.cnblogs.com/gcgc/p/10297563.html

   adduser elasticsearch
   passwd elasticsearch
   密码见云笔记《12-网站维护》
   chown -R elasticsearch elasticsearch-7.3.0 对应到所在目录
   su elasticsearch 
   ./bin/elasticsearch &

好像没有打印启动日志,跟-d有关?

启动后

查看进程 ps -ef | grep elastic

端口9200 netstat -an | grep 9200

测试 curl 127.0.0.1:9200 ,"curl: (7) Failed connect to 127.0.0.1:9200; 拒绝连接":

修改elasticsearch.yml文件,添加

network.host: 0.0.0.0

重启:杀进程后执行启动

max virtual memory areas vm.max_map_count [65530] is too low:

https://blog.csdn.net/jiankunking/article/details/65448030

the default discovery settings are unsuitable for production use; at least one of [discovery.seed_hosts, discovery.seed_providers, cluster.initial_master_nodes] must be configured

https://blog.csdn.net/happyzxs/article/details/89156068

/deploy-path/searchDic/elastic-search/elasticsearch-7.3.0-node2/logs/dianping-app_index_indexing_slowlog.json (权限不够)

是因为使用root启动后生成了一下日志文件,这些文件需要先删除,或者 chown ,然后重新使用elasticsearch用户启动

elasticsearch-7.3.0-node2/data]] with lock id [0]; maybe these locations are not writable or multiple nodes were started without increasing [node.max_local_storage_nodes] (was [1])?

删除data文件夹

    启动日志的最后部分:
    [2020-06-14T09:33:04,907][INFO ][o.e.d.DiscoveryModule    ] [VM_0_2_centos] using discovery type [zen] and seed hosts providers [settings]
    [2020-06-14T09:33:06,711][INFO ][o.e.n.Node               ] [VM_0_2_centos] initialized
    [2020-06-14T09:33:06,712][INFO ][o.e.n.Node               ] [VM_0_2_centos] starting ...
    [2020-06-14T09:33:06,996][INFO ][o.e.t.TransportService   ] [VM_0_2_centos] publish_address {172.17.0.2:9300}, bound_addresses {0.0.0.0:9300}
    [2020-06-14T09:33:07,026][INFO ][o.e.b.BootstrapChecks    ] [VM_0_2_centos] bound or publishing to a non-loopback address, enforcing bootstrap checks
    [2020-06-14T09:33:07,088][INFO ][o.e.c.c.Coordinator      ] [VM_0_2_centos] cluster UUID [b7tF6p8YRAWwIPd7QGZjJQ]
    [2020-06-14T09:33:07,587][INFO ][o.e.c.s.MasterService    ] [VM_0_2_centos] elected-as-master ([1] nodes joined)[{VM_0_2_centos}{DSxes7oFTQWRBm-ALt1xbQ}{uRVpnY^[^[

    再次请求测试
    [root@VM_0_2_centos ~]# curl 127.0.0.1:9200    curl 118.25.49.160:9200(ip访问)
    {
      "name" : "VM_0_2_centos",
      "cluster_name" : "elasticsearch",
      "cluster_uuid" : "b7tF6p8YRAWwIPd7QGZjJQ",
      "version" : {
        "number" : "7.3.0",
        "build_flavor" : "default",
        "build_type" : "tar",
        "build_hash" : "de777fa",
        "build_date" : "2019-07-24T18:30:11.767338Z",
        "build_snapshot" : false,
        "lucene_version" : "8.1.0",
        "minimum_wire_compatibility_version" : "6.8.0",
        "minimum_index_compatibility_version" : "6.0.0-beta1"
      },
      "tagline" : "You Know, for Search"
    }

    http://118.25.49.160:9200/_cat 已屏蔽端口,

    =^.^=

    /_cat/allocation
    /_cat/shards
    /_cat/shards/{index}
    /_cat/master
    /_cat/nodes
    /_cat/tasks
    /_cat/indices
    /_cat/indices/{index}
    /_cat/segments
    /_cat/segments/{index}
    /_cat/count
    /_cat/count/{index}
    /_cat/recovery
    /_cat/recovery/{index}
    /_cat/health
    /_cat/pending_tasks
    /_cat/aliases
    /_cat/aliases/{alias}
    /_cat/thread_pool
    /_cat/thread_pool/{thread_pools}
    /_cat/plugins
    /_cat/fielddata
    /_cat/fielddata/{fields}
    /_cat/nodeattrs
    /_cat/repositories
    /_cat/snapshots/{repository}
    /_cat/templates

    http://118.25.49.160:9200/_cat/health

    1592099840 01:57:20 elasticsearch green 1 1 0 0 0 0 0 0 - 100.0%
4.1.2.3 启动kibana
需要后台启动,关闭shell窗口后可用。

   su elasticsearch 
   cd /deploy-path/searchDic/elastic-search/kibana-7.3.0-linux-x86_64 
   nohup ./bin/kibana & (这样保证日志的位置)
   -- nohup /deploy-path/searchDic/elastic-search/kibana-7.3.0-linux-x86_64/bin/kibana & (注意,这个有nohup.log日志,日志问题见文末关键字:nohup打印的日志问题)
   -- /deploy-path/searchDic/elastic-search/kibana-7.3.0-linux-x86_64/bin/kibana &(加-d 是后台启动,但是启动失败)

无访问权限:

   su root
   chown -R elasticsearch kibana-7.3.0-linux-x86_64
   su elasticsearch
   /deploy-path/searchDic/elastic-search/kibana-7.3.0-linux-x86_64/bin/kibana & (好像使用-d报错)
   最后日志不走的时候,应该已经跑完了,回车看一下

启动日志:
log [04:18:47.420] [info][status][plugin:spaces@7.3.0] Status changed from yellow to green - Ready

netstat -na | grep 5601

访问kibana 118.25.49.160:5601 失败
wget 127.0.0.1:5601, 成功 ,
修改elasticsearch.yml文件,添加

network.host: 0.0.0.0
同时修改 修改防火墙 https://tech.jiangjiesheng.cn/dev/study/java/mmall/backend-1/
通过杀进程方式 再次后台 重启。ps -ef | grep kibana

访问kibana 118.25.49.160:5601 成功

data/headless_shell-linux/swiftshader/libGLESv2.so: cannot open shared object file: No such file or directory:
删除 ./data/文件中内容

4.1.2.4 kibana中使用elasticsearch
   Dev Tools

1. 创建索引
    ...


1.删除索引
DELETE /test
{

}

-- 可无括号


2.创建索引
PUT /test
{

}
-- Index Management 中 可见,状态是yellow,同时 http://118.25.49.160:9200/_cat/health 也是yellow。

另外Create index pattern --> Define index pattern --> index索引名字加上*即可,例如movie*

Primaries:索引的主分片数量
Primaries:从分片数量

通过参数设置指定分片数量,新建索引后变成green
PUT /test
{
  "settings": {
    "number_of_shards": 1,
    "number_of_replicas": 0
  }
}

2.搭建elasticsearch集群

注意:日志文件名都变了

修改文件夹 elasticsearch-7.3.0-node1

要多个空格

修改elasticsearch.yml

cluster.name: dianping-app (共享的名字)

node.name: node-1 (多个要区分)

network.host: 0.0.0.0 (外网可访问 0.0.0.0 或者 118.25.49.160 ,否则127.0.0.1)

http.port: 9200 (多个要区分,响应web http请求)

transport.tcp.port: 9300 (集群间通信)

http.cors.enabled: true (前端跨域访问)

http.cors.allow-origin: "*"

discovery.seed_hosts: ["127.0.0.1:9300", "127.0.0.1:9301","127.0.0.1:9302"] (应该可以 127.0.0.1)

cluster.initial_master_nodes: ["127.0.0.1:9300", "127.0.0.1:9301","127.0.0.1:9302"] (应该可以 127.0.0.1,这里是不是可以直接填node-1?)

再解压2个elasticsearch ,node2,node3(network.host: 0.0.0.0 理论上是不是不要指定)

将上述的配置文件复制到node2中

node.name: node-2

http.port: 9201

transport.tcp.port: 9301

将上述的配置文件复制到node3中

node.name: node-3

http.port: 9202

transport.tcp.port: 9302

分别启动三个节点

 su root
 chown -R elasticsearch elasticsearch-7.3.0-node1
 chown -R elasticsearch elasticsearch-7.3.0-node2
 chown -R elasticsearch elasticsearch-7.3.0-node3
 su elasticsearch
 /deploy-path/searchDic/elastic-search/elasticsearch-7.3.0-node1/bin/elasticsearch &

第一台启动成功,第二台连接不上集群
https://blog.csdn.net/qq_36317804/article/details/88697846

看起来都要设置 cluster.initial_master_nodes: ["node-1"] 才可能启动成功。

kibana已使用域名 http://kibana.jiangjiesheng.cn
es已使用域名 http://es.jiangjiesheng.cn:8092/ (防火墙需要开放,http端口是9200(代理端口为8092))
注意:es服务本身的tcp端口是9300(代理端口为8093,需要重新编译nginx模块,https://blog.csdn.net/blscok/article/details/81941619),

kibana接入身份认证(登录用户名、密码):https://www.jianshu.com/p/fbc3a80c05c5

admin 密码见云笔记《12-网站维护》

生成的密码位置:/usr/local/nginx/conf/custom-password/htpasswd-kibana-dianping

教程:/usr/local/nginx/conf/custom-password/0-nginx配置密码-身份验证.txt

#发现kibana会自动关闭:

su elasticsearch && cd /deploy-path/searchDic/elastic-search/kibana-7.3.0-linux-x86_64 && nohup ./bin/kibana & (这样保证日志的位置)

  1. nohup /deploy-path/searchDic/elastic-search/kibana-7.3.0-linux-x86_64/bin/kibana &

    tail -f nohup.out ,注意查看日志, 日志问题见文末关键字:nohup打印的日志问题
  2. 使用exit退出shell终端:

    /deploy-path/searchDic/elastic-search/kibana-7.3.0-linux-x86_64/bin/kibana &

    ... 启动完成后 ...
    exit

4.2 ElasticSearch基础语法

4.2.1 非结构化方式新建索引

见《4.2 ElasticSearch基础语法.md》

4.2.2 结构化方式新建索引

见《4.2 ElasticSearch基础语法.md》

4.3 ElasticSearch高级语法

见《4.3 ElasticSearch高级语法.md》

4.4.1 analyze分析过程 & 相关性查询手段

analyze:分析=分词的过程:字符过滤器->字符处理 -> 标准分析器(以空格和标点符号分割内容 -> 分词过滤(分词转换:大小写转换))<br/>

english analyze:分析=分词的过程:字符过滤器(过滤特殊符号外加量词,the等等)->字符处理 -> 标准分析器(以空格和标点符号分割内容 -> 分词过滤(分词转换:词干转换:apple 会被转成 appl 单复数等))<br/>

IK analyze:分析=分词的过程:字符过滤器(过滤特殊符号外加量词,"的",stopWord停用词)->字符处理(词库词典) -> 分词过滤(分词转换,词干转化) "中华人民共和国"--> "中华 人民 共和国"<br/>

4.4.2 Tmdb实例

类型:
    Text 被分析索引的字符串类型
    Keyword:不能被分析只能被精确匹配的字符串类型
    Date:日期类型,可以配合format一起使用
    数字类型:long,integer,short,double等
    boolean:true false
    Array:["one","two"]
    Object:json嵌套
    Ip类型
    Geo_point:地理位置

    在线文档:https://www.elastic.co/guide/index.html
    中文教程;https://www.elastic.co/guide/cn/index.html

    tmdb:https://www.themoviedb.org/
    开源数据:https://www.kaggle.com/tmdb/tmdb-movie-metadata vpn使用谷歌浏览器下载
    dev@jiangjiesheng.cn 下载文件路径在 /0-data/tmdb-movie/

更多查询语法见《4.4.2 开始学习tmdb.md》

score打分:
TF IDF tfNORM
TF:token frequency,basketball这样的一个分词在document字段(待搜索的字段)中出现的次数。
IDF:inverse document frequency,逆文档频率,代表basketball这样的一个分词在整个文档中出现的频率,取反。
tfNORM:token frequency normalized 词频归一化。
BM25:解决词频问题。

自定义score计算

查全率查准率

查全率:正确的结果有n个,查询出来正确的有m m/n

查准率:查出的n个文档有m个正确 m/n

两者不可兼得,但可以调整排序

五、中文分词器

5.1 Ik分词器

安装:

       cd /deploy-path/searchDic/elastic-search/elasticsearch-7.3.0-node1
       su elasticsearch
       // ./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.3.0/elasticsearch-analysis-ik-7.3.0.zip
       //上面下载的速度太慢。所以先上传
       scp /Users/jiangjiesheng/Downloads/elasticsearch-analysis-ik-7.3.0.zip  root@m.jiangjiesheng.cn:/deploy-path/searchDic/elastic-search
       ./bin/elasticsearch-plugin install file:///deploy-path/searchDic/elastic-search/elasticsearch-analysis-ik-7.3.0.zip

       * java.net.SocketPermission * connect,resolve
       See http://docs.oracle.com/javase/8/docs/technotes/guides/security/permissions.html
       for descriptions of what these permissions allow and the associated risks.
       Continue with installation? [y/N]
       ERROR: installation aborted by user

       ---> 执行上述install命令后,不要再回车,等到出现ontinue with installation(速度慢)

       cd plugins
       ls
       ...
       杀死es进程,
       重启 ./bin/elasticsearch -d 

       除了上述install的方式,也可以使用把zip包放进plugins文件夹并解压,es启动时自动扫描
   进行到9-3

5.2 Ik分词器学习

见《5.2 Ik分词器学习.md》

此elasticsearch-7.3.0-node1/config/analysis-ik文件夹都是关于ik分词器的配置文件,例如</br>
stopword.dic 英文停用词</br>
extra_stopword.dic 中文停用词</br>

六、点评搜索索引

6.1 点评搜索索引定义

  • 定义字段逻辑
  • 定义字段类型
  • 定义字段analyzer

见《6.1 点评搜索索引定义.md》

6.2 点评搜索索引构建

  • 全量索引构建
  • 增量索引构建
  • 增量构建方式 (时间维度,数据库变化)

logstash-input-jdbc:

  • 数据源
  • 数据模板
  • 同步方式
mysql                                             elasticsearch
  ∧       select * from shop  全量索引构建 (分页)         ∧
  |                                                     |
  监听 <--- logstash-input-jdbc pipe管道   ---> http restful index api  

  分页过程中,可能数据库可能已经发生变化,业务上可以接受。

下载
wget https://artifacts.elastic.co/downloads/logstash/logstash-7.3.0.zip (实际使用时不要中文路径)

下载太慢,重开terminal窗口 scp ./logstash-7.3.0.zip root@m.jiangjiesheng.cn:/deploy-path/searchDic/elastic-search/

    安装:
    cd /deploy-path/searchDic/elastic-search
    unzip logstash-7.3.0.zip
    cd logstash-7.3.0/
    ./bin/logstash-plugin install logstash-input-jdbc (耗时)

    cd bin
    mkdir mysql
    重新开窗口
    scp ~/.m2/repository/mysql/mysql-connector-java/5.1.6/mysql-connector-java-5.1.6.jar root@m.jiangjiesheng.cn:/deploy-path/searchDic/elastic-search/logstash-7.3.0/bin/mysql

    cd mysql
    touch jdbc.conf
    touch jdbc.sql

    从本项目 es-dingping/1-相关软件包/服务器端配置文件/ 直接复制文件内容

    cd /deploy-path/searchDic/elastic-search/logstash-7.3.0/
    ./bin/logstash -f ./bin/mysql/jdbc.conf  (耗时)

    增量更新(按时间,sql上按updated_at > :sql_last_value,就可以找出数据库上最新的数据,此时在updated_at设置索引就可以应付大数据场景吗?如果一次同步失败,就丢失es数据了:后续有方法)
    在jdbc.conf中继续设置:
    jdbc_default_timezone
    last_run_metadata_path(vi bin/mysql/last_value_meta ,输入2010-11-11 11:11:11,小于数据库的updated_at。实测对last_run_metadata_path写入来看,还是小了8小时,但是观察sql日志没有问题。)
    并改造jdbc.sql:增加where 

    重新启动 
    ./bin/logstash -f ./bin/mysql/jdbc.conf  (耗时)
    后台启动 
    nohup /deploy-path/searchDic/elastic-search/logstash-7.3.0/bin/logstash -f /deploy-path/searchDic/elastic-search/logstash-7.3.0/bin/mysql/jdbc.conf >/dev/null & (日志问题见文末关键字:nohup打印的日志问题)

    tail -f /home/elasticsearch/nohup.out 日志位置

    UPDATE shop set updated_at = now(),name = '和府捞面(正大乐城店)1' WHERE id = 1,再观察日志、查询。

    GET /shop/_search
    {
      "query": {
        "match_phrase": { //完全匹配,不分词
          "name": "和府捞面(正大乐城店)"
        }
      },
      "sort": [
        {
          "id": {
            "order": "asc"
          }
        }
      ]
    }


  后台启动 nohup /deploy-path/searchDic/elastic-search/logstash-7.3.0/bin/logstash -f /deploy-path/searchDic/elastic-search/logstash-7.3.0/bin/mysql/jdbc.conf >/dev/null & (日志问题见文末关键字:nohup打印的日志问题)
  【查关键词: logstash启动步骤结论】

6.3 点评搜索应用接入

  • 基本搜索测试

见《6.1 点评搜索索引定义.md》

  • 搜索模型建立

见《6.3 点评搜索应用接入.md》

  • Java代码接入

    node接入 新增node client:新增一个节点,自己也作为集群一部分

    Transport接入 新增transport client:自己不会集群部分,负责集群见通信?
    Http接入 新增rest client:只需要连接集群中的任何一个节点【推荐,不限制环境、语言】

增加jar包

<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>elasticsearch-rest-client</artifactId>
    <version>7.3.0</version>
</dependency>
<dependency>
    <groupId>org.elasticsearch</groupId>
    <artifactId>elasticsearch</artifactId>
    <version>7.3.0</version>
</dependency>
<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>elasticsearch-rest-high-level-client</artifactId>
    <version>7.3.0</version>
</dependency>

相关代码:
新增 ElasticSearchRestClient.java

新增 ShopService.searchES() 并完成 ShopController#search()接口。

查询参数:也可以直接将在kibana中调试的json字符串复制过来,替换必要参数后直接 request.setJsonEntity(reqJson);
(但是不例如后续扩展)

遗留问题:

分词定制化能力

同义词及词性

索引实时性

七、点评搜索应用进阶

  • 扩展词库
  • 同义词
  • canal准实时索引搭建

    7.1 定制化中文分词器(定制化分词,专业性单词)

    7.1.1 扩展词库

    给ik分词库

    GET /shop/_search
    {
      "query": {
        "match": {
          "name": "凯悦"
        }
      }
    }

    GET /shop/_analyze
    {
      "analyzer": "ik_smart",  // 分为 凯 悦
      "text": "凯悦"  
    }
    期望分词结果就是 凯悦 ,不要分开
    cd /deploy-path/searchDic/elastic-search/elasticsearch-7.3.0-node1/config/analysis-ik
    vi new_word.dic 并输入 凯悦 
    vi IKAnalyzer.cfg.xml 编辑 <entry key="ext_dict">new_word.dic</entry>,分别复制这两个文件到其他2个节点config/analysis-ik/ 

    kill并重启es (kill引用jar包少的进程,多的是logstach)
    su elasticsearch
    ./bin/elasticsearch -d(万一有问题,看下日志)

    测试发现上述_search查询凯悦的返回hits为空。原因是构建索引时按凯 和 悦 两个字分词的,现在需要重建索引。

    使用_update_by_query去更新索引(适用于各专业性的单词更新)
    POST /shop/_update_by_query
    {
      "query":{
        "bool":{
          "must":[
            {"term":{"name":"凯"}},
            {"term":{"name":"悦"}}
          ]
        }
      }
    }

7.1.2 热更新词库:

elasticsearch-7.3.0-node1/config/analysis-ik/IKAnalyzer.cfg.xml

<comment>IK Analyzer 扩展配置</comment>
<!--用户可以在这里配置自己的扩展字典 -->
<entry key="ext_dict">new_word.dic</entry>
 <!--用户可以在这里配置自己的扩展停止词字典-->
<entry key="ext_stopwords"></entry>
<!--用户可以在这里配置远程扩展字典 -->
<!-- <entry key="remote_ext_dict">words_location</entry> -->
<!--用户可以在这里配置远程扩展停止词字典-->
<!-- <entry key="remote_ext_stopwords">words_location</entry> -->

Http请求需要返回两个头部,last-modified和etag(摘要)

两者任务一个发生变化则重新更新,ik一分钟检测一次

7.1.3 同义词

  • 语意相近或相同
  • 品牌类目关联
  • 搜索它等于搜索它
    elasticsearch-7.3.0-node1/config/analysis-ik
    vi synonyms.dic ,添加两行为了测试换行支持,txt后缀名应该也是可以的。
    凯悦,锡伯,红桃
    烤鸭,能吃的

    复制文件到node2、node3节点

    修改/shop索引定义

    先 DELETE /shop

    #重新定义门店索引结构,支持同义词
    PUT /shop
    {
      "settings": {
        "number_of_shards": 1, 
        "number_of_replicas": 0, //根据实际集群情况调整,此时是单节点,所以使用0
        "analysis":{ //支持同义词
          "filter":{
            "my_synonym_fiter":{ //随便取名
              "type":"synonym",
              "synonyms_path":"analysis-ik/synonyms.dic" //相对esnode/config/路径
            }
          },
          "analyzer":{
            "ik_syno":{ //自定义后要去修改下面 name 的分词器
              "type":"custom",
              "tokenizer":"ik_smart",
              "filter":["my_synonym_fiter"] 
            },
            "ik_syno_max":{
              "type":"custom",
              "tokenizer":"ik_max_word",
              "filter":["my_synonym_fiter"] 
            }
          }
        }
      },
      "mappings": {
        "properties": {
          "id":{"type": "integer"}, 
          "name":{"type": "text","analyzer": "ik_syno_max","search_analyzer": "ik_syno"}, //分词器的最佳实践,使用自定义的分词器支持同义词
          "tags":{"type": "text","analyzer": "whitespace","fielddata": true},//多个标签以空格分开;fielddata表示分词后数量的聚合,1变多,比较耗内存
          "location":{"type": "geo_point"},
          "remark_score":{"type": "double"},
          "price_per_man":{"type": "integer"},
          "category_id":{"type": "integer"},
          "category_name":{"type": "keyword"},//keyword 不分词,完全匹配
          "seller_id":{"type": "integer"},
          "seller_remark_score":{"type": "double"},
          "seller_disabled_flag":{"type": "integer"}
        }
      }
    }

    #验证同义词分析
    GET /shop/_analyze
    {
      "field": "name", 
      "text": "烤鸭"  //分成 烤鸭 能吃 的,同时分析"能吃的",也能得到3个相同分析结果,但是分析"能吃",仅能得到"能吃"
    }

    停下logstash后再修改(不停下只修改last_value_meta似乎没有重建索引)
    修改last_value_meta 不生效是不是 只填时间 不对?原来写入的是这样格式:
    --- !ruby/object:DateTime '2020-06-27 00:44:00.093633000 Z'
    再次测试。
    实测修改last_value_meta后,起始时间并不能从修改的时间开始。

    logstash启动步骤结论:
    0> 杀死进程
    1> vi last_value_meta
    2> 首次前台启动:
      /deploy-path/searchDic/elastic-search/logstash-7.3.0/bin/logstash -f /deploy-path/searchDic/elastic-search/logstash-7.3.0/bin/mysql/jdbc.conf
    3> 启动完成同步数据后,杀进程,后台重启:
       nohup /deploy-path/searchDic/elastic-search/logstash-7.3.0/bin/logstash -f /deploy-path/searchDic/elastic-search/logstash-7.3.0/bin/mysql/jdbc.conf >/dev/null &

7.1.4 重塑相关性

  • 相关性搜索
  • 让搜索引擎理解语义
  • 影响召回及排序

    #采取词性影响召回策略模型
    GET /shop/_search
    {
    //"explain": true,  //最后再使用explain调优 
    "_source": "*",
    "script_fields": {
       "distance": { // 新增定义
        "script": {
          "source": "haversin(lat,lon,doc['location'].lat,doc['location'].lon)", //半正失曲线?
          "lang": "expression",
          "params": {"lat":31.23916171,"lon":121.48789949}
        }
      }
    },
    "query": {
      "function_score": {
        "query": {
          "bool": {
            "must": [
              {
                "bool": {
                  "should": [//二选一即可
                   {"match": {"name":{"query": "住宿","boost": 0.1}}}, //boost文本再降权0.1,花悦庭果木烤鸭被拉到了第二名
                   {"term":{"category_id": {"value": 2,"boost": 0.1}}} // 2正好是酒店相关的分类,如果不是呢?
                  ]
                }
              },
              {"term":{"seller_disabled_flag": 0}} //精确匹配
            ]
          }
        },
        "functions": [
          {
            "gauss":{
              "location":{
                "origin":"31.23916171,121.48789949",
                "scale":"100km", //衰减
                "offset":"0km", //起始点
                "decay":0.5 
              }
            },
            "weight": 9 //距离对于评价来说,跟重要些
          },
          {
            "field_value_factor": {
              "field": "remark_score" //1-5分,归一化到 0-1 之间,所以设置 weight:0.2
            },
            "weight": 0.2
          },
          {
            "field_value_factor": {
              "field": "seller_remark_score"  //1-5分,归一化到 0-1 之间,所以设置 weight:0.2,但是门店评分比商家评分更重要,所以设置 商家评分seller_remark_score weight : 0.1
            },
            "weight": 0.1
          }
        ],
        "score_mode": "sum",
        "boost_mode": "sum" //replace 不考虑match文本相关性,只考虑距离和评分。本项目搜索使用replace。
      }
    },
    "sort": [
      {
        "_score": { //最后按打分排序
          "order": "desc"
        }
      }
    ]
    }
    

    核心:{"term":{"category_id": {"value": 2,"boost": 0.1}}} 这个分类的值取值方式入口:

    private Map analyzeCategoryKeyword(String keyword) throws IOException

    原理:读取 es/config/analysis-ik/synonyms.dic 下的同义词 ,或者说这里存的是相关性的词,例如:关键词:住宿 可将 酒店(categoryId=2)作为同义词,及

    测试:前端搜索 休息 --> 后档查同义词 --> 分别遍历 private Map> categoryWorkMap --> 能命中则返回对应的categoryId

    (注意:synonyms.dic中未配置休息的同义词,这里分析"休息"时,正好返回休息,休息又能匹配categoryWorkMap并返回了categoryId)

    (另外可以测试 好吃的,住宿等感受一下搜索能力)

    需要开启相关性重塑:boolean isAffectFilter = true ; 距离说明见代码中 。

八 canal索引构建

  • 准实时性
  • 性能要求
  • 编程简化要求

阿里canal

  • 消息管道
  • source为mysql数据库
  • target为其他存储

https://github.com/alibaba/canal

canal工作原理

  • canal 模拟 MySQL slave 的交互协议,伪装自己为 MySQL slave ,向 MySQL master 发送dump 协议
  • MySQL master 收到 dump 请求,开始推送 binary log 给 slave (即 canal )
  • canal 解析 binary log 对象(原始为 byte 流)

下载:

https://github.com/alibaba/canal/releases

https://github.com/alibaba/canal/releases/download/canal-1.1.4/canal.adapter-1.1.4.tar.gz

https://github.com/alibaba/canal/releases/download/canal-1.1.4/canal.deployer-1.1.4.tar.gz

scp ./canal.* root@m.jiangjiesheng.cn:/deploy-path/searchDic/elastic-search

先scp下载再上传到 /deploy-path/searchDic/elastic-search

8.1 canal服务器端自己解析binary log并完成索引构建

  1. 根据canal工作原理,先将mysql开启 Binary log:

    ```
    vi /etc/my.conf
    增加
    server-id = 1
    binlog_format = ROW
    log_bin = mysql_bin
    (mysql_bin是mysql安装路径下的相对路径。whereis mysql, which mysql)

重启
sudo service mysqld restart (https://tech.jiangjiesheng.cn/dev/study/java/mmall/backend-1/)
mysql -ujs -p密码 (或者在Navicat中执行)

show variables like 'log_bin';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_bin | ON |
+---------------+-------+
1 row in set (0.01 sec)

开设一个副本账户给salve端,即Canal端
CREATE USER canal IDENTIFIED BY 'canal';
-- 外网
GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT ON . TO 'canal'@'%' IDENTIFIED by 'canal';
-- 本地
GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT ON . TO 'canal'@'127.0.0.1' IDENTIFIED by 'canal';
-- GRANT ALL PRIVILEGES ON . TO 'canal'@'%' ;

如果指定库:
ERROR 1221 (HY000): Incorrect usage of DB GRANT and GLOBAL PRIVILEGES
错误原因
根据错误提示,可以发现一些授权时全局的权限,针对的是.,而不能单独对某个库、表授权

FLUSH PRIVILEGES;

注意:由于这里的canal好像有所有库的访问权限,所以好像所有库的数据变动都能被canal获取,方案:

  1. 指定canal账号的访问权限
  2. 在下面的 es/shop.yml 中指定 database: es-dianping
  3. 上述原因好像是因为 srcDataSources: #注意两个空格为一个单位 的空格问题导致不能被正确识别
    ```
  4. 启动canal.deployer

    解压需要先创建文件夹: 
    mkdir canal.adapter-1.1.4 
    tar -xvf canal.adapter-1.1.4.tar.gz -C canal.adapter-1.1.4
    
    mkdir canal.deployer-1.1.4
    tar -xvf canal.deployer-1.1.4.tar.gz -C canal.deployer-1.1.4
    
    https://blog.csdn.net/luckyman98/article/details/104121025/
    
    cd canal.deployer-1.1.4/conf/
    vi example/instance.properties 
    
    canal.instance.mysql.slaveId=2
    (数据库密码都正确)
    
    sh bin/startup.sh (默认已后台启动)
    tail -f ./logs/example/example.log  
    sh bin/stop.sh 
    
    验证是否启动:
    ps -ef | grep canal
    netstat -na | grep 11111 (LISTEN)
    
  5. 启动canal.adapter
    ```
    修改源码以支持es7.3.0版本
    下载源码 https://github.com/alibaba/canal
    将整个项目使用idea 打开
    将pom.xml中的elasticsearch相关包(org.elasticsearch)版本都改成7.3.0
    本次下载正好版本是7.3.0,不需要重新修改编译

    mvn package -DskipTests

    复制出 canal-master/client-adapter/launcher/target/canal-adapter/* 到 服务器上 /canal.adapter-1.1.4/

    cd canal.adapter-1.1.4/
    vi conf/application.yml

    srcDataSources: #注意两个空格为一个单位
    defaultDS:
    url: jdbc:mysql://127.0.0.1:3306/es-dianping?useUnicode=true
    username: canal
    password: canal

    ......

    • name: es
      hosts: 127.0.0.1:9300 # 127.0.0.1:9200 for rest mode
      properties:

      mode: transport # or rest

      # security.auth: test:xxxxx # only used for rest mode

      cluster.name: dianping-app

vi es/shop.yml

#注意要有空格

dataSourceKey: defaultDS

#相当于topic
destination: example
database: es-dianping #如果这里不指定数据库,好像会扫描canal有访问权限的所有库。应该是srcDataSources:的空格问题导致
groupId:
esMapping:
_index: shop
_type: _doc
_id: id
upsert: true
sql: ”select a.id,a.name,a.tags,concat(a.latitude,',',a.longitude) as location,a.remark_score,a.price_per_man,a.category_id,b.name as category_name,a.seller_id,c.remark_score as seller_remark_score,c.disabled_flag as seller_disabled_flag from shop a inner join category b on a.category_id = b.id inner join seller c on c.id = a.seller_id“
commitBatch: 3000

bin/startup.sh

验证启动情况:
tail -200f logs/adapter/adapter.log (此日志会打印dataSourceKey的连接信息)

测试 es-dianping 库的更新、插入、删除 (另外其他库的修改)

结果:更新 插入 都是支持,(插入似乎要某些字段都有值),删除能打出日志,但是不能同步到es

会有几十秒的延迟。

  1. 总结:
    目前为止,更新索引的方法有两种:
    1. 使用logstash,定时根据update_at读取最新变化的表
    2. 使用canal读取mysql的binary log,通过canal adapter在服务端接收binary log后更新,此方式有比较大缺陷:
       2.1 canal 读取到的是 changed 部分字段,会导致es中的缺少字段。
       2.2 不适合有连表场景
    
    使用Java代码接入canal:
     消息会堆积,项目启动后消费
    

8.2 Java代码获取canal的binary log日志

类似mq。Java未启动时,canal会保留未消费日志状态。

8.2.1 停用canal.adapter

  1. 停用canal.adapter
  2. canal.deployer需要保留运行.
  3. logstash关闭。
./canal.adapter-1.1.4/bin/stop.sh

添加相关jar包

<dependency>
    <groupId>com.alibaba.otter</groupId>
    <artifactId>canal.client</artifactId>
    <version>1.1.4</version>
    <exclusions>
        <exclusion>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>com.alibaba.otter</groupId>
    <artifactId>canal.common</artifactId>
    <version>1.1.4</version>
</dependency>
<dependency>
    <groupId>com.alibaba.otter</groupId>
    <artifactId>canal.protocol</artifactId>
    <version>1.1.4</version>
</dependency>

相关代码:

要确认如果java项目不运行时会不会无限堆积?

9 点评推荐原理及应用

了解个性化推荐本质及架构

掌握点评应用召回算法及实现

掌握点评应用排序算法及实现

9.1 个性化推荐

  • 千人前面
  • 场景决定推荐规则
  • 基于规则的推荐
  • 基于传统机器学习的推荐
  • 基于深度学习的推荐

推荐模型

  • 规则模型:规则定义,简单的算术公式
  • 机器学习模型训练:数据训练后的算术公式
  • 机器学习模型预测:待预测数据经过训练模型算数公式后的结果

模型评价指标

  • 离线指标:查全率,查准率,auc等
  • 在线指标:点击率,交易转化率等
  • A/B测试

架构图


业务模型

推荐系统核心

  • 召回
  • 排序

个性化召回算法ALS

  • 最小二乘法
  • 利用矩阵分解的结果无限逼近现有数据,得到隐含特征
  • 利用隐含特征预测其余结果

个性化排序算法LR

  • 逻辑回归
  • Y = ax1 + bx2 + cx3 + dx4 ...
  • 计算拟合公式

机器学习的模型实战课程

  • Spark:大规模数据处理而设置的快速通用的设计引擎
  • Spark core,Spark Sql,Spark on Hive,Spark Streaming等
  • Spark mllib: 机器学习库

ALS算法实现

引入spark-mllib_2.12 jar包,相关数据 ./资料/来自官网资料/训练数据 文件夹中

首先添加400条的门店数据:./资料/来自官网资料/训练数据/data/dml.sql

UPDATE shop set icon_url = '/static/image/shopcover/secretroom03.jpg' WHERE icon_url = ''

同时修改shop/recommend接口 返回16+1条数据,优化前端展示(16条是之前信息比较完整的门店)

./资料/来自官网资料/训练数据/data/behavior.csv

离线训练代码 cn.jiangjiesheng.dianping.recommend.AlsRecallTrain.java

cn.jiangjiesheng.dianping.recommend.AlsRecallPredict.java

资料/来自官网资料/训练数据/data/featurevalue.csv

资料/来自官网资料/训练数据/data/feature.csv

特征处理

  • 离散特征:one-hot编码
  • 连续特征:z-score标准化(x-mean)/std
  • 连续特征:max-min标准化 (x-min)/(max-min)
  • 连续特征离散化:bucket编码

重写shop/recommend接口

cn.jiangjiesheng.dianping.recommend.RecommendService.java 先召回

cn.jiangjiesheng.dianping.recommend.RecommendSortService.java 后排序

需要运行AlsRecallTrain、AlsRecallPredict 编译出文件。

常用的点击率预估步骤

  • 足够的有意义的样本
  • 足够的有意义的特征
  • 选取合适的算法训练模型
  • 使用模型再根据输入的结果预测

样本来源

  • 已有App内的数据
  • 用户模型,门店商品模型
  • 列表页,详情页,交易页的卖点和落地数据

特征分类
连续特征:例如用户年龄,门店评分等
离散特征:例如性别,分类等

特征构建

  • 连续特征处理方法:

    z-score标准化:(x-mean)/std 其中mean为均值,std为方差

    max-min标准化:(x-min)/(max-min)

    目标:将特征拍到0-1之间

特征构建

  • 离散特征处理方法:
    bucket one-hot编码

构建算法

  • ALS算法
  • LR算法
  • GBDT算法

决策树算法

  • 分类选择器
  • 多重分类选择器

如何选择树的每个节点特征?

  • 原则:越靠近上面的希望分出越多的区分度
  • 衡量:信息熵 衡量信息量的大小,也就是对随机变量不确定度的一个衡量。熵越大,不确定性越大。

    H(x)= -∑pi*logpi
  • 方法:选取熵大的节点放在上面,依次往下。

  • 离散特征直接安装分类选择进决策树

  • 连续特征可以用二分、三分、四分等方式进决策树,比如年龄小于20岁,20-50之间,50-70之间,70以上等。

决策树的缺点

  • 样本特殊过多时树的高度太高
  • 样本特征本身有问题时的过拟合

决策树的衍生

  • 随机森林

    • 随机的选择样本(返回抽样)
    • 随机的选择特征
    • 构建决策树
    • 随机森林投票(平均)
  • GBDT

    • 从初始训练集中学得一个基准学习器
    • 用基准学习器预测训练样本并且调整做错样本属性的权重
    • 反复迭代生成T个学习器
    • T个学习器串型预测加权结合

训练模型:cn.jiangjiesheng.dianping.recommend.GBDTTrain

验证效果:

  • evaluator accuracy
  • online remark
  • A/B Test
    • public List sort(List shopIdList,Integer userId,String operator){

GBDTTrain

后续如果需要代码连接es服务,配置域名9200端口

nohup打印的日志问题:

  1. 丢弃日志

    /dev/null &

  2. 2>/dev/null和>/dev/null 2>&1和2>&1>/dev/null的区别: https://blog.csdn.net/longgeaisisi/article/details/90519690

注意:
/deploy-path/searchDic/elastic-search/kibana-7.3.0-linux-x86_64/nohup.out 文件过大问题,

尝试使用cron sh 处理

echo '' > nohup.out

相关日志目录整理:

https://www.cnblogs.com/gongxq/p/11002124.html
/deploy-path/searchDic/elastic-search/xxx

/deploy-path/searchDic/elastic-search/logstash-7.3.0/logs

/deploy-path/tomcat 12 /xxx

/deploy-path/jenkins/server.log
/root/.jenkins/logs
/tmp 先研究


增加定时任务


/deployed-path/clear-l-o-g-s/auto-clear-l-o-g-s.sh 
chmod +x /deployed-path/clear-l-o-g-s/auto-clear-l-o-g-s.sh 

杀进程 ps -ef | grep auto-clear-l-o-g-s


还要分析l-o-g-file-list.txt中的文件,并修改文件名,不要有log

# http://www.matools.com/cron/
# */2 * * * * 每2分钟
#注意有些日志会被打成压缩包。
#从服务器下载
# scp root@m.jiangjiesheng.cn:/deployed-path/clear-l-o-g-s/l-o-g-file-list.txt  /Users/jiangjiesheng/Downloads/


### start ###
echo "本次任务开始,开始时间:$(date +"%Y-%m-%d %H:%M:%S")"
echo "本次记录时间:$(date +"%Y-%m-%d %H:%M:%S")"
echo "通过 tail -200f l-o-g-file-list.txt 看进度"

echo -e "本次记录时间:$(date +"%Y-%m-%d %H:%M:%S")" > /deployed-path/clear-l-o-g-s/l-o-g-file-list.txt;
echo -e "" >> /deployed-path/clear-l-o-g-s/l-o-g-file-list.txt;

echo -e "正在 删除指定日志" >> /deployed-path/clear-l-o-g-s/l-o-g-file-list.txt;
echo -e " " >> /deployed-path/clear-l-o-g-s/l-o-g-file-list.txt;
#删除指定日志
find /deploy-path/searchDic/elastic-search/canal.adapter-1.1.4/logs/adapter/ -name "*adapter.log*"  -exec rm -rf {} \;
rm -rf /usr/local/qcloud/YunJing/VulnerDetect/log.txt

echo -e "正在 删除指定的文件夹(文件夹名称不要带/)" >> /deployed-path/clear-l-o-g-s/l-o-g-file-list.txt;
echo -e " " >> /deployed-path/clear-l-o-g-s/l-o-g-file-list.txt;
#删除指定的文件夹(文件夹名称不要带/)
# find ./ -type d | grep testdir | xargs rm -rf;   注意这是模糊匹配,一定要是自己熟知内容的路径
rm -rf /tmp/*;
rm -rf /usr/local/qcloud/YunJing/log/*;
rm -rf /usr/local/qcloud/stargate/logs/*;
rm -rf /j-deploy/git-repository/mmall/CATALINA_HOME_IS_UNDEFINED/logs/*;
rm -rf /deploy-path/tomcat7/mm.jiangjiesheng.cn-1/logs/*;
rm -rf /deploy-path/tomcat7/mm.jiangjiesheng.cn-2/bin/CATALINA_HOME_IS_UNDEFINED/logs/*;
find /deploy-path/searchDic/elastic-search/canal.deployer-1.1.4/ -type d | grep logs | xargs rm -rf;
find /deploy-path/searchDic/elastic-search/elasticsearch-7.3.0-node1/ -type d | grep logs | xargs rm -rf;


echo -e "正在 删除三天前的日志" >> /deployed-path/clear-l-o-g-s/l-o-g-file-list.txt;
echo -e " " >> /deployed-path/clear-l-o-g-s/l-o-g-file-list.txt;
#删除三天前的日志
# find /opt/web/log/ -mtime +3 -name "*.log.*" -exec rm -rf {} \;
find /deploy-path/tomcat7/mm.jiangjiesheng.cn-2/logs/ -mtime +3 -name "*.log" -exec rm -rf {} \;
find /deploy-path/tomcat7/mm.jiangjiesheng.cn-2/logs/ -mtime +3 -name "*.txt" -exec rm -rf {} \;

echo -e "正在创建 需要恢复的文件" >> /deployed-path/clear-l-o-g-s/l-o-g-file-list.txt;
echo -e " " >> /deployed-path/clear-l-o-g-s/l-o-g-file-list.txt;
#需要恢复的文件
touch /deploy-path/tomcat7/mm.jiangjiesheng.cn-1/logs/catalina.out
touch /deploy-path/tomcat7/mm.jiangjiesheng.cn-2/logs/catalina.out

echo -e "正在处理 不删除,只需要清空的日志" >> /deployed-path/clear-l-o-g-s/l-o-g-file-list.txt;
echo -e " " >> /deployed-path/clear-l-o-g-s/l-o-g-file-list.txt;
#不删除,只需要清空的日志[1天前]
echo "" > /deploy-path/jenkins/server.log
echo "" > /deploy-path/searchDic/elastic-search/kibana-7.3.0-linux-x86_64/nohup.out 
find /deploy-path/ -mtime +1 -name "*.out" |awk '{print "echo > "$0}'|bash;
find /deployed-path/ -mtime +1 -name "*.out" |awk '{print "echo > "$0}'|bash;

echo -e "正在处理 最后再扫描全盘[3天前]的log文件,并记录" >> /deployed-path/clear-l-o-g-s/l-o-g-file-list.txt;
echo -e " " >> /deployed-path/clear-l-o-g-s/l-o-g-file-list.txt;
#最后再扫描全盘[3天前]的log文件,并记录
#https://blog.csdn.net/longintchar/article/details/51493562
#find ./ -name "*.cxxxx" | xargs -i cp {} ./dog/; 含义同下。
#find ./ -name "*.cxxxx" -exec cp '{}' ./dog/ \;
find / -mtime +3 -name "*log.*" -exec echo -e {} >> /deployed-path/clear-l-o-g-s/l-o-g-file-list.txt \;
find / -mtime +3 -name "*.log" -exec echo -e {} >> /deployed-path/clear-l-o-g-s/l-o-g-file-list.txt \;
find / -name "*.out" -exec echo -e {} >> /deployed-path/clear-l-o-g-s/l-o-g-file-list.txt \;

echo -e " " >> /deployed-path/clear-l-o-g-s/l-o-g-file-list.txt;
echo -e "本次任务结束,结束时间:$(date +"%Y-%m-%d %H:%M:%S")" >> /deployed-path/clear-l-o-g-s/l-o-g-file-list.txt;
echo "本次任务结束,结束时间:$(date +"%Y-%m-%d %H:%M:%S")"
### end ###

另外注意git仓库这种的,也有很多大文件 /root/.jenkins/workspace/es-dianping-APP/

 du -h --max-depth=1  //需要研究大文件问题
 du -sh * (看哪个目录占用空间大);
 https://www.php.cn/centos/450582.html



 linux查找符合条件的文件并删除
 找到根目录下所有的以test开头的文件并把查找结果当做参数传给rm -rf命令进行删除: 
 1、find / -name “test*” |xargs rm -rf 
 2、find / -name “test*” -exec rm -rf {} \; 
 3、rm -rf $(find / -name “test”)

 如果想指定递归深度,可以这样: 
 1、find / -maxdepth 3 -name “*.mp3” |xargs rm -rf 
 2、find / -maxdepth 3 -name “test*” -exec rm -rf {} \; 
 3、rm -rf $(find / -maxdepth 3 -name “test”) 
 这样只会查找三层目录中符合条件的文件并删除掉!

nginx部署相关:

#解决不同页面访问带来的相对路径错位的问题

location ^~ /image/ {
        proxy_pass http://127.0.0.1:8010/static/image/;
        expires 30d;
        }

这样两条url都能访问:

https://es-dianping.jiangjiesheng.cn/image/main_index_tuan_normal.png

https://es-dianping.jiangjiesheng.cn/static/image/main_index_home_pressed.png

TODO:
0、
收集csv importer项目

1、
导入movie 的cvs工程需要使用9300端口(由于是临时使用,也可以不做,tcp转发)
nginx -V
还有问题

记录保存:
CentOS-nginx配置Https-SSL-ngx_http_ssl_module

或者已有的编译配置参数,然后直接加载下面这句相应位置即可
参考 CentOS-nginx配置Https-SSL-ngx_http_ssl_module,同时修改此文,着重表明 nginx -V 并修改标题增加编译,获取上次编译参数。
https://blog.csdn.net/blscok/article/details/81941619),

unknown directive "stream" in /usr/local/nginx/conf/nginx.conf:134

tail -200f ../../../logs/error.log

nginx: [emerg] bind() to 118.25.49.160:3307 failed (99: Cannot assign requested address)
https://cloud.tencent.com/developer/ask/55222
https://blog.csdn.net/dbi8241/article/details/102044893

echo 'net.ipv4.ip_nonlocal_bind = 1' >> /etc/sysctl.conf
sysctl -p (sysctl -p /etc/sysctl.conf)

2、不处理
后续启动一下集群.如果集群启动成功,movie的csvImporter工程Config Class需要重新调整,movie的index的number_of_replicas重新设置为1

3、
在云笔记中重新排版一下

es的学习分开每条执行,同《6.3 点评搜索应用接入-含【搜索最终版本】.md》
重新发布git pages

4、
上线时把数据库的连接地址改成127.0.0.1

5、
再调试一下csvImporter工程使用
9300 11111端口关闭

6、备份logstash 和 canal 的config文件(有的文件在bin下) (相关项目、服务器端都整体分别打包)

7、后续所有项目都关闭 118.25.49.160(全局搜索,并在笔记中记录哪些地方使用了,后续的新项目都使用专用账户,开放专用的库权限,并收集相关sql) ip直连,关闭端口访问,数据库权限暂不回收,自己需要测试连接的话,配一个域名(不能在项目中使用,)

netstat -lnp| grep 5601 可以找到被那个进程占用

https://blog.csdn.net/liuchuanhong1/article/details/75352442
org.thymeleaf.exceptions.TemplateInputException: Error resolving template

最后还要收集项目(csvImporter) 还有nginx配置也拿出来(nginx 本身也bak一下)

最后记得要关闭仓库访问

代理数据库
https://www.cnblogs.com/Charles-Yuan/p/9738023.html
https://blog.csdn.net/bowei026/article/details/104182715
结合现有的ssl ,找文件路径

配置tcp ,貌似这样也能支持socket。

正文到此结束
本文目录