Docker安装Cassandra数据库,在SpringBoot中连接Cassandra

news2024/9/25 17:13:48

简介

Apache Cassandra是一个高度可扩展的高性能分布式数据库,旨在处理许多商用服务器上的大量数据,提供高可用性而没有单点故障。它是NoSQL数据库的一种。首先让我们了解一下NoSQL数据库的作用。

NoSQL 数据库

NoSQL数据库(有时称为“Not Only SQL”)是一种数据库,它提供了一种存储和检索关系数据库中使用的表格关系以外的数据的机制。这些数据库是无模式的,支持简单的复制,具有简单的API,最终是一致的,并且可以处理大量数据。

什么是Apache Cassandra?

Apache Cassandra是一个开源,分布式和分散/分布式存储系统(数据库),用于管理分布在世界各地的大量结构化数据。它提供高可用性服务,没有单点故障。

以下列出了Apache Cassandra的一些值得注意的地方-

  • 它具有可伸缩性,容错性和一致性。
  • 它是一个面向列的数据库。
  • 其分发设计基于亚马逊的Dynamo及其在Google的Bigtable上的数据模型。
  • 它创建于Facebook,与关系数据库管理系统截然不同。
  • Cassandra实现了Dynamo风格的复制模型,没有单点故障,但是添加了更强大的“column family”数据模型。
  • 一些大型公司(例如Facebook,Twitter,Cisco,Rackspace,ebay,Twitter,Netflix等)正在使用Cassandra。

特性:

弹性可扩展性 - Cassandra是高度可扩展的; 它允许添加更多的硬件以适应更多的客户和更多的数据根据要求。
始终基于架构 - Cassandra没有单点故障,它可以连续用于不能承担故障的关键业务应用程序。
快速线性性能 - Cassandra是线性可扩展性的,即它为你增加集群中的节点数量增加你的吞吐量。因此,保持一个快速的响应时间。
灵活的数据存储 - Cassandra适应所有可能的数据格式,包括:结构化,半结构化和非结构化。它可以根据您的需要动态地适应变化的数据结构。
便捷的数据分发 - 可以在多个数据中心之间复制数据,可以灵活地在需要时分发数据。
事务支持 - Cassandra支持属性,如原子性,一致性,隔离和持久性(ACID)。
快速写入 - Cassandra被设计为在廉价的商品硬件上运行。 它执行快速写入,并可以存储数百TB的数据,而不牺牲读取效率。

Cassandra特点

Cassandra由于其出色的技术特性而变得如此受欢迎。以下是Cassandra的一些功能:

  • 弹性可扩展性– Cassandra具有高度可扩展性;它允许添加更多硬件,以根据需求容纳更多客户和更多数据。
  • 始终在线-Cassandra没有单点故障,并且可以连续用于无法承受故障的关键业务应用程序。
  • 快速的线性规模性能-Cassandra具有线性可扩展性,即,随着集群中节点数量的增加,它可以提高吞吐量。因此,它保持了快速的响应时间。
  • 灵活的数据存储-Cassandra可容纳所有可能的数据格式,包括:结构化,半结构化和非结构化。它可以根据需要动态适应对数据结构的更改。
  • 轻松进行数据分发-Cassandra通过在多个数据中心之间复制数据,提供了在所需位置分发数据的灵活性。
  • 事务支持-Cassandra支持原子性,一致性,隔离性和持久性(ACID)等属性。
  • 快速写入-Cassandra旨在在廉价的商品硬件上运行。它执行快速的写入,并且可以存储数百TB的数据,而不会牺牲读取效率。

架构

Cassandra的设计目标是在多个节点上处理大数据工作负载而不会出现任何单点故障。 Cassandra在其节点之间具有对等分布式系统,并且数据分布在集群中的所有节点之间。

  • 集群中的所有节点都扮演相同的角色。每个节点都是独立的,并同时互连到其他节点。
  • 集群中的每个节点都可以接受读写请求,而不管数据实际位于集群中的何处。
  • 当某个节点发生故障时,可以从网络中的其他节点处理读/写请求。

