原子讲

重诺,守时

Kubernetes(通常缩写为K8s)是一个开源的容器编排平台,旨在自动化容器化应用的部署、扩展和管理。它最初由Google开发,现在由云原生计算基金会(CNCF)维护。以下是Kubernetes的基础介绍:

1. Kubernetes的核心概念

  • 容器:Kubernetes主要用于管理容器化应用,容器是一种轻量级的虚拟化技术,可以在同一操作系统上运行多个独立的应用实例。

  • Pod:Pod是Kubernetes中最小的可部署单元,通常包含一个或多个紧密相关的容器。Pod中的容器共享网络和存储资源。

  • 节点(Node):节点是Kubernetes集群中的一个工作机器,可以是物理机或虚拟机。每个节点上运行着一个Kubernetes代理(kubelet)和容器运行时(如Docker)。

  • 集群(Cluster):集群是由多个节点组成的集合,Kubernetes通过集群来管理和调度容器。

  • 控制平面(Control Plane):控制平面负责管理集群的状态,包括调度、监控和维护集群的健康。主要组件包括API服务器、调度器、控制管理器和etcd(分布式键值存储)。

2. Kubernetes的主要组件

  • API Server:Kubernetes的核心组件,提供RESTful API接口,所有的操作都通过API Server进行。

  • etcd:一个高可用的分布式键值存储,用于保存Kubernetes集群的所有数据和状态。

  • Scheduler:负责将Pod调度到合适的节点上,考虑资源需求、节点负载等因素。

  • Controller Manager:管理集群的控制循环,确保集群的实际状态与期望状态一致。

  • Kubelet:运行在每个节点上的代理,负责管理Pod的生命周期,确保容器正常运行。

  • Kube Proxy:负责网络代理和负载均衡,处理服务的网络请求。

3. Kubernetes的基本资源

  • Deployment:用于管理无状态应用的声明式更新,支持滚动更新和回滚。

  • Service:定义一组Pod的访问策略,提供负载均衡和服务发现。

  • ConfigMap:用于存储非机密的配置数据,可以在Pod中使用。

  • Secret:用于存储敏感信息(如密码、令牌等),以安全的方式提供给Pod。

  • Volume:用于持久化存储,支持多种存储后端(如NFS、云存储等)。

4. Kubernetes的工作流程

  1. 定义应用:使用YAML或JSON文件定义应用的期望状态,包括Pod、Service、Deployment等。

  2. 提交配置:将定义的配置提交到Kubernetes API Server。

  3. 调度与部署:Kubernetes Scheduler根据资源需求和策略将Pod调度到合适的节点上,Kubelet负责在节点上启动和管理容器。

  4. 监控与自愈:Kubernetes持续监控集群状态,确保实际状态与期望状态一致。如果某个Pod失败,Kubernetes会自动重启或替换它。

5. Kubernetes的优势

  • 自动化:自动化容器的部署、扩展和管理,减少人工干预。

  • 可扩展性:支持水平扩展和负载均衡,能够处理大规模的应用。

  • 自愈能力:自动监控和修复故障,确保应用的高可用性。

  • 灵活性:支持多种云环境和本地部署,适应不同的基础设施。

6. Kubernetes的生态系统

Kubernetes有一个丰富的生态系统,包含许多工具和项目,如:

  • Helm:Kubernetes的包管理工具,简化应用的部署和管理。
  • Prometheus:用于监控和告警的开源系统。
  • Istio:服务网格技术,提供微服务间的通信管理和安全性。

总结

Kubernetes是现代云原生应用的核心技术之一,提供了强大的容器编排能力。通过理解Kubernetes的基本概念和组件,开发者和运维人员可以更有效地管理和部署容器化应用。

背景

在更新一些 nvim 依赖时发现偶尔会报:git@github.com: Permission denied (publickey).,但是我已经添加过 github 秘钥配置了,使用 ssh 命令ssh -T git@github.com测试也报同样问题。

解决方案

1
ssh-add ~/.ssh/g_id_rsa # g_id_rsa为本机的github秘钥

