东风草堂博客

公众号:开发者来风

MySQL 体系结构

  • 连接层
    最上层是一些客户端和链接服务,主要完成一些类似于连接处理、授权认证、及相关的安全方案。服务器也会为安全接入的每个客户端验证它所具有的操作权限。
  • 服务层
    第二层架构主要完成大多数的核心服务功能,如 SQL 接口,并完成缓存的查询, SQL 的分析和优化,部分内置函数的执行。所有跨存储引擎的功能也在这一层实现,如过程、函数等。
  • 引擎层
    存储引擎真正的负责了 MySQL 中数据的存储和提取,服务器通过 API 和存储引擎进行通信。不同的存储引擎具有不同的功能,这样我们可以根据自己的需要,来选取合适的存储引擎。
  • 存储层
    主要是将数据存储在文件系统之上,并完成与存储引擎的交互。

show create table account,查看建表语句,engine指定存储引擎。show engins查询支持的引擎。

InnoDB

阅读全文 »


传统的缓存策略一般是请求到达 Tomcat 后,先查询 Redis ,如果未命中则查询数据库,存在下面的问题:

  • 请求要经过 Tomcat 处理, Tomcat 的性能成为整个系统的瓶颈
  • Redis 缓存失效时,会对数据库产生冲击

多级缓存方案

用作缓存的 Nginx 是业务 Nginx ,需要部署为集群,再有专门的 Nginx 用来做反向代理(proxy_pass+upstream配置):

缓存在日常开发中启动至关重要的作用,由于是存储在内存中,数据的读取速度是非常快的,能大量减少对数据库的访问,减少数据库的压力。我们把缓存分为两类:

  • 分布式缓存,例如 Redis :
    • 优点:存储容量更大、可靠性更好、可以在集群间共享.缺点:访问缓存有网络开销
    • 场景:缓存数据量较大、可靠性要求较高、需要在集群间共享
  • 进程本地缓存,例如 HashMap 、 GuavaCache :
    • 优点:读取本地内存,没有网络开销,速度更快·缺点:存储容量有限、可靠性较低、无法共享
    • 场景:性能要求较高,缓存数据量较小
阅读全文 »

单点redis问题

  • 数据丢失,实现redis持久化
  • 并发能力,主从集群,读写分离
  • 故障恢复,哨兵机制,健康监测,自动恢复
  • 存储能力,分片集群,插槽机制实现动态扩容

redis持久化

rdb,redis数据备份文件,实现持久化。
save命令开启,主进程阻塞完成。bgsave后台完成。停机时自动执行rdb。
redis.conf可以配置,save 900 1表示900秒内,如果至少一个key被修改,则执行bgsave,如果是save “”,则表示禁用rdb。dbfilename和dir也可以配置文件名和目录,rdbcompression可以配置是否压缩,但会消耗cpu。


bgsave开始时会fork主进程得到子进程,子进程共享主进程的内存数据,完成fork后读取内存数据写入rgb文件。fork采用copy-on-write技术,读操作访问共享内存,写操作拷贝数据执行写操作,所以极端情况所有数据都被修改了,可能内存会翻倍。

阅读全文 »

在 CentOS 系统上安装 Google Chrome 浏览器,可以按照以下步骤进行:

添加 Google Chrome 的 YUM 源
在终端中输入以下命令:

sudo tee /etc/yum.repos.d/google-chrome.repo <<-‘EOF’
[google-chrome]
name=google-chrome - $basearch
baseurl=http://dl.google.com/linux/chrome/rpm/stable/$basearch
enabled=1
gpgcheck=1
gpgkey=https://dl.google.com/linux/linux_signing_key.pub
EOF
安装 Google Chrome
输入以下命令进行安装:

yum -y install google-chrome-stable –nogpgcheck
启动 Google Chrome
在终端中输入以下命令启动 Google Chrome 浏览器:

google-chrome
这样就可以在 CentOS 系统上安装和使用 Google Chrome 浏览器了,输入法安装:https://www.google.cn/intl/zh-CN/inputtools/chrome/index.html。

阅读全文 »

go server

1
data: something happend!\n\n

第二个 \n 表示这个 event 结束,可以发给客户端了。第一个 \n 主要是为了有时要传输多行数据时,例如传个 json:

1
2
3
data: {\n
data: "foo": "bar"\n
data: }\n\n

上面都属于 message 这个类型,如果想发送别的类型可以通过 event 字段自定义:

阅读全文 »

网络模式

docker的默认网络模式的bridge,有个问题,docker内部无法直接与另外的docker内的端口进行通信,改为host模式即可。如果不改网络模式的话,要么不走http,改为走uds通信就可以。

1
2
3
services:
nginx:
network_mode: "host"

镜像推送

1
2
3
4
docker build . -t REPOSITORY:TAG
docker tag IMAGEID(镜像id) REPOSITORY:TAG(仓库:标签)
docker login
docker push nephen2023/chatgpt-next-web

+——————————————-+
| Server |
| (single-threaded, event-driven etc) |
+——————————————-+
| Processor |
| (compiler generated) |
+——————————————-+
| Protocol |
| (JSON, compact etc) |
+——————————————-+
| Transport |
| (raw TCP, HTTP etc) |
+——————————————-+

Transport