Cassandra中的数据复制

在Cassandra中,集群中的一个或多个节点充当给定数据段的副本。如果检测到某些节点响应的值过时,则Cassandra会将最新值返回给客户端。返回最新值后,Cassandra在后台执行读取修复以更新过时的值。

下图显示了Cassandra如何在集群中的节点之间使用数据复制以确保没有单点故障的示意图。

Cassandra使用Gossip协议,以允许节点彼此通信并检测集群中的任何故障节点。

入门安装:使用docker-compose 安装

docker-compose.yaml

version: "3.8"
services:
  cassandra:
    image: cassandra:4.1
    container_name: cassandra
    ports:
      - 9042:9042
    volumes:
      - $PWD/commitlog:/var/lib/cassandra/commitlog
      - $PWD/hints:/var/lib/cassandra/hints
      - $PWD/data:/var/lib/cassandra/data
      - $PWD/saved_caches:/var/lib/cassandra/saved_caches
      - $PWD/logs:/var/log/cassandra

启动容器

使用如下指令启动容器:

docker-compose up -d

注意:如果如果没有在docker-compose.yaml文件所在目录或者文件名不是docker-compose.yaml,需要通过-f指定文件所在位置。即如:

docker-compose -f cassandra-start-up.yaml up -d

启动好之后,可以进入到容器之中:

➜  cassandra docker-compose up -d
Creating network "cassandra_default" with the default driver
Pulling cassandra (cassandra:4.1)...
4.1: Pulling from library/cassandra
eaead16dc43b: Pull complete
46e1869246ce: Pull complete
bbd45db92608: Pull complete
6fcfd0f47989: Pull complete
996685dfbe33: Pull complete
4927828dcc1b: Pull complete
7f67cde8352d: Pull complete
09bb07e15655: Pull complete
b8d7c6610af3: Pull complete
Status: Downloaded newer image for cassandra:4.1
Creating cassandra ... done
➜  cassandra docker ps
CONTAINER ID   IMAGE           COMMAND                  CREATED          STATUS          PORTS                                                       NAMES
cdf4f5b56a88   cassandra:4.1   "docker-entrypoint.s…"   10 minutes ago   Up 10 minutes   7000-7001/tcp, 7199/tcp, 9160/tcp, 0.0.0.0:9042->9042/tcp   cassandra
➜  cassandra docker exec -it cdf4f5b56a88 bash
root@cdf4f5b56a88:/# cqlsh
Connected to Test Cluster at 127.0.0.1:9042
[cqlsh 6.1.0 | Cassandra 4.1-beta1 | CQL spec 3.4.6 | Native protocol v5]
Use HELP for help.
cqlsh> desc keyspaces;

system       system_distributed  system_traces  system_virtual_schema
system_auth  system_schema       system_views

可以看到,我们已经通过cqlsh命令,登录到了当前的Cassandra数据库。
但是这里会有疑惑产生:

登录数据库的指令太过简单了吧?!如果需要登录指定主机地址的数据库,应该怎么设置主机地址?
登录数据库的指令不需要用户名和密码嘛?
需要的话,我的用户名和密码是什么?就目前而言,我并没有做任何设置。
如何设置用户名和密码?
 

cqlsh的基本命令 


选项    使用/作用
help    此命令用于显示有关CQLsh命令选项的帮助主题。
version    它用于查看您正在使用的CQLsh的版本。
color    它用于彩色输出。
debug    它显示其他调试信息。
execute    它用于引导shell接受并执行CQL命令。
show    显示当前会话详情

这里的options包括哪些呢? 官网写的很详细,我就不抄了,看这里 cqlsh: the CQL shell
我就挑几个最关心的看一下:

-u USERNAME --username=USERNAME
Authenticate as user.

-p PASSWORD --password=PASSWORD
Authenticate using password.