再使用ssh -T git@github.com测试,成功!

总结

已经添加过秘钥但是还报错通常是本机的这个 git 仓库并没有和这个 SSH key 关联上,重新添加一下就好了。

在 Go 语言中,JSON(JavaScript Object Notation)和 GOB(Go Binary)是两种常用的序列化和反序列化数据的格式。encoding/json想必大家都不陌生,encoding/gob在常规 golang 的开发项目中使用频率就低了很多,两者的区别是什么?使用场景又是什么?一起来学习下。

JSON 与 GOB 的区别

对比维度 JSON GOB
可读性 JSON 是一种文本格式,易于阅读和理解。它使用键值对的形式表示数据,并使用大括号和方括号来表示对象和数组。 GOB 是一种二进制格式,不可读,主要用于在 Go 程序之间高效地传输和存储数据。
兼容性 JSON 是一种通用的数据交换格式,可以被多种编程语言解析和生成。 GOB 是 Go 语言特有的格式,只能在 Go 程序之间进行序列化和反序列化。
数据类型支持 JSON 支持基本数据类型(如字符串、数字、布尔值)、数组、对象和 null 值。 GOB 支持 Go 语言的所有数据类型,包括结构体、切片、映射、通道等。
序列化效率 JSON 的序列化和反序列化相对较慢,占用较多的存储空间和网络带宽。 由于 GOB 是二进制格式,相对于 JSON,它在序列化和反序列化过程中更高效,占用更少的存储空间和网络带宽。
跨语言支持 由于 JSON 是一种通用格式,可以被多种编程语言解析和生成,因此在不同语言之间进行数据交换更方便。 GOB 只能在 Go 语言程序之间使用,不适用于跨语言的数据交换。

总结:JSON 是一种通用的、可读性强的数据交换格式,适用于跨语言的数据交换。而 GOB 是 Go 语言特有的、高效的二进制格式,适用于在 Go 程序之间进行数据传输和存储。选择使用哪种格式取决于你的具体需求和使用场景。

GOB 具体使用场景

  1. Go 程序之间的通信:如果你有多个 Go 程序之间需要进行数据交换,使用 GOB 可以实现高效的序列化和反序列化,减少数据传输的开销。

  2. 数据持久化:如果你需要将 Go 程序中的数据持久化到磁盘或数据库中,使用 GOB 可以将数据以二进制格式进行存储,占用更少的存储空间,并且读写速度更快。

  3. 缓存数据:如果你需要将数据缓存在内存中,以提高读取速度,使用 GOB 可以将数据以二进制格式进行序列化,并在需要时快速反序列化,提高缓存的效率。

  4. 分布式系统:如果你正在构建分布式系统,需要在不同的节点之间传输数据,使用 GOB 可以实现高效的数据传输,减少网络带宽的占用。

  5. RPC(远程过程调用):如果你使用 Go 语言的 RPC 框架进行远程过程调用,GOB 是默认的序列化格式,可以方便地进行数据传输和调用。

总结:GOB 适用于在 Go 程序之间高效地传输和存储数据的场景,特别是在需要高性能和低开销的情况下。

项目要求:存储流水信息,通过 ID 查询流水内容。

在对比 clickhouse、hbase、es 后,选择了 hbase 作为流水存储 db,宽表存储,价格实惠,除了需要学习下使用方法。

基础知识流程图

