数据库设计案列分析和经验总结

设计经验总结

数据库设计最好的文章之一

掌握ER模型中的基本元素和概念,实体,关系,属性,关系,数据库范式,反范式

单人开发项目时,如果无法很快设计出全部的数据库,可以先设计简单的小部分,然后编码,这样可以提高开发效率效率,如果一直空想会浪费很多时间,任何设计都是逐步完善和迭代的,面对复杂的逻辑,大部分普通程序员都无法一下想出很好的设计方案

关系的度(Degree of a Relationship)

表示几个实体之间的关系,二元关系 ,三元关系,N元关系 ,二元回归关系(例子:无限级分类pid自关联);

在数据表中的体现是一张表中有几个外键;设计时要仔细确定各终端每个需求需要的是几元关系;

将项目拆分模块后,要对模块继续拆分,拆分到每一个页面的每个块数据,转化成具体查询思路

当一个中间表(关系)无法满足需求时,可能需要多个中间表实现;一个实体(表)可以参与到任意多个关系(中间表)中。每个关系可以联系任意多个元(实体 表),而且两个实体(表)之间也能有任意多个二元关系(中间表)。

关系的连通数(Connectivity of a Relationship)

二元(两个表) 的 一对一,一对多,多对多

多元(多个表)的一对一对一.. 一对一对多.. 一对多对多.. 多对多对多.. 可以用数学中的函数依赖表示

关系是强制的还是可以选的

数据库范式

第一范式(1NF)列值必须有具有原子性,不可分割,例如省市区或经纬度不能放到一个字段里

第二范式(2NF)一张表满足第一范式且每个非键属性完全依赖于主键。当一个属性出现在函数依赖式的右端,且函数依赖式的左端为表的主键或可由主键传递派生出的属性组,则该属性完全依赖于主键;通俗的说法就是

第三范式(3NF)一张表满足当且仅当其每个非平凡函数依赖X –> A,其中X和A可为简单或复合属性,必须满足以下两个条件之一。1. X为超键 或 2. A为某候选键的成员。若A为某候选键的成员,则A被称为主属性。注:平凡函数依赖的形式为YZ –> Z

Boyce-Codd范式(BCNF)一张表R满足Boyce-Codd范式(BCNF),若其每一条非平凡函数依赖X –> A中X为超键。

范式总结:

二三范式,多值属性,可变值属性,一张表中有多个事实描述,需要拆成多张表关联,解决插入和更新异常

bcnf范式,删除异常通过中间表加冗余字段来解决,比如删除商品后,订单中需要展示的封面图和商品名称字段不见了需要增加封面图和商品名称冗余字段来保存

范式设计是参考标准,最终以需求为准满足需求的设计才是最适合的设计,避免原教旨主义。

特殊需求反范式设计,提升查询性能

三种设置主键的思路:业务字段做主键、自增字段做主键和手动赋值字段做主键。

业务字段做主键

例用户表使用会员卡做主键,当业务需求发生变化,例如需要将A的会员卡号转给B,会造成用户关联表流水记录出现混乱,A的流水变成了B的流水

以业务字段做主键还有一个可能的后果就是,索引的叶子结点中的内容占用空间可能会比较大,一个页面可能能放入的数据更少了

自增字段做主键

单数据库应用通常使用自增id做主键,例如laravel框架默认使用自增id

当业务需求需要多个数据库分别保存数据库时,例如超市门店要求离线保存并定期最终汇总到一起,自增id就会出现冲突。

手动赋值字段做主键

手动赋值可以上述问题,在总部的数据库里保存一下当前最大id的值,然后插入之前先查询一下id的最大值

UUID和雪花ID能保证主键的唯一性,也可以解决上述需求,分布式系统常用

物理设计注意事项

varchar和char 最大行65535

text类型字段个数限制

案例分析

贝宝项目-分销

需求描述

用户和盟商创建时自动生成合伙人,合伙人分享给用户链接,用户点击分享链接时绑定为合伙人的粉丝

用户表
盟商表
合伙人表
合伙人粉丝关系表