-k KEYSPACE --keyspace=KEYSPACE
Authenticate to the given keyspace.

这三个是用来指定用户名和密码以及keySpace的。

–credentials=CREDENTIALS
Specify an alternative credentials file location.

这个是用来指定credentials的。

为什么没有输入用户名和密码就直接登录了?


这里是由于没有做任何个性化配置,我们使用的相关配置是默认配置文件cassandra.yaml文件里的配置,这个配置文件在容器里的/opt/cassandra/conf目录下。这里的配置内容是
 

#AllowAllAuthenticator performs no checks - set it to disable authentication.
authenticator: AllowAllAuthenticator

当这里配置为AllowAllAuthenticator的时候,将不做任何的检查。是设置为关闭认证。
要想启用用户名密码登录,就需要将其设置为PasswordAuthenticator:

authenticator: PasswordAuthenticator

不过这个时候会发现,容器中没有vim,也没有vi,那就只能把容器里的文件copy出来,修改完再copy回去了。

docker cp cdf4f5b56a88:/opt/cassandra/conf/cassandra.yaml .

我这是把文件从容器中copy当当前位置,修改完之后再copy回去,source和destination位置互换,即:

docker cp cassandra.yaml cdf4f5b56a88:/opt/cassandra/conf/

替换完成之后,再重新启动容器:

docker restart cdf4f5b56a88

重启完之后再进入容器,再使用cqlsh指令登录,发得到如下错误:

➜  cassandra docker exec -it cdf4f5b56a88 bash
root@cdf4f5b56a88:/# cqlsh
Connection error: ('Unable to connect to any servers', {'127.0.0.1:9042': ConnectionRefusedError(111, "Tried connecting to [('127.0.0.1', 9042)]. Last error: Connection refused")})
root@cdf4f5b56a88:/#

看上面的提示,似乎也看不出来什么错误,只是connection refused。那就想着用用户名和密码尝试一下吧?由于我们没有设置用户名和密码,这个时候就只能使用系统默认设置的用户名和密码都是cassandra的账户进行登录。

root@cdf4f5b56a88:/# cqlsh -u cassandra -p cassandra

Warning: Using a password on the command line interface can be insecure.
Recommendation: use the credentials file to securely provide the password.

Connected to Test Cluster at 127.0.0.1:9042
[cqlsh 6.1.0 | Cassandra 4.1-beta1 | CQL spec 3.4.6 | Native protocol v5]
Use HELP for help.
cassandra@cqlsh>

创建新用户


cassnadra划分了三种角色类型:

xxopr: 应用账号,只能进行对表的查询、数据插入、数据删除等DML操作
xxdata: 相当于数据OWNER用户,对表空间内的对象拥有增删改查等DDL操作
cassandra: 超级用户,用于创建表空间的,DBA权限管理

这里先创建一个superuser:

create user root_cassandra with password '123456' superuser;

然后使用这个用户进行登录:

root@cdf4f5b56a88:/# cqlsh -u root_cassandra -p 123456

Warning: Using a password on the command line interface can be insecure.
Recommendation: use the credentials file to securely provide the password.

Connected to Test Cluster at 127.0.0.1:9042
[cqlsh 6.1.0 | Cassandra 4.1-beta1 | CQL spec 3.4.6 | Native protocol v5]
Use HELP for help.
root_cassandra@cqlsh> list users;

 name           | super | datacenters
----------------+-------+-------------
      cassandra |  True |         ALL
 root_cassandra |  True |         ALL

(2 rows)
root_cassandra@cqlsh>

可以看到,这里已经有两个超级用户了,不想保留cassandra这个用户的可以直接drop掉。

drop user cassandra

简单操作

既然已经到这里了,那就创建一个用户,试试简单操作先:

root_cassandra@cqlsh> create user test_data with password '123456' nosuperuser;
root_cassandra@cqlsh> exit;
root@cdf4f5b56a88:/# cqlsh -u test_data -p 123456