2023 年,经历过数次微博、抖音的卸载安装操作后,最终我每日临幸的 APP 分成了两个设备群:

  • 手机:小红书、微博、王者荣耀

  • Pad:抖音

    我很忙,我真的很忙。每天都要给自己洗脑,从睁眼到入睡,无数的内容占据了我的时间,吃饭会看一会、去卫生间看一会,下班回家先摊着刷会抖音,不知不觉时间就从 20:00 跳到了 23:59,你问我这期间获取到了什么消息?答:阿巴阿巴阿巴…..

    相信有这种体验的不止我一个人,为此我们可以做些什么呢?

    1. 找一项日常的事情,坚持一个月。比如:每天背 10 个单词、读一篇好文、锻炼 30 分钟……习惯形成之后,成就感随之而来;
    2. 化碎片信息为整。每天挨个浏览的信息,按照目前大部分 APP 都有的推荐算法逻辑,大多会分为几类,对于我来说便是:摄影、萌宠、穿搭以及美食这几个大类,在结束一天的碎片化信息获取之后,我将使用思维导图的方式,把有意义的内容记录下来,太过重复的内容则使用 APP 自身的不感兴趣方式挪出我的推荐池,过滤电子垃圾;
    3. 主动检索。碎片化信息对我思维能力、记忆能力的影响很大,多采用主动出击的方式,了解自己需要的内容,避免被动的接收信息导致大脑不断刷新内存;
    4. 多接触现实生活,比如有意义有主题的社交、多参与拥抱大自然活动,从外部汲取能量。

    光阴似箭,日月如梭真是老生常谈了,现在到退休还有好几十年,希望多做一些有意义的事情吧!

为了确保安全与速度,除了增、删、改之外,我们通常不直接对数据库进行操作,而是利用 redis 或者 mencache 等缓存机制获取数据。如何使用 redis 进行搜索呢?本文通过姓名/拼音首字母搜索人物基本信息实例叙述两种 redis 搜索方式,适用的情况也有所不同。

环境

LNMP/Redis

方法一

将所有人物信息存入一个 string 格式的 key(user_all)中,搜索时遍历查找 key 的内容。

实例中将人物的 id(uid)、姓名(name)、拼音首字母(spell)等信息存入 user_all 键。

代码如下:

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
function search() {
$con = $_POST['con']; //接收搜索信息

//连接本地的 Redis 服务
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);

$ret = json_decode($redis->get('user_all'), TRUE);//获取user_all所有数据
if (empty($ret)) {
return false;
}
$searchInfos = array();

//从第一位往后匹配
foreach ($ret as $k => $v) {
if (strpos($v['name'], $con) === 0 || strpos($v['spell'], strtoupper($con)) === 0) {
$searchInfos[] = $v;
}
}
if ($searchInfos) {
return $searchInfos;
} else {
return false;
}
}

注意:使用 get(key)的方式获取到的数据格式可能是 object(stdClass),遍历时需要用访问对象的方式获取数据,因此使用 json_decode($content, TRUE)函数将其变为 array 格式。

方法二

将每个人物的信息分别存入 string 格式的 key(以 prefixname_uid,prefix_spell_uid 的形式,如 user路飞_001,user_LF_001)中,通过 keys()对键名进行模糊查询,以获取人物信息。

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function search() {
$con = $_POST['con']; //接收搜索信息

//连接本地的 Redis 服务
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);

$ret = $redis->keys('user_' . $con . '*');//获取所有匹配数据
if (empty($ret)) {
return false;
}
$searchInfos = array();

foreach ($ret as $k => $v) {
$searchInfos[] = $redis->get($v);
}
if ($searchInfos) {
return $searchInfos;
} else {
return false;
}
}

两种方法比较

两种方式均能获得搜索结果,也都有各自的优缺点:

第一种方式,进行增加、删除、修改操作时都需进行数据库查询,获取所有人物信息,添加到 user_all 键中,查询时直接进行字符串匹配;
第二种方式,需要对 redis 键进行全部查询操作,不适用于键特别多的情况。

其他

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//除掉字符串中的标点符号
function spellReplace($spell) {
$char = "。、!?:;﹑•"…‘’“”〝〞∕¦‖— 〈〉﹞﹝「」‹›〖〗】【»«』『〕〔》《﹐¸﹕︰﹔!¡?¿﹖﹌﹏﹋'´ˊˋ―﹫︳︴¯_ ̄﹢﹦﹤‐­˜﹟﹩﹠﹪﹡﹨﹍﹉﹎﹊ˇ︵︶︷︸︹︿﹀︺︽︾ˉ﹁﹂﹃﹄︻︼()# #";
$pattern = array(
"/[[:punct:]]/i", //英文标点符号
'/[' . $char . ']/u', //中文标点符号
'/[ ]{2,}/'
);
$str = preg_replace($pattern, '', $spell);
return $str;
}
//获取拼音首字母,如yuan zi jiang =>YZJ
function spellChar($spell) {
$new_name = '';
$nword = explode(" ", $spell);
foreach ($nword as $letter) {
$new_name .= $letter{0};
}
return strtoupper($new_name);
}

