美文网首页
2021-02-14 情人节关于ES的思考

2021-02-14 情人节关于ES的思考

作者: 胖子钓鱼 | 来源:发表于2021-02-14 22:03 被阅读0次

    ES,ElasticSearch的缩写,并不特殊,特殊的是今天是西方的情人节,说起情人节,是不是最先想到的是圣瓦伦丁这位大神,一个基督徒。其实这位大哥跟情人节没什么直接关系,把情人节跟他的名字联系在一起的是英国的李白,乔叟;把情人节炒作起来的是贺卡/邮币商人还有当初做了心形巧克力的吉百利。
    ES跟数据库有些相似之处,毕竟它也来自Compass,15年前为西安的华商网做搜索,第一次用到了Lucene/Compass,到了现在搜索领域的热度远不如当年,技术上的确也有进步,对比大数据还是差了很多。ES最近我们也在用,的确是因为要把用户的使用情况这种使用日志记录下来,就是记录“某某在几月几日几点几分在系统上做了什么操作,就是系统使用日志”,为啥我们要记录这些,就是想记录之后,能够看到大家在系统上作业的过程,从流程到时间都会记录,还能让管理者更好的进行搜索也是避免一些操作型风险的产生。既然说ES跟数据库有相似之处,相似在:


    数据库-ES
    • 索引(Index): 索引与关系型数据库实例(Database)相当。索引只是一个 逻辑命名空间,它指向一个或多个分片(shards)
    • 文档类型(Type):相当于数据库中的表的概念。每个文档在ES中都必须设定它的类型。文档类型使得同一个索引中在存储结构不同文档时,只需要依据文档类型就可以找到对应的参数映射(Mapping)信息,方便文档的存取。
    • 文档(Document) :相当于数据库中的row, 是可以被索引的基本单位。例如,你可以有一个的客户文档,有一个产品文档,还有一个订单的文档。文档是以JSON格式存储的。在一个索引中,您可以存储多个的文档。
      ES主要就这些基本概念了,弄明白很容易。别问为啥能进行搜索,因为这还要借助于分词工具比如“ik_max_word”等。
    PUT my/_doc/1
     {
        "msg":"我爱北京天安门"
     }
    POST /my/_search
    {
        "query": {
            "match": {
                "msg": "北京"
            }
        }
    }
    PUT my/_mapping
    {
        "properties": {
            "msg": {
                "type": "text",
                "analyzer": "ik_max_word"
            }
        }
    }
    
    

    只要我们给定我们的标准日志格式,就能够轻松获取所有的日志。ES只是存储了这些索引,更方便进行检索。前后联动的逻辑,我们不细说了,因为都一样。

    <template>
      <div id="login">
        <el-form ref="form" :model="User" label-width="80px">
          <el-form-item label="账号">
            <el-input v-model="User.username"></el-input>
          </el-form-item>
          <el-form-item label="密码">
            <el-input v-model="User.password" type="password"></el-input>
          </el-form-item>
          <el-form-item>
            <el-button type="primary" @click="toLogin">立即登录</el-button>
            <el-button>取消</el-button>
          </el-form-item>
        </el-form>
      </div>
    </template>
    
    <script>
    const axios = require("axios");
    export default {
      name: 'login',
      data () {
        return {
          User: { //Assume user has only two attributes
            username: '',
            password: ''
          }
        }
      },
      methods: {
        toLogin () {//登录方法
          var vm = this;
          axios.post('http://localhost:8080/login', this.User)
            .then(function (response) {
              if (response.data.state == 200) {//登录成功
                vm.$notify.success({//弹窗
                  title: '登录',
                  message: '登录成功!',
                  position: 'bottom-right'
                });
            })
            .catch(function (error) {
              console.log(error)
            })
        }
      }
    }
    
    </script>
    
    <style>
    #login {
      width: 800px;
      margin: 0 auto;
      margin-top: 100px;
    }
    </style>
    

    Java的代码片段如下:

    
    @RestController
    public class LoginController {
    
        @Autowired
        private UserServiceImpl userService;
    
        /**
         * Login
         * @param response
         * @param request
         * @param user
         * @param model
         * @return
         */
        @PostMapping("/login")
        public ResponseResult Login(HttpServletResponse response , HttpServletRequest request, @RequestBody User user, Model model){
            ResponseResult responseResult=new ResponseResult();
            try {
                User my-user = userService.userlogin(request, response, user);
                if (user2!=null){
                    responseResult.setState(200);
                    responseResult.setMsg("登录成功!");
                    return responseResult;
                }
            }catch (Exception e) {
                .....
            }
        }.....
    
    UserServiceImpl.java
    @Service
    public class UserServiceImpl{
        @Autowired
        private UserDao userDao;
    
        private Map<Integer,String> UserLogin = new HashMap<>();
        @Resource
        private KafkaTemplate<String, String> kafkaTemplate;
        /**
         * 登录
         * @param request
         * @param response
         * @param u
         * @return
         */
        public User userlogin(HttpServletRequest request, HttpServletResponse response, User u){
            //查询登录是否成功
            User user=userDao.findByUsernameAndPassword(u.getUsername(),u.getPassword());
            //判断user是否为空
            if(user==null){
                return null;
            }
           kafkaTemplate.send("Kafka.topic.user", user.toString());
            return user;
        } .....
    

    只要再写个Consumer消费一下消息,并且把消息的内容ES一下即可:

    KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props);
    consumer.subscribe(Collections.singletonList("Kafka.topic.user"));
    

    说白了就是这么个过程


    VUE->Spring Controller - Kafka->ES

    当然,你完全可以通过Logstash来完成这件事,也不复杂,还是ELK的精髓所在。
    日志的来源还是靠客户端的事件获取。ES的shards是用来做集群使用的,关于集群ES倒是用不上Zookeeper了,因为自己干的就是这么个集群的事情,用分片这个词更恰当。ES可以把一个完整的索引分成多个分片,这样的好处是可以把一个大的索引拆分成多个,分布到不同的节点上。构成分布式搜索。分片的数量只能在索引创建前指定,而且索引创建后不能更改。除了分片,ES还提供Replicas,代表了索引副本,副本的作用一是提高系统的容错性,当某个节点某个分片损坏或丢失时可以从副本中恢复。二是提高ES的查询效率,能够自动对搜索请求进行负载均衡(设计的的确巧妙)。当然在实际使用的场景下,一些基本的设置还是要注意的,比如:

    • 内存:特别是机器内存大于64G的时候,还有GC,另外像Query Cache的设置,是否需要手动Flush,避免使用脚本来对ES进行线上的操作等等。
      总之,还是要在实际场景中去使用,技术才会有价值,好吧还是祝大家情人节快乐。

    相关文章

      网友评论

          本文标题:2021-02-14 情人节关于ES的思考

          本文链接:https://www.haomeiwen.com/subject/bpquxltx.html