Warning: Using a password on the command line interface can be insecure.
Recommendation: use the credentials file to securely provide the password.

Connected to Test Cluster at 127.0.0.1:9042
[cqlsh 6.1.0 | Cassandra 4.1-beta1 | CQL spec 3.4.6 | Native protocol v5]
Use HELP for help.
test_data@cqlsh> CREATE KEYSPACE IF NOT EXISTS store WITH REPLICATION = { 'class' : 'SimpleStrategy', 'replication_factor' : '1' };
test_data@cqlsh> desc keyspaces;

store   system_auth         system_schema  system_views
system  system_distributed  system_traces  system_virtual_schema

test_data@cqlsh> desc keyspace store

CREATE KEYSPACE store WITH replication = {'class': 'SimpleStrategy', 'replication_factor': '1'}  AND durable_writes = true;
test_data@cqlsh> CREATE TABLE IF NOT EXISTS store.shopping_cart (
   ... userid text PRIMARY KEY,
   ... item_count int,
   ... last_update_timestamp timestamp
   ... );
test_data@cqlsh> INSERT INTO store.shopping_cart
   ... (userid, item_count, last_update_timestamp)
   ... VALUES ('9876', 2, toTimeStamp(now()));
test_data@cqlsh> INSERT INTO store.shopping_cart
   ... (userid, item_count, last_update_timestamp)
   ... VALUES ('1234', 5, toTimeStamp(now()));

可以看到已经创建了一个keyspace为store的库,创建了一个表shopping_cart,并插入了一些数据。查看一下表结构以及数据:

test_data@cqlsh:store> select * from store.shopping_cart;

 userid | item_count | last_update_timestamp
--------+------------+---------------------------------
   1234 |          5 | 2022-11-05 08:39:47.077000+0000
   9876 |          2 | 2022-11-05 08:39:46.226000+0000

(2 rows)
test_data@cqlsh:store> desc table shopping_cart;

CREATE TABLE store.shopping_cart (
    userid text PRIMARY KEY,
    item_count int,
    last_update_timestamp timestamp
) WITH additional_write_policy = '99p'
    AND bloom_filter_fp_chance = 0.01
    AND caching = {'keys': 'ALL', 'rows_per_partition': 'NONE'}
    AND cdc = false
    AND comment = ''
    AND compaction = {'class': 'org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy', 'max_threshold': '32', 'min_threshold': '4'}
    AND compression = {'chunk_length_in_kb': '16', 'class': 'org.apache.cassandra.io.compress.LZ4Compressor'}
    AND memtable = 'default'
    AND crc_check_chance = 1.0
    AND default_time_to_live = 0
    AND extensions = {}
    AND gc_grace_seconds = 864000
    AND max_index_interval = 2048
    AND memtable_flush_period_in_ms = 0
    AND min_index_interval = 128
    AND read_repair = 'BLOCKING'
    AND speculative_retry = '99p';
test_data@cqlsh:store>

到此完成了Cassandra的启动。 

在SpringBoot中连接Cassandra

1.添加依赖:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.14</version>
        <relativePath/>
    </parent>
    <groupId>com.example</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-cassandra</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

2.添加配置:

spring:
  data:
    cassandra:
      contact-points: localhost
      port: 9042
      keyspace-name: store
      username: root_cassandra
      password: 123456

3.添加配置类

package com.example.demo;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Component
@ConfigurationProperties(prefix = "spring.data.cassandra",
        ignoreInvalidFields = true)
public class CassandraConfigurationProperties {

    private String contactPoints;
    private int port = 9042;
    private String username;
    private String password;
    private String keyspaceName;

    public String getContactPoints() {
        return contactPoints;
    }

    public void setContactPoints(String contactPoints) {
        this.contactPoints = contactPoints;
    }

    public int getPort() {
        return port;
    }