Transport传输层为从网络读取/向网络写入提供了一个简单的抽象。这使 Thrift 能够将底层传输与系统的其余部分分离(例如,序列化/反序列化)
Transport接口:

  • open
  • close
  • read
  • write
  • flush

除了上面的 Transport 接口之外,Thrift 还使用了一个 ServerTransport 接口,用于接受或创建原始传输对象。顾名思义,ServerTransport 主要用于服务器端,为传入连接创建新的传输对象

阅读全文 »

https://docs.midjourney.com/docs/invite-the-bot,可以将机器人拉入到自己的群中,这样消息不会被淹没。

api下载mj生成的图片:https://medium.com/@neonforge/how-to-create-a-discord-bot-to-download-midjourney-images-automatically-python-step-by-step-guide-3e76d3282871
api自动发送mj消息:https://medium.com/@neonforge/how-to-automate-midjourney-image-generation-with-python-and-gui-automation-ac9ca5f747ae

discord生成应用:https://discord.com/developers/applications
discord开发手册:https://discord.com/developers/docs/interactions/application-commands

1
2
3
4
5
Action shot.An Asian little boy sitting on a flying pterosaur .Close-Up.surreal photography. 

A 10 year old Chinese girl wearing a fiery red dress and a large fiery phoenix, 16k, ultra detailed, ultra realistic, captured by a Fuji camera,, --iw 2 --ar 3:4 --v 5.2

A lively and cute Chinese girl interacts with a huge flower in a surreal setting, 6 year old girl, looks like Angelababy, the art of Hitoko Kawauchi, natural poses, dadcore for vacation, energy and pressure of youth, body extension, simulation film in the sky, super detail, dreamlike high photography. A riot of colour, shot on fujifilm XT4,3d, c4d,hd, oc renderer, cinematic lighting, super detail, 8k, super detail --s 350 --ar 3:4

网页重定向

网页迟迟没有被google收录,进入https://search.google.com/发现:

在 Nuxt.js 中,您可以通过设置 generate.subFolders 选项来控制生成的文件是否应该包含子目录。默认情况下,该选项的值为 true,这意味着生成的文件将被放置在相应的路由目录中。

如果您不想要生成的文件包含子目录,并直接生成 HTML 文件,您可以将 generate.subFolders 设置为 false。您可以在 nuxt.config.js 文件中添加以下配置:

1
2
3
4
5
export default {
generate: {
subFolders: false
}
}
阅读全文 »

服务器TNonblockingServer

rpc请求生成task放入到任务队列中,这个任务是Runnable的,但没有依附于某个thread,等于是封装了个run函数,供线程池工作线程调用时运行的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
void addTask(stdcxx::shared_ptr<Runnable> task) {
threadManager_->add(task, 0LL, taskExpireTime_);
}

stdcxx::shared_ptr<Runnable> task = stdcxx::shared_ptr<Runnable>(
new Task(processor_, inputProtocol_, outputProtocol_, this));
server_->addTask(task);

// 真正的任务,其实也是一个run函数,这个Runnable是没有thread实体的
class TNonblockingServer::TConnection::Task : public Runnable {
public:
Task(stdcxx::shared_ptr<TProcessor> processor,
stdcxx::shared_ptr<TProtocol> input,
stdcxx::shared_ptr<TProtocol> output,
TConnection* connection)
: processor_(processor),
input_(input),
output_(output),
connection_(connection),
serverEventHandler_(connection_->getServerEventHandler()),
connectionContext_(connection_->getConnectionContext()) {}

void run() {
try {
for (;;) {
if (serverEventHandler_) {
serverEventHandler_->processContext(connectionContext_, connection_->getTSocket());
}
if (!processor_->process(input_, output_, connectionContext_)
|| !input_->getTransport()->peek()) {
break;
}
}
} catch (const TTransportException& ttx) {
GlobalOutput.printf("TNonblockingServer: client died: %s", ttx.what());
} catch (const std::bad_alloc&) {
GlobalOutput("TNonblockingServer: caught bad_alloc exception.");
exit(1);
} catch (const std::exception& x) {
GlobalOutput.printf("TNonblockingServer: process() exception: %s: %s",
typeid(x).name(),
x.what());
} catch (...) {
GlobalOutput.printf("TNonblockingServer: unknown exception while processing.");
}

// Signal completion back to the libevent thread via a pipe
if (!connection_->notifyIOThread()) {
GlobalOutput.printf("TNonblockingServer: failed to notifyIOThread, closing.");
connection_->server_->decrementActiveProcessors();
connection_->close();
throw TException("TNonblockingServer::Task::run: failed write on notify pipe");
}
}

TConnection* getTConnection() { return connection_; }

private:
stdcxx::shared_ptr<TProcessor> processor_;
stdcxx::shared_ptr<TProtocol> input_;
stdcxx::shared_ptr<TProtocol> output_;
TConnection* connection_;
stdcxx::shared_ptr<TServerEventHandler> serverEventHandler_;
void* connectionContext_;
};

线程池管理ThreadManager

线程池的管理,包括增加工作线程worker,这个worker线程是继承自Runnable的,依附于具体的线程thread,还有就是增加任务,上面说到了server是怎么调用这个增加任务的接口的。注意worker和task都是继承自runnable,一个有依附的thread,一个没有,都要实现run函数。

阅读全文 »
0%