点餐项目-手环消息推送

需求描述

用户在餐桌呼叫服务,向餐桌绑定的手环逐个发送消息。如果第一个手环的使用者响应了消息则呼叫服务成功,否则继续向下一个手环发送消息,直至超过最大调度次数。

舍得租赁电商-相机排期

共好电商-多规格SKU

统计需求汇总

总结,

查询简单对性能要求不高的直接查询返回,

查询复杂的按照展示需求单独建表统计,可以基于复杂查询语句的查询结果整个写入统计表中

更复杂的统计用ES实现

点餐统计需求

寻草订单交易量统计需求

仿京东商城数据库

Mysql 非基础常用查询方式

where in 查询结果排序

默认情况下返回结果不会按照in语句内的数据顺序排序。如果需要返回结果按照in语句内的数据顺序排序,可以通过如下方式实现。

第一种 order by FIND_IN_SET(str,strlist)

select * from test where id in (2,1,4,3,5) order by find_in_set id (id,'2,1,4,3,5')

第二种 order by SUBSTRING_INDEX(str,delim,count)

select * from test where id in (2,1,4,3,5) order by substring_index('2,1,4,3,5',id,1)

第三种 order by field

select * from test where id in (2,1,4,3,5) order by field(id,2,1,4,3,5)

一对多 关联 对查询结果 用“多”表的字段进行排序

关系是一 的表 requirement_order

关系为多的表 goods_sku 关联字段为 requirement_id

对requirement_order表进行查询并按照 goods_sku 表中 price 价格进行倒排序

select * from requirement_order ORDER BY (select goods_sku.price from goods_sku where goods_sku.requirement_id = requirement_order.id limit 1) desc
一对多限制从表条数查询,比如查出所有分类以及每个分类下n条文章

表结构如下

分类表
文章表

方法一

laravel构造器写法

$category = Category::select('id', 'name')
    ->with([
     'article'=>function ($query) {
       $query->select('id', 'cat_id', 'title', 'author')
             ->whereRaw('(select count(*) from articles as articles2 where articles2.cat_id = articles.cat_id and articles2.id >= articles.id) <= ?', [3]);
                }
    ])
    ->get();

代码执行SQL

//查询分类
select `id`,`name` from `categories`
//查询分类下文章,每个分类下3条
select
  `id`,
  `cat_id`,
  `title`,
  `author`
from
  `articles`