    public void setPort(int port) {
        this.port = port;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getKeyspaceName() {
        return keyspaceName;
    }

    public void setKeyspaceName(String keyspaceName) {
        this.keyspaceName = keyspaceName;
    }
}

package com.example.demo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.cassandra.config.AbstractCassandraConfiguration;
import org.springframework.data.cassandra.config.CqlSessionFactoryBean;

@Configuration
@EnableConfigurationProperties(CassandraConfigurationProperties.class)
public class CassandraConfiguration extends AbstractCassandraConfiguration {

    @Autowired
    private CassandraConfigurationProperties cassandraConfigurationProperties;

    @Override
    protected String getKeyspaceName() {
        return cassandraConfigurationProperties.getKeyspaceName();
    }

    @Override
    protected String getContactPoints() {
        return cassandraConfigurationProperties.getContactPoints();
    }

    @Override
    protected int getPort() {
        return cassandraConfigurationProperties.getPort();
    }

    @Override
    public CqlSessionFactoryBean cassandraSession() {
        CqlSessionFactoryBean cqlSessionFactoryBean = super.cassandraSession();
        cqlSessionFactoryBean.setPassword(cassandraConfigurationProperties.getPassword());
        cqlSessionFactoryBean.setUsername(cassandraConfigurationProperties.getUsername());
        return cqlSessionFactoryBean;
    }

}

设置对应的实体类:

package com.example.demo;

import org.springframework.data.cassandra.core.cql.PrimaryKeyType;
import org.springframework.data.cassandra.core.mapping.Column;
import org.springframework.data.cassandra.core.mapping.PrimaryKeyColumn;
import org.springframework.data.cassandra.core.mapping.Table;

import java.util.Date;

@Table("shopping_cart")
public class ShoppingCart {

    @PrimaryKeyColumn(type = PrimaryKeyType.PARTITIONED)
    private String userid;
    @Column
    private int item_count;
    @Column
    private Date last_update_timestamp;

    public String getUserid() {
        return userid;
    }

    public void setUserid(String userid) {
        this.userid = userid;
    }

    public int getItem_count() {
        return item_count;
    }

    public void setItem_count(int item_count) {
        this.item_count = item_count;
    }

    public Date getLast_update_timestamp() {
        return last_update_timestamp;
    }

    public void setLast_update_timestamp(Date last_update_timestamp) {
        this.last_update_timestamp = last_update_timestamp;
    }

    @Override
    public String toString() {
        return "ShoppingCart{" +
                "userid='" + userid + '\'' +
                ", item_count=" + item_count +
                ", last_update_timestamp=" + last_update_timestamp +
                '}';
    }
}

设置接口类:

package com.example.demo;

import org.springframework.data.cassandra.repository.CassandraRepository;

public interface ShoppingCartRepo extends CassandraRepository<ShoppingCart, String> {
}

设置SpringBoot启动类:

package com.example.demo;


import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

}

编写测试代码:

package com.example.demo;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.cassandra.core.CassandraTemplate;

import java.util.List;

@SpringBootTest
class DemoApplicationTests {

    @Autowired
    private CassandraTemplate cassandraTemplate;

    @Test
    void query() {
        ShoppingCart cart = cassandraTemplate.selectOne("select * from store.shopping_cart", ShoppingCart.class);
        System.out.println(cart);
    }

    @Autowired
    private ShoppingCartRepo shoppingCartRepo;

    @Test
    void query2(){
        List<ShoppingCart> all = shoppingCartRepo.findAll();
        System.out.println(all);
    }


}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/382365.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

YOLO5-V7.0的python代码转成exe,方便离线部署

思路&#xff1a;用Pyinstaller打包&#xff0c;但有一些坑&#xff0c;踩完坑后成功运行&#xff0c;写个踩坑指南分享下。 前提&#xff1a;已经在conda 环境下安装完可以运行的yolo5代码&#xff0c;例如你的虚拟python环境叫yolo5&#xff0c;主代码是XXX.py&#xff08;这…

数字IC手撕代码--低功耗设计 Clock Gating