摘要

作为一个初入 PHP、偶尔写一点后台管理系统的前端部分的小菜鸟,需要学习的东西真的太多太多。
     循序渐进,本月研读了 Pro PHP and jQuery 这本书,印象深刻,所以趁热打铁整理了一些对前后端联调很有用的小 Tips。

后台向前端传值方式:1、模板输出(smarty); 2、ajax 函数回调;

写在最前

为了防止 PHP 中的变量符$与jQuery冲突,本文代码中jQuery与正常情况使用jQuery时的$等价。

准备工作

获取数据

即传送给后端的数据,多数为表单内容。

1
2
3
4
5
jQuery('.content').html();  //获取标签内所有内容,包括html符号等
jQuery('.content').text(); //获取标签内所有文本
jQuery('.content').val(); //获取value值
jQuery(this).parent().find('.content').text(); //在当前元素的父元素中查找content类,并获取文本值
jQuery(this).attr('type'); //获取当前元素type属性的值

前端数据验证

为防止前端频繁访问后台,加大服务器压力,前端需进行数据验证。

空值判断

手机号、电子邮件等:使用正则表达式验证
提醒式验证:如“确定删除”,可以使用 confirm()等方法
验证失败可弹出提示或重定位界面。

ajax 传值

前端验证成功后就可以向后台请求数据了,jQuery 给我们封装了 ajax 方法,多数操作将是 success 回调函数中完成。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
jQuery.ajax({
type: 'post', //传值方式,post/get
url: '/gxapi/rank', //请求地址
dataType: "json", //传送数据格式,json是前后端常用传值数据格式
data: {content: content, type: type}, //要传送的数据值{后端接受字段名称:前端发送字段名称},通常另两者名称相等。
success: funtion (res) {
if(res.code) {
//有数据的操作,多在此更改局部数据
...
}else{
//请求失败,多为未登录、无数据等
...
}
}
});

注意:1、浏览器可以自动识别 json 数据,web 应用可以不用设置;2、如果涉及移动端,则必须设置 json 格式;3、跨域请求数据需设置 dataType 格式为 jsonp。

碎片功能

点击事件

  • 点击某元素触发事件,如增加、删除、编辑等。

通过模板渲染所得的页面,可以直接对 dom 元素进行操作,例如:

1
2
3
4
jQuery('.btn').click(function () {
//点击事件后续操作
...
});
  • 通过动态生成得到的界面,操作 dom 元素时需要绑定元素,下面的例子中,list 类是非动态生成的元素,我们将 delete 点击事件绑定到该元素上,例:
1
2
3
4
jQuery('.list').on('click', '.delete', function () {
//点击事件后续操作
...
});
  • 其中 click 可以更改为 change、hover 等,在对列表进行操作时常用。另外还有一种方式,适用于 jQuery 版本较低的场景。
1
2
3
4
jQuery(".list").delegate(".delete", "click", function () {
//点击事件后续操作
...
});

需要注意的是,这两个方法的 click 位置不同。

数据处理

  • 保留小数点后两位:Number(num).toFixed(2)
  • 遍历:可用于批量操作
1
2
3
4
 jQuery.each(res.data, function (i, item) {
//批量操作、结合append()生成列表行等
...
});

注意:当遍历 dom 元素时一定要注意在遍历前元素已经生成。

其他小技巧

  • 前端获取到数据后可以存在 display:none 的标签里,便于以后使用。
  • 要更改样式最简单的方法还是通过 css,故我们可以通过给元素添加 class 并设置 class 的值来批量更改样式。
0%