where
  `articles`.`cat_id` in (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
  and (
    select
      count(*)
    from
      articles as articles2
    where
      articles2.cat_id = articles.cat_id
      and articles2.id >= articles.id
  ) <= 3

如果只是查询一条的情况可以在with中使用groupBy从句

多对多限制从表条数查询,查出所有书单以及每个书单下n本书籍

表结构如下

书单表
书籍表
中间表

方法一

适用于数据量少的情况,数据多的时候查询慢

//书单模型BookList定义限制条数关联recommendBook
public function recommendBook()
{
  return $this->belongsToMany('App\Models\Book', 'book_list_has_books', 'booklist_id', 'book_id')
     ->select('books.id', 'name', 'cover', 'author')
     ->orderBy('book_list_has_books.sort', 'asc')
     ->latest('book_list_has_books.created_at')
     ->limit(10);
}

//控制器中查询
$booklists = BookList::select('id', 'title', 'position')
   ->latest()
   ->get()
   ->each(function ($booklist) {
        $booklist->load('recommendBook');
   });

代码执行SQL

循环查询

方法二

适用于从表数据量少的情况,相比第一种方法减少了查询次数,但是增加了从表数据量(因为是查所有),会占更多的用内存,可能导致内存泄露

$booklists = BookList::select('id', 'title', 'position')
  ->with([
     'listHasBook'=>function ($query) {
         $query->select('books.id', 'name', 'cover', 'author')
               ->orderBy('book_list_has_books.sort', 'asc')
               ->latest('book_list_has_books.created_at');
      }
   ])
  ->when($request->input('position'), function ($query) use ($request) {
      $query->where('position', $request->input('position'));
   })
  ->orderBy('sort', 'asc')
  ->latest()
  ->get()
  ->each(function (&$booklist) {
     $booklist->books = $booklist->listHasBook->slice(0, 10)->all();
     unset($booklist->listHasBook);
  });

执行SQL

只查询两次

如果只是查询一条的情况可以在with中使用groupBy从句

$booklist = BookList::select('id', 'title')
  ->with([
      'listHasBook'=>function ($query) {
           $query->select('books.id', 'cover')
                 ->groupBy('booklist_id');
       }
  ])

参考

https://blog.csdn.net/zdw19861127/article/details/80449691

https://bbs.csdn.net/topics/390969673?page=1

laravel with 查询列表限制条数

Ubuntu 安装 Mysql-workbench 错误

mysql-workbench
Workbench can't find libproj.so, some options may be unavailable.
/usr/bin/mysql-workbench-bin: symbol lookup error: /usr/lib/mysql-workbench/libwbprivate.so.8.0.16: undefined symbol: 
_ZN7pcrecpp2RE4InitEPKcPKNS_10RE_OptionsE

ubuntu 安装mysql-workbench-comminuty 启动之后报上述错误,

原因是gtk绘图失败,安装所有有关gdk的更新(同理可安装gtk

sudo apt install gtk*

安装之后没有效果,还是失败,最后重装解决。

18.04及后续版本没有出现此问题

Elasticsearch Mapping 和 Setting

Mapping

是定义文档及其包含的字段的存储和索引方式的过程,相当于关系型数据库中定义数据库和表结构的语句

核心数据类型 Core datatypes

  • 字符串(string) : text 和 keyword
  • 数字(numeric): long ,integer ,short byte double float half_float scaled_float
  • 日期(date): date date_nanos (纳秒)
  • 布尔(boolean)
  • 二进制 (Binary)

复杂数据类型 Complex datatypes

  • Object json对象
  • Nested 嵌套类型

Geo 数据类型 (地理位置)

专有数据类型 Specialised datatypes

  • IP IPv4 and IPv6

Range 范围

https://www.elastic.co/guide/en/elasticsearch/reference/current/range.html

数组

在Es中数组不需要专门定义,任何字段都可以包含另个或多个值即数组,数组中的所有制都必须具有相同的数据类型。

多字段 Multi-fileds

为不同的目的以不同的方式为同一字段建立索引

设置多个字段可以使用不同方式索引,使用不同的analyzer

PUT my_index
{
  "mappings": {
    "properties": {
      "city": {
        "type": "text",
        "fields": {
          "raw": { 
            "type":  "keyword"
          }
        }
   },
   "comment": {
        "type": "text",
        "fields": {
          "english_comment": { 
            "type":  "text",
             "analyzer":"english",
             "search_analyzer":"english"
          }
        }
      }
    }
  }
}

Dynamic Mapping 自动创建Mapping

创建index时,不需要定义Mapping,Es根据数据类型自动判断创建类型,优点是方便,缺点是有时后自动创建类型不是你想要的数据类型。

Mapping 字段类型修改机制

1.新增字段

Dynamic 设置为true时,一旦新增字段的文档写入,Mapping也同时被更新

Dynamic 设置为false,Mapping不会被更新,新增字段的数据无法被索引,但是信息会出现在_source中。

Dynamic设置成Strict,文档写入失败

2.已有字段,一旦已经有数据写入,就不再支持修改字段定义

Lucene实现的倒排索引,一旦生成后,就不允许修改

3.如果希望改变字段类型,必须Reindex Api,重建索引,因为如果修改了字段的数据类型,会导致已经索引的数据数据无法被搜索,新增自担不会有这种影响。

PUT movies
{
 "mappings":{
    "_doc":{
      "dynamic":"false"
    }
 }
}

自定义Mapping

1.参考API手册,纯手写

2.为了减少输入的工作量,减少出错概率,可以依靠以下步骤

  • 创建临时的index,写入一些样本数据
  • 通过访问Mapping API获取该临时文件的动态Mapping 定义
  • 修改后使用该配置创建你的索引
  • 删除临时索引

Index Options

四种不同界别的Index Options 配置,可以控制倒排索引记录的内容

  • docs – 记录doc id
  • freqs – 记录doc id 和 term frequencies
  • postions – 记录 doc id / term frequencies /term positon
  • offsets – 记录 doc id / term frequencies /term posistion / character offects

Text类型默认记录postions,其它默认为docs

记录内容越多,占用存储空间越大

null value

设置null_value 属性可以搜索null值

PUT users
{
  "mappings":{
    "properties":{
      "firstName":{
       "type":"text",
       "index":false //不索引该字段
      },
     "bio":{
       "type":"text",
       "index_options":"offsets"
     },
     "mobile":{
       "type":"text",
       "null_value":"NULL"
     }
   }
  }
}

精确值和全文本 Exact values vs Full Text

精确值不需要做分词处理

创建自定义分词器

Elasticsearch CRUD基本操作

文档CRUD

IndexPUT my_index/_doc
{“user”:”mike”,”comment”:”you know for search”}
CreatePUT my_index/_create/1
{“user”:”mike”,”comment”:”you know for search”}
POST my_index/_doc(不指定ID,自动生成)
ReadGET my_index/_doc/1
UpdatePOST my_index/_update/1
{“doc”:{“user”:”mike”,”comment”:”you know, Elasticsearch”}}
DeleteDELETE my_index/_doc/1
  • Type名,约定都用_doc ,相当于RDMBS的表名都叫_doc
  • Create—如果指定的ID已存在,会失败
  • Index—如果ID不存在,创建新的文档。否则,先删除先有的文档,再创建新的文档,版本会增加
  • Update—文档必须已经存在,更新只会对响应字段做增量修改

Bulk API

在单次API调用中执行多个索引编制或删除操作。这样可以减少开销,并可以大大提高索引速度。

支持四种类型操作 Index,Create,Update,Delete

mget

在单次请求中对一个或多个索引进行查询

msearch

在单词API请求中执行多个search

Elasticsearch 基本概念:索引 文档 REST API

ES与关系型数据库相似性对比

RDBMS(以Mysql为例)Elasitcsearch
存储引擎不同的数据分布 Setting
数据库 Schema(Database)文档字段类型 Mapping 相当于关系型数据库的表结构
数据表 Table索引 Index 类型 Type
数据行 Row文档 Document
数据列(字段) Column字段 Fields
DQL(数据查询)DSL
DML(数据操作)DSL

ps:7.0以后一个Index只能创建一个Type,并统一命名为 _doc,相当于一个数据库只能创建一个表

文档

  • Es是面向文档的搜索引擎,文档是所有可搜索数据的最小单位,相当于关系型数据库中的一条记录
  • 文档以json格式存储,json对象由字段组成对应数据类型有:字符串,数值,布尔值,日期,二进制,范围类型
  • 每个文档都有一个Unique ID 你可以自己指定 ID 或者通过Es自动生成

文档元数据

  • _index 文档所属索引名
  • _type 文档所属类型名
  • _id 文档唯一ID
  • _source 文档的原始json数据
  • _version 文档的版本信息
  • _score 相关性打分
  • _all 所有字段的整合信息,已废除

索引

文档的容器,一类文档的结合

  • Index 体现了逻辑空间的概念:每个索引都有自己的Mapping定义,用于定义包含的文档字段名和字段类型
  • Shard 体现了物理空间的概念:索引中的数据分散在Shard上

索引的Mapping和Settings

  • Mapping定义文档字段的类型
  • Setting定义不同的数据分布

索引的不同语义

  • 名词:一个ES集群中,可以创建很多不同的索引
  • 动词:保存一个文档到ES的过程也叫索引(indexing)ES中,创建一个倒排索引的过程
  • 名词:一个B tree索引,一个倒排索引

相关文章

告别类型,迎接无类型

Mysql 性能调试或监控常用指令

show processlist

官方手册 https://dev.mysql.com/doc/refman/8.0/en/show-processlist.html

如果有 SUPER 权限,则可以看到全部的线程,否则,只能看到自己发起的线程(这是指,当前对应的 MySQL 帐户运行的线程)

说明各列的含义和用途,

id列:一个标识,你要kill 一个语句的时候很有用。

user列: 显示当前用户,如果不是root,这个命令就只显示你权限范围内的sql语句。

host列:显示这个语句是从哪个ip 的哪个端口上发出的。可用来追踪出问题语句的用户。

db列:显示这个进程目前连接的是哪个数据库。

command列:显示当前连接的执行的命令,一般就是休眠(sleep),查询(query),连接(connect)

通常代表资源未释放,如果是通过连接池,sleep状态应该恒定在一定数量范围内

 实战范例:因前端数据输出时(特别是输出到用户终端)未及时关闭数据库连接,导致因网络连接速度产生大量sleep连接,在网速出现异常时,数据库too many connections挂死。

 简单解读,数据查询和执行通常只需要不到0.01秒,而网络输出通常需要1秒左右甚至更长,原本数据连接在0.01秒即可释放,但是因为前端程序未执行close操作,直接输出结果,那么在结果未展现在用户桌面前,该数据库连接一直维持在sleep状态

time列:此这个状态持续的时间,单位是秒。

state列:显示使用当前连接的sql语句的状态,很重要的列,后续会有所有的状态的描述,请注意,state只是语句执行中的某一个状态,一个sql语句,已查询为例,可能需要经过copying to tmp table,Sorting result,Sending data等状态才可以完成。

info列:显示这个sql语句,因为长度有限,所以长的sql语句就显示不全,但是一个判断问题语句的重要依据。 

这个命令中最关键的就是state列,mysql列出的状态主要有以下几种:

Checking table

正在检查数据表(这是自动的)。

Closing tables

正在将表中修改的数据刷新到磁盘中,同时正在关闭已经用完的表。这是一个很快的操作,如果不是这样的话,就应该确认磁盘空间是否已经满了或者磁盘是否正处于重负中。

Connect Out

复制从服务器正在连接主服务器。

Copying to tmp table on disk

 由于临时结果集大于 tmp_table_size,正在将临时表从内存存储转为磁盘存储以此节省内存。

索引及现有结构无法涵盖查询条件,才会建立一个临时表来满足查询要求,产生巨大的恐怖的i/o压力。

很可怕的搜索语句会导致这样的情况,如果是数据分析,或者半夜的周期数据清理任务,偶尔出现,可以允许。频繁出现务必优化之。

Copy to tmp table通常与连表查询有关,建议逐渐习惯不使用连表查询。

实战范例:

某社区数据库阻塞,求救,经查,其服务器存在多个数据库应用和网站,其中一个不常用的小网站数据库产生了一个恐怖的copy to tmp table操作,导致整个硬盘i/o和cpu压力超载。Kill掉该操作一切恢复。

Creating tmp table

正在创建临时表以存放部分查询结果。

deleting from main table

服务器正在执行多表删除中的第一部分,刚删除第一个表。

deleting from reference tables

服务器正在执行多表删除中的第二部分,正在删除其他表的记录。

Flushing tables

正在执行 FLUSH TABLES,等待其他线程关闭数据表。

Killed

发送了一个kill请求给某线程,那么这个线程将会检查kill标志位,同时会放弃下一个kill请求。MySQL会在每次的主循环中检查kill标志位,不过有些情况下该线程可能会过一小段才能死掉。如果该线程程被其他线程锁住了,那么kill请求会在锁释放时马上生效。

Locked 被其他查询锁住了

有更新操作锁定

通常使用innodb(支持行锁定)可以很好的减少locked状态的产生,但是切记,更新操作要正确使用索引,即便是低频次更新操作也不能疏忽。如上影响结果集范例所示。

在myisam的时代,locked是很多高并发应用的噩梦。所以mysql官方也开始倾向于推荐innodb。

Sending data

 正在处理 SELECT 查询的记录,同时正在把结果发送给客户端。

Sending data并不是发送数据,别被这个名字所欺骗,这是从物理磁盘获取数据的进程,如果你的影响结果集较多,那么就需要从不同的磁盘碎片去抽取数据,偶尔出现该状态连接无碍。

回到上面影响结果集的问题,一般而言,如果sending data连接过多,通常是某查询的影响结果集过大,也就是查询的索引项不够优化。

如果出现大量相似的SQL语句出现在show proesslist列表中,并且都处于sending data状态,优化查询索引,记住用影响结果集的思路去思考。

Sorting for group

正在为 GROUP BY 做排序。

Sorting for order

正在为 ORDER BY 做排序。 

        和Sending data类似,结果集过大,排序条件没有索引化,需要在内存里排序,甚至需要创建临时结构排序  

Opening tables

这个过程应该会很快,除非受到其他因素的干扰。例如,在执 ALTER TABLE 或 LOCK TABLE 语句行完以前,数据表无法被其他线程打开。 正尝试打开一个表。

Removing duplicates

正在执行一个 SELECT DISTINCT 方式的查询,但是MySQL无法在前一个阶段优化掉那些重复的记录。因此,MySQL需要再次去掉重复的记录,然后再把结果发送给客户端。

Reopen table

获得了对一个表的锁,但是必须在表结构修改之后才能获得这个锁。已经释放锁,关闭数据表,正尝试重新打开数据表。

Repair by sorting

修复指令正在排序以创建索引。

Repair with keycache

修复指令正在利用索引缓存一个一个地创建新索引。它会比 Repair by sorting 慢些。

Searching rows for update

正在讲符合条件的记录找出来以备更新。它必须在 UPDATE 要修改相关的记录之前就完成了。

Sleeping

正在等待客户端发送新请求.

System lock

正在等待取得一个外部的系统锁。如果当前没有运行多个 mysqld 服务器同时请求同一个表,那么可以通过增加 –skip-external-locking参数来禁止外部系统锁。

Upgrading lock

INSERT DELAYED 正在尝试取得一个锁表以插入新记录。

Updating

正在搜索匹配的记录,并且修改它们。

User Lock

正在等待 GET_LOCK()。

Waiting for tables

该线程得到通知,数据表结构已经被修改了,需要重新打开数据表以取得新的结构。然后,为了能的重新打开数据表,必须等到所有其他线程关闭这个表。以下几种情况下会产生这个通知:FLUSH TABLES tbl_name, ALTER TABLE, RENAME TABLE, REPAIR TABLE, ANALYZE TABLE, 或 OPTIMIZE TABLE。

waiting for handler insert

INSERT DELAYED 已经处理完了所有待处理的插入操作,正在等待新的请求。

Waiting for net, reading from net, writing to net

   偶尔出现无妨

   如大量出现,迅速检查数据库到前端的网络连接状态和流量

   案例:因外挂程序,内网数据库大量读取,内网使用的百兆交换迅速爆满,导致大量连接阻塞在waiting for net,数据库连接过多崩溃

大部分状态对应很快的操作,只要有一个线程保持同一个状态好几秒钟,那么可能是有问题发生了,需要检查一下。还有其它的状态没在上面中列出来,不过它们大部分只是在查看服务器是否有存在错误是才用得着。

show profiles
show profile for query 1

官方手册:https://dev.mysql.com/doc/refman/8.0/en/show-profile.html

show status
flush status
show global status
show engine innodb status(老版 show innodb status)

 show tables from information_schema

explain

官方手册 https://dev.mysql.com/doc/refman/8.0/en/using-explain.html

详细介绍:https://www.yangliuan.cn/?p=145

参考链接

elasticsearch 基本概念:集群 节点 分片

极客时间学习笔记

简介

elasticsearch是用java语言开发的基于lucene的全文搜索引擎。

特性

高可用,可扩展的分布式系统

服务可以用性-允许有节点停止服务

数据可用性-部分节点丢失不会丢失数据

扩展性-请求量提升/数据不断增长(将数据分不到多有节点上),水平扩容

分布式架构

不同的集群通过不同的名字区分,默认名字 “elasticsearch”,可以通过配置文件或者命令行启动时中 -E cluster.name = xxx 设定 配置文件

一个集群可以有一个或多个节点

节点

节点是一个elasticsearch的实例,本质上是一个java的进程,一台机器可以运行多个节点,生产环境建议一台机器只运行一个elasticsearch实例

每个节点都有自己的名字,通过配置文件,或者启东时 -e node.name = xxx 指定,节点启动后会分配一个UID,保存在data目录下

Master-eligible nodes 和 Master Node

每个节点启动后,默认就是一个master eligible 节点(可以通过配置关闭 node.master:false)

每一个Master-eligible节点都可以参加选主流程,成为Master节点

第一个Master-eligible节点启动时会将自己选举为Master节点

每个节点上都保存了集群的状态,只有Master节点才能修改集群的状态(大哥说了算,保持数据一致性)

集群状态中存储了必要信息 :所有节点的信息;所有索引和相关Mapping与Setting信息;分片路由信息

Data node 和 Coordinaing Node

Data node 保存数据的节点,负责保存分片数据,数据扩展时起重要作用(待补充)

Coordinating Node

负责接受Client请求,将请求分发到合适的节点,最终把结果汇总到一起,每个节点默认都起到Coordinating Node的职责

其他的节点类型

Hot & Warm Node 不同配置的Data Node,用来实现Hot & Warm 架构 降低集群部署成本,Hot高配置机器,Warm低配置机器。

Machine Learning Node 负责跑机器学习 Job ,用来做异常检测

Tribe Node 连接不同的Es集群并支持将这些集群当成一个单独集群处理后续版本将会废弃,5.3开始使用Search across clusters替代

配置节点类型

开发环境一个节点可以承担多种角色

生产环境设置单一的角色节点(dedicated node)

节点类型配置参数默认值
maste eligiblenode.mastertrue
datanode.datatrue
ingestnode.ingesttrue
coordinating only每个节点默认都是coordinating节点设置其他类型全部为false
machine learningnode.mltrue(需 enable x-pack)

分片(Primary shard & Replica Shard)

主分片,用以解决数据水平扩展的问题,通过主分片,可以将数据分布到集群内的所有节点之上

  • 一个分片是一个运行的Lucene的实例
  • 主分片数在索引创建时指定,后续不允许修改,除非Reindex

副本分片,用以解决数据高可用的问题。分片是主分片的拷贝

  • 副本分片数,可以动态的调整
  • 增加副本数,一定程度上提高服务的可用性(读取的吞吐量)

分片的设定

对于生产环境中分片的设定,需要提前做好容量规划

分片数设置过小

  • 导致后续无法增加节点实现水平扩展
  • 单个分片的数据量太大,导致数据重新分配耗时

分片数设置过大,7.0开始,默认主分片设置成1,解决了over-sharding的问题

  • 影响搜索结果的相关性打分,影响统计结果的准确性
  • 单个节点上过多的分片会导致资源浪费同事也会影响性能

查看集群状态

GET _cluster/health

{
  "cluster_name" : "elasticsearch",
  "status" : "yellow",//green主分片与副分片都正常 yellow主分片全部分配正常,有副本分片未能正常分配,red有主分片未能分配,例如当服务器磁盘容量超过85%去创建新的索引时
  "timed_out" : false,
  "number_of_nodes" : 1,
  "number_of_data_nodes" : 1,
  "active_primary_shards" : 7,
  "active_shards" : 7,
  "relocating_shards" : 0,
  "initializing_shards" : 0,
  "unassigned_shards" : 1,
  "delayed_unassigned_shards" : 0,
  "number_of_pending_tasks" : 0,
  "number_of_in_flight_fetch" : 0,
  "task_max_waiting_in_queue_millis" : 0,
  "active_shards_percent_as_number" : 87.5
}

REDIS配置详解





Redis必须是以文件路径作为第一个参数开始
redis-server /path/to/redis.conf

需要内存大小时,可以指定通常以1k 5GB 4M的形式出现,以此类推:
1k => 1000字节
1kb => 1024字节
1m => 1000000字节
1mb => 1024 * 1024字节
1g => 1000000000字节
1gb => 1024 * 1024 * 1024字节
单位不区分大小写,因此1GB 1Gb 1gB都是相同的

==INCLUDES==========================================================
在此处包含一个或多个其他配置文件。如果你这很有用有一个标准模板,可以转到所有Redis服务器,但也需要自定义一些每服务器设置。包含文件可以包括the other files,所以明智地使用它。
通知选项“include”不会被命令“CONFIG REWRITE”重写
来自admin或Redis Sentinel。由于Redis总是使用最后一次处理line作为配置指令的值,你最好把include包括在内在此文件的开头,以避免在运行时覆盖配置更改。
include /path/to/local.conf
include /path/to/other.conf

==MODULES===========================================================启动时加载模块。
如果服务器无法加载模块它会中止。可以使用多个loadmodule指令。
loadmodule /path/to/my_module.so
loadmodule /path/to/other_module.so

==NETWORK==========================================================
如果未指定“bind”配置指令,则Redis将监听来自服务器上所有可用ip的连接。可以使用只听一个或多个选定的ip
bind 192.168.1.100 10.0.0.1 
bind 127.0.0.1 ::1
bind 0.0.0.0 监听所有
port 6379 监听端口

 
默认情况下启用保护模式。
只有当您确定希望其他主机的客户端连接到Redis 时,即使未配置任何身份验证,也不应使用“bind”指令明确列出特定的接口您应该禁用它.
开启远程访问需要将此选择项改为no
protected-mode yes

此参数确定了TCP连接中已完成队列(完成三次握手之后)的长度, 当然此值必须不大于Linux系统定义的/proc/sys/net/core/somaxconn值,默认是511,而Linux的默认参数值是128。当系统并发量大并且客户端速度缓慢的时候,可以将这二个参数一起参考设定。
tcp-backlog 511

Unix socket.
指定以redis unix socket方式运行的
unixsocket /tmp/redis.sock //路径
unixsocketperm 700 //权限建议 777


客户端空闲超时时间,0表示禁用
timeout 0


tcp keepalive参数。如果设置不为0,就使用配置tcp的SO_KEEPALIVE值,使用keepalive有两个好处:检测挂掉的对端。降低中间设备出问题而导致网络看似连接却已经与对端端口的问题。在Linux内核中,设置了keepalive,redis会定时给对端发送ack。检测到对端关闭需要两倍的设置值。
tcp-keepalive 300


daemonize是用来指定redis是否要用守护线程的方式启动。 
daemonize 设置yes或者no区别
daemonize:yes:redis采用的是单进程多线程的模式。当redis.conf中选项daemonize设置成yes时,代表开启守护进程模式。在该模式下,redis会在后台运行,并将进程pid号写入至redis.conf选项pidfile设置的文件中,此时redis将一直运行,除非手动kill该进程。
daemonize:no: 当daemonize选项设置成no时,当前界面将进入redis的命令行界面,exit强制退出或者关闭连接工具(putty,xshell等)都会导致redis进程退出
daemonize yes


是否通过upstart或systemd管理守护进程。默认no没有服务监控,可选项有no ,upstart, systemd, auto
supervised no

pid文件在redis启动时创建,退出时删除。最佳实践为配置该项。
pidfile /var/run/redis_6379.pid

#配置日志级别。选项有debug, verbose, notice, warning
loglevel notice

日志名称。空字符串表示标准输出。注意如果redis配置为后台进程,标准输出中信息会发送到/dev/null
logfile /usr/local/redis/var/redis.log

是否启动系统日志记录。
syslog-enabled no

指定系统日志身份。
syslog-ident redis

指定syslog设备。必须是user或LOCAL0 ~ LOCAL7之一。
syslog-facility local0


设置数据库个数。默认数据库是 DB 0
可以通过SELECT where dbid is a number between 0 and 'databases'-1为每个连接使用不同的数据库。
databases 16