背景介绍芯片功耗组成中&#xff0c;有高达 40%甚至更多是由时钟树消耗掉的。这个结果的原因也很直观&#xff0c;因 为这些时钟树在系统中具有最高的切换频率&#xff0c;而且有很多时钟 buffer&#xff0c;而且为了最小化时钟 延时&#xff0c;它们通常具有很高的驱动强度。 …

《分布式技术原理与算法解析》学习笔记Day26

流量控制 什么是流量控制&#xff1f; 网络传输中的流量控制就是让发送方发送数据的速度不要太快&#xff0c;这样可以让接收方来得及接收数据&#xff0c;通常使用滑动窗口的方式来实现。 滑动窗口是指在任意时刻&#xff0c;发送方都维持一个连续的允许发送的数据大小&…

全国CSM敏捷教练认证将于2023年3月25-26开班,报名从速!

CSM&#xff0c;即Certified Scrum Master&#xff0c;是Scrum联盟发起的Scrum认证。 CSM可以帮助团队正确使用Scrum&#xff0c;从而提高项目整体成功的可能性。 CSM深刻理解Scrum的价值观、实践以及Scrum框架。 CSM是“服务型领导”&#xff0c;帮助Scrum团队一起紧密合作。 …

QT案例 Qt Creator 使用QuaZIP加密压缩解压ZIP文件

QT开发中部分项目可能会涉及对项目数据的一些指定文件的打包压缩以及指定目录下的解压&#xff0c;此时也需要对数据数据进行加密以确保数据的安全性。此时就可以使用Quazip实现相关功能。 QuaZIP是使用Qt&#xff0c;C对ZLIB进行简单封装的用于压缩ZIP以及解压缩ZIP的开源库。…

Hive表-----数据清洗

以下内容所需要的环境 &#xff1a;hive 、beeline、Zeppelin&#xff08;可视化界面如何操作表格&#xff09; 一、准备表格 1、上传csv表格至linux目录中 百度网盘自取&#xff1a;链接&#xff1a;https://pan.baidu.com/s/1xd5MdXiBDLBUtP07kpgl5Q?pwd2ema 提取码&…

python+appium+夜神模拟器(app抓包爬虫)

安装模块 pip install appium-python-client 安装andriodSDK 官网下载&#xff1a;https://android-sdk.en.softonic.com/download 自动下载一个压缩包&#xff0c;解压后就是一个文件夹放各种需要的文件&#xff0c;将解压的路径配置到环境变量中。 然后添加到path中。 下…

带你了解“函数递归”

目录 1. 什么是递归&#xff1f; 2. 函数递归的必要条件 2.1 接收一个整型值&#xff08;无符号&#xff09;&#xff0c;按照顺序打印它的每一位。 代码如下&#xff1a; 2.2 编写一个函数&#xff0c;不用临时变量求字符串长度 代码如下&#xff1a; 2.3 递归与迭代 …

爬虫之Selenium,Phantomjs,Chrome handless

爬虫之模拟浏览器前言1. Selenium1.1 Selenium介绍1.2 安装selenium1.3 Selenium访问京东1.4 Selenium元素定位1.5 seleniu访问元素信息1.6 selenium交互2. Phantomjs2.1 介绍Phantomjs2.1 使用Phantomjs3. Chrome handless3.1 Chrome handless的系统要求3.2 Chrome handless的…

STM32 E18-D80NK红外检测

本文代码使用 HAL 库。 文章目录前言一、E18-D80NK 红外传感器&#xff1a;1. E18-D80NK 的介绍2. 电器特性二、红外检测小实验代码讲解三、实验现象总结前言 这篇文章介绍 如何使用 STM32 控制 E18-D80NK 进行红外检测。 一、E18-D80NK 红外传感器&#xff1a; 1. E18-D80N…

Qt学习笔记-Qt程序中的调试日志

