图数据库Neo4j的基本使用及与SpringBoot集成
Neo4j
官网地址:https://neo4j.com/
下载地址:https://neo4j.com/download-center/#community
官方入门文档:https://neo4j.com/docs/getting-started
安装
Window安装
window下安装下载对应的安装包,然后配置环境变量即可。
增加系统环境变量NEO4J_HOME;
修改path环境变量增加%NEO4J_HOME%\bin
cmd 窗口执行 :neo4j console 便可以启动数据库。
C:\Users\lich0>neo4j console
2021-02-24 07:24:33.778+0000 INFO ======== Neo4j 3.5.26 ========
2021-02-24 07:24:33.795+0000 INFO Starting...
2021-02-24 07:24:37.133+0000 INFO Bolt enabled on 127.0.0.1:7687.
2021-02-24 07:24:38.110+0000 INFO Started.
2021-02-24 07:24:38.840+0000 INFO Remote interface available at http://localhost:7474/
Linux安装
下载安装包,解压后,简单修改配置文件就可以使用。云服务器的话需要放开对应的端口。
配置文件修改:
# 可以读写
dbms.read_only=false
# 可以远程访问
dbms.connectors.default_listen_address=0.0.0.0
启动服务
[root@VM-0-2-centos bin]# ./neo4j start
Active database: graph.db
Directories in use:
home: /opt/neo4j-community-3.5.26
config: /opt/neo4j-community-3.5.26/conf
logs: /opt/neo4j-community-3.5.26/logs
plugins: /opt/neo4j-community-3.5.26/plugins
import: /opt/neo4j-community-3.5.26/import
data: /opt/neo4j-community-3.5.26/data
certificates: /opt/neo4j-community-3.5.26/certificates
run: /opt/neo4j-community-3.5.26/run
Starting Neo4j.
Started neo4j (pid 20669). It is available at http://localhost:7474/
There may be a short delay until the server is ready.
See /opt/neo4j-community-3.5.26/logs/neo4j.log for current status.
查看状态
[root@VM-0-2-centos bin]# ./neo4j status
Neo4j is running at pid 20669
关闭服务
[root@VM-0-2-centos bin]# ./neo4j stop
Stopping Neo4j.. stopped
访问服务即可:http://xxxxx:7474/browser/
Docker部署
拉取镜像,启动就行了呀
拉取镜像
[root@VM-0-2-centos ~]# docker pull neo4j:3.5.26
[root@VM-0-2-centos ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/neo4j 3.5.26 27b84ff7b769 6 weeks ago 333 MB
启动容器,建议写个启动的脚本:neo4j_start.sh
这里需要注意脚本权限,映射的目录的访问权限
sudo docker run -it --name neo4j -e NEO4J_AUTH=neo4j/123456 -p 7474:7474 -p 7687:7687 \
-v /data/neo4j/data:/data \
-v /data/neo4j/neo4j/logs:/logs \
-v /data/neo4j/conf:/conf \
-v /data/neo4j/metrics:/metrics \
-v /data/neo4j/plugins:/plugins \
-v /data/neo4j/import:/import \
-d neo4j:3.5.26
查看启动的容器
[root@VM-0-2-centos neo4j]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b92f8beb7d82 neo4j:3.5.26 "/sbin/tini -g -- ..." 3 minutes ago Up 3 minutes 0.0.0.0:7474->7474/tcp, 7473/tcp, 0.0.0.0:7687->7687/tcp neo4j
访问服务即可:http://xxxxx:7474/browser/
基本概念
Node 节点
图的基本单位主要是节点和关系,节点和关系都可以包含多个k-v结构的属性。
Relationships 关系
关系的主要功能就是连接节点,一个关系连接两个节点,一个开始和一个结束节点,这种关系是有进出方向的。
Properties 属性
属性就可以理解为关系型数据库中表中的所有字段了,节点和关系都可以有多个属性,并且属性的key为字符串,值可以是其他类型例如数值,布尔
Lables 标签
标签和ES的别名是一样的作用,可以用来划分一类的节点,查询的时候可以通过标签来分类查询。
Travelsal 遍历
查询的时候往往都是遍历图谱,遍历的过程中会有一个开始节点,然后根据Cypher语句,遍历相关的节点和关系得到最终的结果
Paths 路径
路径是一个或者多个节点通过关系连接起来,例如通过Cypher查询得到的结果
Schema 模式
neo4j是类似ES一样的无模式图谱数据库,使用它无需要定义schema
Indexes 索引
和关系型数据库中的索引一样为了加快检索的速度,这里构建索引是一个异步的过程,只有创建成功后才会生效。如果创建失败可以删除后从新创建。
Constraints 约束
约束可以定义在某个字段上,限制字段值唯一,创建约束会自动创建索引
Cypher
语句cypher是neo4j官网提供的声明式查询语言,非常强大,用它可以完成任意的图谱里面的查询过滤。就好像关系型数据库中的SQL语句一样
创建节点
创建电影相关的节点
-- 创建一个节点:黑客帝国; 标签:电影;属性:标题-The Matrix,发布年份-1997
CREATE (matrix:Movie { title:"The Matrix",released:1997 })
-- 下面的同理
CREATE (cloudAtlas:Movie { title:"Cloud Atlas",released:2012 })
CREATE (forrestGump:Movie { title:"Forrest Gump",released:1994 })
创建演员相关的节点
CREATE (keanu:Person { name:"Keanu Reeves", born:1964 })
CREATE (robert:Person { name:"Robert Zemeckis", born:1951 })
CREATE (tom:Person { name:"Tom Hanks", born:1956 })
CREATE (jerry:Person { name:"Jerry", born:1986 })
创建关系
-- Tom Hanks在电影Forrest Gump中出演Forrest角色
CREATE (tom)-[:ACTED_IN { roles: ["Forrest"]}]->(forrestGump)
-- Tom Hanks在电影Forrest Gump中出演Forrest角色
CREATE (tom)-[:ACTED_IN { roles: ['Zachry']}]->(cloudAtlas)
-- jerry 在电影 The Matrix 出演 Jerry角色
CREATE (jerry)-[:ACTED_IN { roles: ["J"]}]->(matrix)
-- Robert Zemeckis指导电影Forrest Gump
CREATE (robert)-[:DIRECTED]->(forrestGump)
注意:上面创建节点,关系的语句需要同时执行后,节点才会有关联关系,如下所示:
如果你的创建节点和创建关系的语句是分开执行的话,会是如下的结果:因为创建的关系的时候没有指定节点是属性会被认为是新的节点
如果是分开创建的话,创建关系的语句应该是如下所示:
-- Tom Hanks在电影Forrest Gump中出演Forrest角色
MATCH (tom:Person{name:"Tom Hanks"}),(forrestGump:Movie{title:"Forrest Gump"}) CREATE (tom)-[:ACTED_IN { roles: ["Forrest"]}]->(forrestGump)
-- Tom Hanks在电影Forrest Gump中出演Forrest角色
MATCH (tom:Person{name:"Tom Hanks"}),(cloudAtlas:Movie{title:"Cloud Atlas"}) CREATE (tom)-[:ACTED_IN { roles: ['Zachry']}]->(cloudAtlas)
-- jerry 在电影 The Matrix 出演 Jerry角色
MATCH (jerry:Person{name:"Jerry"}),(matrix:Movie{title:"The Matrix"}) CREATE (jerry)-[:ACTED_IN { roles: ["J"]}]->(matrix)
-- Robert Zemeckis指导电影Forrest Gump
MATCH (robert:Person{name:"Robert Zemeckis"}),(forrestGump:Movie{title:"Forrest Gump"}) CREATE (robert)-[:DIRECTED]->(forrestGump)
过滤查询
查询所有节点
MATCH (nodes) return nodes
结果:
╒════════════════════════════════════════╕
│"nodes" │
╞════════════════════════════════════════╡
│{"title":"The Matrix","released":1997} │
├────────────────────────────────────────┤
│{"title":"Cloud Atlas","released":2012} │
├────────────────────────────────────────┤
│{"title":"Forrest Gump","released":1994}│
├────────────────────────────────────────┤
│{"name":"Keanu Reeves","born":1964} │
├────────────────────────────────────────┤
│{"name":"Robert Zemeckis","born":1951} │
├────────────────────────────────────────┤
│{"name":"Tom Hanks","born":1956} │
└────────────────────────────────────────┘
查询标签是Movie的节点
MATCH (m:Movie) return m
结果:
╒════════════════════════════════════════╕
│"m" │
╞════════════════════════════════════════╡
│{"title":"The Matrix","released":1997} │
├────────────────────────────────────────┤
│{"title":"Cloud Atlas","released":2012} │
├────────────────────────────────────────┤
│{"title":"Forrest Gump","released":1994}│
└────────────────────────────────────────┘
根据标题查询
-- 查询标题是The Matrix的节点
MATCH (m:Movie) WHERE m.title = "The Matrix" RETURN m
结果:
╒══════════════════════════════════════╕
│"m" │
╞══════════════════════════════════════╡
│{"title":"The Matrix","released":1997}│
└──────────────────────────────────────┘
多个条件查询
-- 条件查询 和SQL语句一样
MATCH (p:Person)-[r:ACTED_IN]->(m:Movie) WHERE p.name =~ "K.+" OR m.released > 2000 OR "Neo" IN r.roles RETURN p,r,m
结果:
╒═════════════════════════════════════════════════════════════════════════════════════════════╕
│"p" │"r" │"m" │
╞═════════════════════════════════════════════════════════════════════════════════════════════╡
│{"name":"Tom Hanks","born":1956}│{"roles":["Zachry"]}│{"title":"Cloud Atlas","released":2012}│
└─────────────────────────────────────────────────────────────────────────────────────────────┘
删除
删除所有节点和所有关系
MATCH (r)
DETACH DELETE r
根据ID删除节点及所有关系
MATCH (r)
WHERE id(r) = 493
DETACH DELETE r
结果增加列
和sql语句一样,可以给返回结果增加列
MATCH (p:Person)
RETURN p, p.name AS name, toUpper(p.name), coalesce(p.nickname,"n/a") AS nickname,
{ name: p.name, label:head(labels(p))} AS person
JSON结果:
[
{
"p": {
"identity": 65,
"labels": [
"Person"
],
"properties": {
"name": "Keanu Reeves",
"born": 1964
}
},
"name": "Keanu Reeves",
"toUpper(p.name)": "KEANU REEVES",
"nickname": "n/a",
"person": {
"name": "Keanu Reeves",
"label": "Person"
}
},
{
"p": {
"identity": 66,
"labels": [
"Person"
],
"properties": {
"name": "Robert Zemeckis",
"born": 1951
}
},
"name": "Robert Zemeckis",
"toUpper(p.name)": "ROBERT ZEMECKIS",
"nickname": "n/a",
"person": {
"name": "Robert Zemeckis",
"label": "Person"
}
},
{
"p": {
"identity": 67,
"labels": [
"Person"
],
"properties": {
"name": "Tom Hanks",
"born": 1956
}
},
"name": "Tom Hanks",
"toUpper(p.name)": "TOM HANKS",
"nickname": "n/a",
"person": {
"name": "Tom Hanks",
"label": "Person"
}
}
]
排序分页
演员按照出演电影的数量排序取前10个
MATCH (a:Person)-[:ACTED_IN]->(m:Movie)
RETURN a, count(*) AS appearances
ORDER BY appearances DESC SKIP 0 LIMIT 10;
结果:
╒════════════════════════════════╤═════════════╕
│"a" │"appearances"│
╞════════════════════════════════╪═════════════╡
│{"name":"Tom Hanks","born":1956}│2 │
├────────────────────────────────┼─────────────┤
│{"name":"Jerry","born":1986} │1 │
└────────────────────────────────┴─────────────┘
聚合统计查询
查看演员的总数量
MATCH (:Person)
RETURN count(*) AS people
结果:
╒════════╕
│"people"│
╞════════╡
│4 │
└────────┘
统计出演电影的演员
MATCH (m:Movie)<-[:ACTED_IN]-(a:Person)
RETURN m.title AS movie, collect(a.name) AS cast, count(*) AS actors
结果:
╒══════════════╤═════════════╤════════╕
│"movie" │"cast" │"actors"│
╞══════════════╪═════════════╪════════╡
│"The Matrix" │["Jerry"] │1 │
├──────────────┼─────────────┼────────┤
│"Cloud Atlas" │["Tom Hanks"]│1 │
├──────────────┼─────────────┼────────┤
│"Forrest Gump"│["Tom Hanks"]│1 │
└──────────────┴─────────────┴────────┘
UNION / WITH
union 用来组合查询的结果,查询电影的演职人员表
MATCH (actor:Person)-[r:ACTED_IN]->(movie:Movie)
RETURN actor.name AS name, type(r) AS type, movie.title AS title
UNION
MATCH (director:Person)-[r:DIRECTED]->(movie:Movie)
RETURN director.name AS name, type(r) AS type, movie.title AS title
结果:
╒═════════════════╤══════════╤══════════════╕
│"name" │"type" │"title" │
╞═════════════════╪══════════╪══════════════╡
│"Jerry" │"ACTED_IN"│"The Matrix" │
├─────────────────┼──────────┼──────────────┤
│"Tom Hanks" │"ACTED_IN"│"Cloud Atlas" │
├─────────────────┼──────────┼──────────────┤
│"Tom Hanks" │"ACTED_IN"│"Forrest Gump"│
├─────────────────┼──────────┼──────────────┤
│"Robert Zemeckis"│"DIRECTED"│"Forrest Gump"│
└─────────────────┴──────────┴──────────────┘
或者和下面的查询是等价的
MATCH (actor:Person)-[r:ACTED_IN|DIRECTED]->(movie:Movie)
RETURN actor.name AS name, type(r) AS type, movie.title AS title
WITH 关键字可以看成是查询的语句的一个子条件,主要是用来过滤数据用的,比如
查询出演次数大于一次的演员和相关的电影
MATCH (person:Person)-[:ACTED_IN]->(m:Movie)
WITH person, count(*) AS appearances, collect(m.title) AS movies
WHERE appearances > 1
RETURN person.name, appearances, movies
结果:
╒═════════════╤═════════════╤══════════════════════════════╕
│"person.name"│"appearances"│"movies" │
╞═════════════╪═════════════╪══════════════════════════════╡
│"Tom Hanks" │2 │["Cloud Atlas","Forrest Gump"]│
└─────────────┴─────────────┴──────────────────────────────┘
Springboot 集成
测试版本:2.0.3.RELEASE
引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-neo4j</artifactId>
</dependency>
配置文件application.yml
注意格式的正确
spring:
data:
neo4j:
uri: bolt://localhost:7687
username: neo4j
password: 123456
定义节点、关系对象
(省略了Get/Set等方法)
/**
* @author chenghao.li
* @Description 电影节点
*/
@NodeEntity(label = "Movie")
public class MovieGraph implements Serializable {
/**
* 主键
*/
@Id
@GeneratedValue
private Long id;
/**
* 电影标题
*/
@Property(name = "title")
private String title;
/**
* 发布年份
*/
@Property(name = "released")
private Integer released;
}
/**
* @author chenghao.li
* @Description 演员节点
*/
@NodeEntity(label = "People")
public class PeopleGraph implements Serializable {
@Id
@GeneratedValue
private Long id;
@Property(name = "name")
private String name;
@Property(name = "born")
private Integer born;
}
/**
* @author chenghao.li
* @Description 出演关系
*/
@RelationshipEntity(type = "ACTED_IN")
public class ActedInRelationShip implements Serializable {
@Id
@GeneratedValue
private Long id;
@StartNode
private PeopleGraph startNode;
@EndNode
private MovieGraph endNode;
@Property(name = "roles")
private String roles;
}
/**
* @author chenghao.li
* @Description 指导关系
*/
@RelationshipEntity(type = "DIRECTED")
public class DirectedRelationShip implements Serializable {
@Id
@GeneratedValue
private Long id;
@StartNode
private PeopleGraph startNode;
@EndNode
private MovieGraph endNode;
}
涉及到的一些注解说明:
@NodeEntity(label = "People")
表示图中的一个节点
@Id
主键ID,使用Long类型
@GeneratedValue
自动生成主键ID的值
@Property(name = "name")
表示图中节点的一个属性
@RelationshipEntity(type = "ACTED_IN")
表示图中连线的关系
定义Repository
以演员为例,继承Neo4jRepository
即可实现增删改查分页排序等操作;其他的都是如此
/**
* @author chenghao.li
*/
@Repository
public interface PeopleRepository extends Neo4jRepository<PeopleGraph, Long> {
/**
* 根据姓名查找
*
* @param name 姓名
* @return PeopleGraph
*/
@Query("MATCH (p:People) where p.name={0} return p")
PeopleGraph findByName(String name);
}
单元测试
@SpringBootTest
@RunWith(SpringRunner.class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class Neo4jApplicationTests {
@Autowired
private PeopleRepository peopleRepository;
@Autowired
private MovieRepository movieRepository;
@Autowired
private ActedInRelationShipRepository actedInRelationShipRepository;
@Autowired
private DirectedRelationShipRepository directedRelationShipRepository;
/**
* 添加演员节点
*/
@Test
public void t1() {
PeopleGraph peopleGraph1 = new PeopleGraph();
peopleGraph1.setName("Keanu Reeves");
peopleGraph1.setBorn(1964);
PeopleGraph peopleGraph2 = new PeopleGraph();
peopleGraph2.setName("Robert Zemeckis");
peopleGraph2.setBorn(1951);
PeopleGraph peopleGraph3 = new PeopleGraph();
peopleGraph3.setName("Tom Hanks");
peopleGraph3.setBorn(1956);
PeopleGraph peopleGraph4 = new PeopleGraph();
peopleGraph4.setName("Jerry");
peopleGraph4.setBorn(1986);
List<PeopleGraph> peopleGraphList = new ArrayList<>();
peopleGraphList.add(peopleGraph1);
peopleGraphList.add(peopleGraph2);
peopleGraphList.add(peopleGraph3);
peopleGraphList.add(peopleGraph4);
Iterable<PeopleGraph> peopleGraphs = peopleRepository.saveAll(peopleGraphList);
Assert.assertNotNull(peopleGraphs);
}
/**
* 添加电影节点
*/
@Test
public void t2() {
MovieGraph movieGraph1 = new MovieGraph();
movieGraph1.setTitle("The Matrix");
movieGraph1.setReleased(1997);
MovieGraph movieGraph2 = new MovieGraph();
movieGraph2.setTitle("Cloud Atlas");
movieGraph2.setReleased(2012);
MovieGraph movieGraph3 = new MovieGraph();
movieGraph3.setTitle("Forrest Gump");
movieGraph3.setReleased(1994);
List<MovieGraph> movieGraphs = new ArrayList<>();
movieGraphs.add(movieGraph1);
movieGraphs.add(movieGraph2);
movieGraphs.add(movieGraph3);
Iterable<MovieGraph> movieGraphIterable = movieRepository.saveAll(movieGraphs);
Assert.assertNotNull(movieGraphIterable);
}
/**
* 添加关系
*/
@Test
public void t3() {
// Tom Hanks在电影Forrest Gump中出演Forrest角色
PeopleGraph tom_hanks = peopleRepository.findByName("Tom Hanks");
MovieGraph forrest_gump = movieRepository.findByTitle("Forrest Gump");
ActedInRelationShip tom_ActedIn_relationShip_forrest = new ActedInRelationShip();
tom_ActedIn_relationShip_forrest.setStartNode(tom_hanks);
tom_ActedIn_relationShip_forrest.setEndNode(forrest_gump);
tom_ActedIn_relationShip_forrest.setRoles("Forrest");
ActedInRelationShip save = actedInRelationShipRepository.save(tom_ActedIn_relationShip_forrest);
Assert.assertNotNull(save);
// Tom Hanks在电影Forrest Gump中出演Forrest角色
MovieGraph cloud = movieRepository.findByTitle("Cloud Atlas");
ActedInRelationShip tom_ActedIn_relationShip_Cloud = new ActedInRelationShip();
tom_ActedIn_relationShip_Cloud.setStartNode(tom_hanks);
tom_ActedIn_relationShip_Cloud.setEndNode(cloud);
tom_ActedIn_relationShip_Cloud.setRoles("Zachry");
ActedInRelationShip save1 = actedInRelationShipRepository.save(tom_ActedIn_relationShip_Cloud);
Assert.assertNotNull(save1);
// Robert Zemeckis指导电影Forrest Gump
PeopleGraph robert_zemeckis = peopleRepository.findByName("Robert Zemeckis");
DirectedRelationShip directedRelationShip = new DirectedRelationShip();
directedRelationShip.setStartNode(robert_zemeckis);
directedRelationShip.setEndNode(forrest_gump);
DirectedRelationShip save2 = directedRelationShipRepository.save(directedRelationShip);
Assert.assertNotNull(save2);
// jerry 在电影 The Matrix 出演 J 角色
PeopleGraph jerry = peopleRepository.findByName("Jerry");
MovieGraph the_matrix = movieRepository.findByTitle("The Matrix");
ActedInRelationShip jerry_ActedIn_relationShip_matrix = new ActedInRelationShip();
jerry_ActedIn_relationShip_matrix.setStartNode(jerry);
jerry_ActedIn_relationShip_matrix.setEndNode(the_matrix);
jerry_ActedIn_relationShip_matrix.setRoles("J");
actedInRelationShipRepository.save(jerry_ActedIn_relationShip_matrix);
}
}
附报错信息
报错:检查下配置文件application.yml 是不是有多余的空格等格式问题
org.springframework.transaction.CannotCreateTransactionException: Could not open Neo4j Session for transaction; nested exception is org.neo4j.driver.v1.exceptions.AuthenticationException: Unsupported authentication token, scheme 'none' is only allowed when auth is disabled.
图数据库Neo4j的基本使用及与SpringBoot集成的更多相关文章
- 图数据库Neo4j
官网下载:https://neo4j.com/download/ 图数据库Neo4j入门:https://blog.csdn.net/gobitan/article/details/68929118 ...
- 图数据库Neo4j简介
图数据库Neo4j简介 转自: 图形数据库Neo4J简介 - loveis715 - 博客园https://www.cnblogs.com/loveis715/p/5277051.html 最近我在用 ...
- 主流图数据库Neo4J、ArangoDB、OrientDB综合对比:架构分析
主流图数据库Neo4J.ArangoDB.OrientDB综合对比:架构分析 YOTOY 关注 0.4 2017.06.15 15:11* 字数 3733 阅读 16430评论 2喜欢 18 1: 本 ...
- Hello World 之Spring Boot 调用图数据库Neo4j
明日歌 [清]钱鹤滩 明日复明日,明日何其多! 我生待明日,万事成蹉跎 1. 图数据库Neo4j之爱的初体验 ----与君初相识,犹似故人归 在如今大数据(big data)横行的时代,传统的关系型数 ...
- 开源软件:NoSql数据库 - 图数据库 Neo4j
转载自原文地址:http://www.cnblogs.com/loveis715/p/5277051.html 最近我在用图形数据库来完成对一个初创项目的支持.在使用过程中觉得这种图形数据库实际上挺有 ...
- (三)图数据库neo4j的安装配置
(一)neo4j安装 neo4j有社区版本和企业版,社区版本是免费的,企业版本是收费的.在linux上安装如下步骤: 1.将下载的neo4j-enterprise-3.4.0-unix.tar.gz包 ...
- 知识图谱之图数据库Neo4j
知识图谱中的知识是通过RDF结构来进行表示的,其基本单元是事实.每个事实是一个三元组(S, P, O),在实际系统中,按照存储方式的不同,知识图谱的存储可以分为基于表结构的存储和基于图结构的存储. 基 ...
- 图数据库neo4j和关系数据库的区别
相信您和我一样,在使用关系型数据库时常常会遇到一系列非常复杂的设计问题.例如一部电影中的各个演员常常有主角配角之分,还要有导演,特效等人员的参与.通常情况下这些人员常常都被抽象为Person类型,对应 ...
- linux环境图数据库neo4j安装
自定义yum源 Neo4j Stable Yum Repo First, you'll want our key: cd /tmp wget http://debian.neo4j.org/neote ...
随机推荐
- 连接共享打印机失败错误代码0x80070035
局域网内共享打印机非常方便,但是在连接中经常遇到问题,其中出现错误代码0x80070035的概率非常之高! 1.必须确保有关打印功能的相关服务都处于自动启动状态,重点检查TCP/IP NetBIOS ...
- js之window对象(慕课网学习笔记)
javaScript定义了一个变量一个函数都会变成window中的一个成员 var a=1; alert(window.a) //会输出a的值 window基础 创建窗口.调整窗口.移动窗口.关闭窗口 ...
- 二.Go微服务--令牌桶
1. 令牌桶 1.1 原理 我们以 r/s 的速度向桶内放置令牌,桶的容量为 b , 如果桶满了令牌将会丢弃 当请求到达时,我们向桶内获取令牌,如果令牌足够,我们就通过转发请求 如果桶内的令牌数量不够 ...
- C# 简单粗暴的毫秒转换成 分秒的格式
C# 简单粗暴的毫秒转换成 分秒的格式 1:code(网络上很多存在拷贝或者存在bug的或者不满足自己的要求) 1 public static string RevertToTime(double m ...
- AQS实现原理
AQS实现原理 AQS中维护了一个volatile int state(共享资源)和一个CLH队列.当state=1时代表当前对象锁已经被占用,其他线程来加锁时则会失败,失败的线程被放入一个FIFO的 ...
- 字符型:char
字符型:char 字符变量的定义和输出 字符变量用于存储一个单一字符,在C语言中用char表示,其中每个字符变量都会占用1个字节.在给字符型变量赋值时,需要用一对因为半角格式的单引号(' ')把字 ...
- MyBatis学习总结(四)——字段名与实体类属性名不相同的冲突的解决
表中的字段名和表对应实体类的属性名称不一定都是完全相同的,这种情况下的如何解决字段名与实体类属性名不相同的冲突.如下所示: 一.准备演示需要使用的表和数据 CREATE TABLE my_user( ...
- rtsp->rtmp 推流直播 Plan B
上篇文章我们谈到使用 EasyDarwin 推流后 前端HTML播放器 播放无画面的情况,找了各种播放器都服务正常解决,但使用VLC却能正常播放的问题,我们尝试了很久最后另辟蹊径,找到 nginx安装 ...
- Flask - 解决 app.run() 添加 host、port、debug 参数后运行不生效的问题
问题背景 app.run() 添加了 host.port.debug 参数,运行后发现没有生效,咋肥事! 解决方案 要打开 debug 模式的话,勾选 FLASK_DEBUG 就好啦 再次运行,发现已 ...
- Spring Boot中使用@Async的时候,千万别忘了线程池的配置!
上一篇我们介绍了如何使用@Async注解来创建异步任务,我可以用这种方法来实现一些并发操作,以加速任务的执行效率.但是,如果只是如前文那样直接简单的创建来使用,可能还是会碰到一些问题.存在有什么问题呢 ...