Qt学习笔记-Qt程序中的调试日志环境说明Qt程序中调试日志使用案例对于一门好的编程语言或者开发框架来说&#xff0c;便捷的调试日志功能是必不可少的。QT作为一个跨平台的开发工具&#xff0c;内置了便捷的调试日志功能&#xff0c;本文就对其做一个简介。环境说明 操作系统&…

测试好工具fiddler,手机抓包,查看手机app请求了哪些接口

领导让我接收一个项目&#xff0c;但是这个项目是安卓的&#xff0c;安卓我一窍不通&#xff0c;我们只做过web页面的。身为一个大数据程序员&#xff0c;要接手同事的项目&#xff0c;给我了代码&#xff0c;但是我完全不知道&#xff0c;这个代码对应&#xff0c;安卓机里面的…

Serverless 时代开启,云计算进入业务创新主战场

作者&#xff1a;于洪涛 “我们希望让用户做得更少而收获更多&#xff0c;通过 Serverless 化&#xff0c;让企业使用云服务像用电一样简单。” Serverless 化正在成为全新的软件研发范式&#xff0c;阿里云将坚定推进核心产品全面 Serverless 化&#xff0c;帮助客户更好的实现…

Jetpack Compose 深入探索系列五:State Snapshot System

Jetpack Compose 有一种特殊的方式来表示状态和传播状态变化&#xff0c;从而驱动最终的响应式体验&#xff1a;状态快照系统&#xff08;State snapshot system&#xff09;。这种响应式模型使我们的代码更加强大和简洁&#xff0c;因为它允许组件根据它们的输入自动重组&…

Zookeeper3.5.7版本——Zookeeper的概述、工作机制、特点、数据结构及应用场景

目录一、Zookeeper的概述二、Zookeeper的工作机制三、Zookeeper的特点四、Zookeeper的数据结构五、Zookeeper的应用场景5.1、统一命名服务5.2、统一配置管理5.3、统一集群管理5.4、服务器动态上下线5.5、软负载均衡一、Zookeeper的概述 Zookeeper 是一个开源的分布式的&#x…

飞桨全量支持业内AI科学计算工具——DeepXDE!

AI技术在跨学科融合创新方面扮演着日益重要的角色&#xff0c;特别是在Al for Science领域&#xff0c;AI技术的发展为跨学科、跨领域的融合创新带来了巨大的机会。AI已成为一个关键的研究工具&#xff0c;改变了基础科学的研究范式。依托AI技术开发的科学计算工具&#xff0c;…

【教学类-07-06】20230302《破译电话号码-图形篇(图形固定列不重复)》(两款输入版)

效果展示1、适合中班默写学号——有姓名 有班级&#xff0c;无学号&#xff0c;适合中班幼儿2、适合大班幼儿默写名字——有学号&#xff0c;有班级&#xff0c;无姓名&#xff0c;适合初学者描字&#xff08;小班、中班、大班&#xff09;——名字、学号、班级都有&#xff08…

Java面试总结(三)

类加载的流程 类从被加载到虚拟机内存中开始&#xff0c;到卸载出内存为止&#xff0c;它的整个生命周期包括&#xff1a;加载、验证、准备、解析、初始化、使用和卸载7个阶段。其中验证、准备、解析3个部分统称为连接。 如果想要详细了解类加载的过程&#xff0c;可以参考我…

【同步工具类:CyclicBarrier】

同步工具类:CyclicBarrier介绍源码分析CyclicBarrier 基于ReetrantLock Condition实现。构造函数await() 函数业务场景方案一:代码实现测试截图方案二代码实现测试打印总结介绍 官方介绍: 一种同步辅助工具&#xff0c;允许一组线程都等待对方到达共同的障碍点。CyclicBarrie…

完全彻底卸载Oracle

一、停止使用Oracle的服务停用oracle服务&#xff0c;进入计算机管理&#xff0c;在服务中&#xff0c;找到oracle开头的所有服务&#xff0c;右击选择停止。二、打开Universal Installer工具运行卸载Oracle数据库程序&#xff08;1&#xff09;、一般情况运行Oracle自带的卸载…