当前位置: 首页 > 编程日记 > 正文

Varnish purges 缓存清除

Varnish的缓存清除非常复杂。无论是Varnish的清除方式还是清除时候使用的语法规则等,都是比较复杂。为了理解他,我花费了不少时间,现在我很高兴我知道怎么来解释给大家听了。
1、Varnish有两种方式来清除缓存,其中一种方式是通过命中对象的单一变体,所以在他命中一个没有压缩的对象的时候他不能清除一个已经压缩的对象。这个方式也就是强制过期(forced expiry),他是通过设置你想清除的对象的TTL为0去强制它过期。VCL设置如下:

acl purge {
"localhost";
"192.0.2.14";
}
sub vcl_recv {
if (req.request == "PURGE") {
if (!client.ip ~ purge) {
error 405 "Not allowed.";
}
lookup;
}
}
sub vcl_hit {
if (req.request == "PURGE") {
set obj.ttl = 0s;
error 200 "Purged.";
}
}
sub vcl_miss {
if (req.request == "PURGE") {
error 404 "Not in cache.";
}
}

2、另外一种方式是使用purge_url,VCL设置如下:

acl purge {
"localhost";
"192.0.2.14";
}
sub vcl_recv {
if (req.request == "PURGE") {
if (!client.ip ~ purge) {
error 405 "Not allowed.";
}
purge("req.url == " req.url);
}


通过以上在VCL文件的设置,我们通过HTTP来执行PURGE。这意味着你现在发送了一个:

PURGE / HTTP/1.0
Host: www.example.com

通过80端口给了Varnish。但是,这种执行PURGE的方式不支持正则。如果你想支持,可以按照这样来设置VCL:

acl purge {
"localhost";
"192.0.2.14";
}
sub vcl_recv {
if (req.request == "PURGE") {
if (!client.ip ~ purge) {
error 405 "Not allowed.";
}
purge("req.url ~ " req.url);
}

3、对于purge的方式,除了像上边第2点那样设置VCL来允许PURGE外,其实我们还可以通过Varnish的管理端口发送灵活的PURGE命令来清除缓存。
3.1 首先让我们来看看管理端口的help(Varnish版本2.1)

[root@varnish4 varnish]# telnet 192.168.1.185 3500
Trying 192.168.1.185...
Connected to 192.168.1.185 (192.168.1.185).
Escape character is '^]'.
200 154     
-----------------------------
Varnish HTTP accelerator CLI.
-----------------------------
Type 'help' for command list.
Type 'quit' to close CLI session.
help
200 377     
help [command]
ping [timestamp]
auth response
quit
banner
status
start
stop
stats
vcl.load <configname> <filename>
vcl.inline <configname> <quoted_VCLstring>
vcl.use <configname>
vcl.discard <configname>
vcl.list
vcl.show <configname>
param.show [-l] [<param>]
param.set <param> <value>
purge.url <regexp>
purge <field> <operator> <arg> [&& <field> <oper> <arg>]...
purge.list

3.2 help中和purge有关的命令有三个,其中purge.list是查看purge的列表,能执行purge的是purge.url和purge两个命令。
3.2.1 purge.url命令它只支持url的purge,如清除http://blog.izhoufeng.com/test.html。

[root@varnish2 varnish]# telnet 192.168.1.185 3500
Trying 192.168.1.185...
Connected to varnish1 (192.168.1.185).
Escape character is '^]'.
200 154     
-----------------------------
Varnish HTTP accelerator CLI.
-----------------------------
Type 'help' for command list.
Type 'quit' to close CLI session.
purge.url test.html
200 0

除用CLI接口外也可以用:

/usr/local/varnish-2.1/bin/varnishadm -T 192.168.1.185:3500 purge.url ^test.html$

3.2.2 purge命令则很灵活,请看列子:
清除http://izhoufeng.com/somedirectory/和目录下的所有页面。

purge req.http.host == izhoufeng.com && req.url ~ ^/somedirectory/.*$
or
purge req.url ~ ^/somedirectory/ && req.http.host == izhoufeng.com

清除所有带“Cache-Control: max-age=3600”的对象。

purge obj.http.Cache-Control ~ max-age=3600
or
purge obj.http.Cache-Control ~ max-age ?= ?3600[^0-9]

4、对于大量清除,需要程序接口来做。
4.1 通过HTTP的PURGE的接口。

<?php
//刷新varnish缓存的函数,$ip为varnish服务器IP地址, $host为要刷新的网站域名,$url为要刷新的不含域名的URL地址
function varnish_purge($ip, $host, $url)   
{   
$errstr = '';   
$errno = '';
$fp = fsockopen ($ip, 80, $errno, $errstr, 10);
if (!$fp)   
{   
return false;   
}   
else  
{   
$out = "PURGE {$url} HTTP/1.1\r\n";   
$out .= "Host:{$host}\r\n";   
$out .= "Connection: close\r\n\r\n";   
fputs ($fp, $out);   
$out = fgets($fp , 4096);
fclose ($fp);   
return true;   
}   
}   
//用法:假设 192.168.1.185(varnish1)和192.168.1.186(varnish2)是两台varnish缓存服务器的内网IP地址,http://blog.izhoufeng.com/housing1d/08041110_2372147.htm为要刷新的地址
varnish_purge("varnish1", "blog.izhoufeng.com", "/housing1d/08041110_2372147.htm");
varnish_purge("varnish2", "blog.izhoufeng.com", "/housing1d/08041110_2372147.htm");
?>

4.2 通过Varnish的管理端口的接口。
对下边接口,先建立表把需要PURGE的URL放入表内。

mysql> show create table dirty_url;
+-----------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table     | Create Table                                                                                                                                                                                                                                                                                                           |
+-----------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| dirty_url | CREATE TABLE `dirty_url` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`url` varchar(600) NOT NULL,
`is_done` tinyint(2) NOT NULL DEFAULT '0',
`ip` varchar(15) NOT NULL,
`time` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `is_done` (`is_done`)
) ENGINE=InnoDB AUTO_INCREMENT=20627685 DEFAULT CHARSET=utf8 |
+-----------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
mysql> select * from dirty_url limit 10;
+----------+---------------------------------------------------------------+---------+-----------------+---------------------+
| id       | url                                                           | is_done | ip              | time                |
+----------+---------------------------------------------------------------+---------+-----------------+---------------------+
| 20544199 | http://blog.izhoufeng.com/xianzhilipin/10040810_3231622.htm         |       0 | 192.168.1.186  | 2010-04-08 10:43:11 |
| 20544200 | http://blog.izhoufeng.com/yingyouyunfu/10040810_3231623.htm         |       0 | 192.168.1.186  | 2010-04-08 10:43:11 |
| 20544201 | http://blog.izhoufeng.com/ershoubijibendiannao/10040810_3231624.htm |       0 | 192.168.1.186  | 2010-04-08 10:43:11 |
| 20544202 | http://blog.izhoufeng.com/zhaoshangjiameng/10032610_2222213.htm     |       0 | 192.168.1.186 | 2010-04-08 10:43:11 |
| 20544203 | http://blog.izhoufeng.com/fushixiaobaxuemao/10040810_3231625.htm    |       0 | 192.168.1.186  | 2010-04-08 10:43:11 |
| 20544204 | http://blog.izhoufeng.com/wupinjiaohuan/10040810_3231626.htm        |       0 | 192.168.1.186  | 2010-04-08 10:43:11 |
| 20544205 | http://blog.izhoufeng.com/fushixiaobaxuemao/10040810_3231627.htm    |       0 | 192.168.1.186  | 2010-04-08 10:43:11 |
| 20544206 | http://blog.izhoufeng.com/wupinjiaohuan/10040810_3231628.htm        |       0 | 192.168.1.186  | 2010-04-08 10:43:11 |
| 20544207 | http://blog.izhoufeng.com/qitawupin/10040810_3231629.htm            |       0 | 192.168.1.186  | 2010-04-08 10:43:11 |
| 20544208 | http://blog.izhoufeng.com/shoujitongxun/10040810_3231630.htm        |       0 | 192.168.1.186  | 2010-04-08 10:43:11 |
+----------+---------------------------------------------------------------+---------+-----------------+---------------------+
<?php
//error_reporting(E_ALL);
//ini_set("log_errors", "1");
//ini_set("display_errors", "0");
set_time_limit(0);
$adminHost[0] = "192.168.1.185"; // IP address to connect to
$adminHost[1] = "192.168.1.186"; // IP address to connect to
$adminHost[2] = "192.168.1.187"; // IP address to connect to
$adminPort = "3500"; // Port to connect to
function pollServer($command,$adminHost,$adminPort) {
$socket = socket_create(AF_INET, SOCK_STREAM, getprotobyname("tcp"));
if ((!socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, Array("sec" => "5", "usec" => "0"))) OR (!socket_set_option($socket, SOL_SOCKET, SO_SNDTIMEO, Array("sec" => "5", "usec" => "0")))) {
die("Unable to set socket timeout");
}
if (@socket_connect($socket, $adminHost, $adminPort)) {
$data = "";
if (!$socket) {
die("Unable to open socket to " . $server . ":" . $port . "\n");
}
socket_write($socket, $command . "\n");
socket_recv($socket, $buffer, 65536, 0);
$data .= $buffer;
socket_close($socket);
return $data;
}
else {
return "Unable to connect: " . socket_strerror(socket_last_error()) . "\n";
}
}
//this function is to add the web into varnish
function socketHttpGet($url,$hostIp)
{
$urlInfo = parse_url($url);
$urlInfo["path"] = ($urlInfo["path"] == "" ? "/" : $urlInfo["path"]);
$urlInfo["port"] = (!isset($urlInfo["port"]) ? 80 : $urlInfo["port"]);
$urlInfo["request"] =  $urlInfo["path"] .
(empty($urlInfo["query"]) ? "" : "?" . $urlInfo["query"]) .
(empty($urlInfo["fragment"]) ? "" : "#" . $urlInfo["fragment"]);
$fsock = fsockopen($hostIp, $urlInfo["port"], $errno, $errstr, 10);
if (false == $fsock) {
return false;
}
/* begin get  */
$in = "GET " . $urlInfo["request"] . " HTTP/1.0\r\n";
$in .= "Host: " . $urlInfo["host"] . "\r\n";
$in .= "Accept: */*\r\n";
$in .= "Accept-Language: zh-CN\r\n";
$in .= "Accept-Encoding: gzip, deflate\r\n";
$in .= "Accept-Language: zh-CN\r\n";
$in .= "User-Agent: Mozilla/4.0 (Auto add the Web to Varnish)\r\n";
$in .= "Cache-Control: no-cache\r\n";
$in .= "Connection: close\r\n\r\n";
//stream_set_timeout($fsock, 10);
if (!fwrite($fsock, $in, strlen($in))) {
fclose($fsock);
return false;
}
unset($in);
//fclose($fsock);return;
//process response
$out = "";
while ($buff = fgets($fsock, 2048)) {
$out .= $buff;
}
//finish socket
fclose($fsock);
$pos = strpos($out, "\r\n\r\n");
$head = substr($out, 0, $pos);
return $head;
}
//now to purge from the mysql
while(true)
{
$conn=mysql_connect("192.168.1.186","username","password");
mysql_query("set names utf8");
mysql_select_db("queue",$conn);
$query="select url,id from dirty_url where is_done =0 order by id asc limit 200";
$results=mysql_query($query);
while($arr=mysql_fetch_array($results))
{
$url=parse_url($arr['url']);
$purge_url="purge.url ".$url['path'];
$stats=0;
foreach($adminHost as $value)
{
$result=pollServer($purge_url,$value,$adminPort);
$status = explode(" ", $result);
if($status[0]=="200")
{
//socketHttpGet($arr['url'],$value);
$stats++;
}
}
if($stats==3)
{
$ups="update dirty_url set is_done =1 where id=$arr[id]";
mysql_query($ups);
}
}
sleep(1);
}
?>

我想接口固然是接口,但是如果到大型网站,每天刷新量有10多万,就需要用到多线程来做了,下图就是我开发的刷新程序,希望能给大家些启发。

5、对于PURGE的几种方式,原理都一样,我们可以从purge.list的输出结果就可以看出。
5.1 用2大点中用VCL来控制刷新,然后通过HTTP发送PURGE命令的日志如下:

  384   req.url == /fang5/10040721_93041.htm
0   req.url == /jiajiao/10040721_25874.htm
0   req.url == /fang5/10040721_530212.htm
0   req.url == /jiaoyou9/10040721_3814.htm
0   req.url == /fang1/10040721_152079.htm
0   req.url == /fang5/10040721_284698.htm
0   req.url == /fang1/10040721_625739.htm
0   req.url == /fang5/10040721_388442.htm
0   req.url == /fang1/10040721_450056.htm
0   req.url == /fang5/10040721_704267.htm
0   req.url == /fang5/10040721_704266.htm
0   req.url == /fang1/10040721_625738.htm
0   req.url == /fang5/10040721_704265.htm
0   req.url == /fang1/10040721_71558.htm
0   req.url == /fang5/10040721_226345.htm
0   req.url == /fang5/10040721_121378.htm
0   req.url == /fang1/10040721_818489.htm

5.2 用purge.url命令的日志是:

0x2aaaaec44640 1270695397.844543     0  req.url ~ ^test.html$

5.3 用purge命令的日志是:

0x2aaaaecc9fa0 1270698757.617076     0  req.http.host ~ sh.izhoufeng.com && req.url ~ ^/jzjiuba/10040810_1173704.htm$
0x2aaaaecc9f40 1270698757.616768     0  req.http.host ~ bj.izhoufeng.com && req.url ~ ^/fang5/10040711_6414363.htm$
0x2aaaaecc9e80 1270698757.547097     0  req.http.host ~ sh.izhoufeng.com && req.url ~ ^/zpshichangyingxiao/09112600_1315775.htm$
0x2aaaaecc9e20 1270698755.967497     0  req.http.host ~ sh.izhoufeng.com && req.url ~ ^/jzjiuba/10040810_1173702.htm$
0x2aaaaecc9dc0 1270698755.665087     0  req.http.host ~ bj.izhoufeng.com && req.url ~ ^/zpsiji/10040811_3258734.htm$
0x2aaaaecc9d60 1270698755.591958     0  req.http.host ~ bj.izhoufeng.com && req.url ~ ^/zpbaomu/10040811_3258735.htm$
0x2aaaaecc9ca0 1270698755.356326     0  req.http.host ~ bj.izhoufeng.com && req.url ~ ^/zpyinyuebiaoyanzhuchi/10040811_3258736.htm$
0x2aaaaecc9c40 1270698755.291577     0  req.http.host ~ bj.izhoufeng.com && req.url ~ ^/zpwenan/10040811_3258737.htm$
0x2aaaaecc9be0 1270698755.290569     0  req.http.host ~ sh.izhoufeng.com && req.url ~ ^/lvshi/10040809_2410859.htm$

6、Varnish刷新原理是通过ban列表来操作的。
当我们执行如下:

purge req.url ~ \.png

这个操作就添加到活跃的bans的前边。当有同样的purge操作时,他就会一直添加,Varnish不可能遍历它缓存的几亿个缓存对象以确定谁受影响。代替Varnish从缓存中查找对象是它通过比较purge list的bans。
如果匹配的ban被找到,这个ban和缓存中的对像进行比较。当有一个匹配的时候,对象被标记为不可用,除非另外个合适的对象能被找到,缓存hit将被一缓存miss替代,促使对象从后端获取。
新创建的对象不被老bans约束,当我们插入一个对象到缓存,他被标记为checked以针对所有的在列表中的现有bans。
针对一个ban当所有的对象都已经被检查过,这个ban就被从purge list中移除,同时内存重新可用。
7、我参考的文档如下:

http://varnish-cache.org/wiki/Purging

http://kristian.blog.linpro.no/2010/02/02/varnish-purges/

http://varnish-cache.org/wiki/VCLExamplePurging

相关文章:

如何快速搭建智能人脸识别系统

作者 | 小白来源 | 小白学视觉网络安全是现代社会最关心的问题之一&#xff0c;确保只有特定的人才能访问设备变得极其重要&#xff0c;这是我们的智能手机设有两级安全系统的主要原因之一。这是为了确保我们的隐私得到维护&#xff0c;只有真正的所有者才能访问他们的设备。基…

全局唯一ID生成方案

2019独角兽企业重金招聘Python工程师标准>>> 全局唯一ID生成方案对比 - http://cenalulu.github.io/mysql/guid-generate/ 转载于:https://my.oschina.net/meilihao/blog/386264

大型互联网 b2b b2c o2o 电子商务云平台

技术解决方案 开发语言&#xff1a; java、j2ee 数据库&#xff1a;mysql JDK支持版本&#xff1a; JDK1.6、JDK1.7、JDK1.8版本 核心技术&#xff1a;分布式、云服务、微服务、服务编排等。 核心架构&#xff1a; 使用Spring Cloud分布式微服务云架构进行服务化开发&#xff0…

Linux下redis安装部署

1、下载源代码 http://code.google.com/p/redis/downloads/list 下载redis-1.2.6.tar.gz 将下载包拷贝到/usr/local/webserver/redis-1.2.6/下 2、安装 tar -zxvf redis-1.2.6.tar.gzce redis-1.2.6make 3、调整内存 如果内存情况比较紧张的话&#xff0c;需要设定内核参数&am…

阿里无人车配送快递突破 100 万单,小蛮驴牵引的自动驾驶战略布局

作者 | 张昊 出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09; 从物流的“最后”三公里中&#xff0c;我们看到了自动驾驶技术的“最前”沿 在9月27日举办的达摩院媒体沟通会上&#xff0c;阿里巴巴集团副总裁、达摩院自动驾驶实验室负责人王刚宣布&#xff0c;达摩院…

[Python] 中文路径和中文文本文件乱码问题

情景: Python首先读取名为log.txt的文本文件, 其中包含有文件名相对路径信息filename. 随后Python调用shutil.copy2(src, dst)对该filename文件进行复制操作. 由于filename为相对路径信息, 所以我们需要硬编码写入父目录, 假设为"C:\\源目录\\", 同时还有目标目录信息…

kubernetes Helm

Helm产生原因利用Kubernetes部署一个应用&#xff0c;需要Kubernetes原生资源文件如deployment、replicationcontroller、service或pod 等。而对于一个复杂的应用&#xff0c;会有很多类似上面的资源描述文件&#xff0c;如果有更新或回滚应用的需求&#xff0c;可能要修改和维…

造车新势力“围猎”秋招,应届生如何拿下高薪 offer ?

作者 | 易璜珵 出品 | 《新程序员》近年来&#xff0c;互联网大厂的秋招开启得越来越早&#xff0c;只为先人一步将优秀的毕业生纳入麾下。所谓“金九银十”&#xff0c;九月即将结束&#xff0c;许多大厂的秋招正式批也逐渐进入笔试和面试环节。在新能源汽车领域&#xf…

云评测、云监测、云加速,性能魔方mmTrix全球速度最快

在移动互联网高速发展的今天&#xff0c;互联网企业如果要实现业务增长&#xff0c;在激烈的市场竞争中站稳脚跟&#xff0c;必须要尽可能的提高用户体验和产品影响力。而要达实现这个目标&#xff0c;产品应用性能质量的好坏往往起到重要作用&#xff0c;APM服务受到了越来越多…

水平切分与垂直切分

数据库优化无非水平切分与垂直切分&#xff01; 1.水平.就是按记录分. 一个数据库有3000W用户记录.处理速度比较慢.这时可以把3000W.分成三份.每份都是1000W.分别放在不同的机器上. 2.垂直分割就是按字段分. 一个数据库有3000W用户记录.包括字段id,user,password,first_name,l…

iOS 设计模式浅析 1 - 策略

本篇文章主要讲三个点: 1. 什么是策略模式.2. 策略模式的优缺点.3. demo .1. 策略模式定义一系列算法, 并且将每个算法封装起来, 算法之间可以互相替换. 使用前提: 输入已知, 好比你渴了, 可以喝可乐, 可以喝牛奶, 也可以喝水. 在我们项目中比较常见的使用情况: 1. 切换主题, 要…

何崚谈阿里巴巴前端性能优化最佳实践

转载&#xff1a;http://www.infoq.com/cn/interviews/hl-alibaba-front-end-performance-optimization 大家好&#xff0c;我现在在阿里巴巴园区采访阿里巴巴中文站架构师&#xff0c;兼B2B网站优化领域的负责人何崚。何崚你好&#xff0c;请简单介绍一下你自己。 我叫何崚&am…

java基础_04

2019独角兽企业重金招聘Python工程师标准>>> 1、java语言的程序结构。Java语言支持3种程序结构&#xff1a;顺序结构、选择结构&#xff08;分支结构&#xff09;、循环结构2、顺序结构是最简单、最普遍的一种。java程序如果没有意外都是按照从前到后、从左到右的顺…

会唱歌、会弹琴,清华大学 AI 学生华智冰火了

整理 | 禾木木 出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09; 清华大学计算机系知识工程实验室&#xff0c;开发的中国首个原创虚拟学生——华智冰&#xff0c;与近日亮相。她的声音、肢体动作全部由人工智能完成。 今年6月&#xff0c;清华大学计算机系录取了一位…

22. Node.Js Buffer类(缓冲区)-(二)

转自&#xff1a;https://blog.csdn.net/u011127019/article/details/52512242转载于:https://www.cnblogs.com/sharpest/p/8046463.html

linux安装sphinx

从sphnix网站下载sphinx源码包&#xff0c;当前最新版本是&#xff1a; http://sphinxsearch.com/files/sphinx-0.9.9.tar.gz。当然&#xff0c;还需要保证你的系统已经安装了mysql。其次&#xff0c;就是依照官方的安装指导进行安装了&#xff0c;基本步骤如下&#xff1a;解压…

机器人越像人越好?被机器人盯着会变『蠢』

编译 | 禾木木 出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09; 摘要&#xff1a;人形机器人的凝视会影响人们对社会决策任务的反应方式。 资料来源&#xff1a;IIT 你是否遇到过这种问题&#xff0c;跟别人对是不超过三秒&#xff1f;当你直视别人眼睛的时候&#x…

SQL Server 储存过程的output 参数

要做的参数的回传一方面要做到有储存过程的配合&#xff0c;再一方面也要有调用方法的配合&#xff0c;也就是说错误的调用方法是没有办法把值回传的。 下面是例子 --1、储存过程方面的配合 create procedure dbo.usp_C i as int output ---**注意这里要用output 关键字**--…

JavaScript基础笔记集合(转)

JavaScript基础笔记集合 JavaScript基础笔记集合js简介 js是脚本语言。浏览器是逐行的读取代码&#xff0c;而传统编程会在执行前进行编译 js存放的位置 html脚本必须放在<script>、</script>之内。 <script>可放置在<head>、<body>里 和css一…

Xapian安装

Xapian是一个用C编写的全文检索程序&#xff0c;他的作用类似于Java的lucene。Xapian除了提供原生的C编程接口之外&#xff0c;还提供了Perl&#xff0c;PHP&#xff0c;Python和Ruby编程接口和相应的类库&#xff0c;所以你可以直接从自己喜欢的脚本编程语言当中使用Xapian进行…

IOS开发中多线程的使用

一、创建多线程的五种方式1.开启线程的方法一 NSThread * thread[[NSThread alloc] initWithTarget:self selector:selector(_update) object:nil]; 2.开启线程的方法二 [NSThread detachNewThreadSelector:selector(_update) toTarget:self withObject:nil]; 3.开启线程的方法…

介绍如何用 Python 来绘制高清的交互式地图,建议收藏

作者 |俊欣来源 |关于数据分析与可视化今天小编来为大家介绍一个叫做Folium的模块&#xff0c;我们可以用它来绘制高清的交互式地图&#xff0c;并且标注出重要的地理位置等等&#xff0c;读者在看过本篇文章之后&#xff0c;读者大致会掌握1. 使用Folium来进行交互式地图的绘制…

Pandas Cheat Sheet

Pandas Doc: http://pandas.pydata.org/pandas-docs/stable/10min.html#min 转载于:https://www.cnblogs.com/nuswgg95528736/p/8053582.html

google ProtoBuf开发者指南

目录 1 概览 1.1 什么是protocol buffer 1.2 他们如何工作 1.3 为什么不用XML? 1.4 听起来像是为我的解决方案&#xff0c;如何开始? 1.5 一点历史 2 语言指导 2.1 定义一个消息类型 2.2 值类型 2.3 可选字段与缺省值 2.4 枚举 2.5 使用其他消息…

AI 生成的代码可信吗?编写的代码有 Bug 吗?

编译 | 禾木木 出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09; 即使是帮助开发人员编写软件的工具也会产生类似的bug。 目前&#xff0c;大部分的软件开发人员会让 AI 帮助开发者们编写代码&#xff0c;但是开发人员发现 AI 会像程序员的代码一样还是存有 bug。 去年…

嵌入式开发之信号采集同步---VSYNC和HSYNC的作用以及它们两者之间的关系

VSYNC和HSYNC的作用以及它们两者之间的关系 VSYNC和HSYNC的作用以及它们两者之间的关系 VSYNC和HSYNC是什么 VSYNC: vertical synchronization&#xff0c;指与显示器的帧数同步。 简单来说就是启用了VSYNC的渲染过程&#xff0c;帧数不会超过显示器的帧数&#xff0c;一个同步…

对ListenSocket 的研究(四)

对postmaster.c 中的 readmask&#xff0c;rmask,nsocket等进行分析&#xff0c;可以看到&#xff1a;它们之间有如下的关系(与细节无关的代码省略)&#xff1a;复制代码/* * Initialise the masks for select() for the ports we are listenin…

MySQL下的NoSQL解决方案HandlerSocket

目前使用MySQL的网站&#xff0c;多半同时使用Memcache作为键值缓存。虽然这样的架构极其流行&#xff0c;有众多成功的案例&#xff0c;但过于依赖Memcache&#xff0c;无形中让Memcache成为故障的根源&#xff1a; Memcache数据一致性的问题&#xff1a;当MySQL数据变化后&a…

人群距离监测 DeepSOCIAL 最全汉化论文+源码导读

作者 |神经星星来源 |HyperAI超神经By 超神经内容一览&#xff1a;在疫情期间&#xff0c;公共场所中尽量避免人群聚集&#xff0c;可以有效控制疫情扩散。英国利兹大学的研究团队开源了 DeepSOCIAL 人群距离监测项目&#xff0c;通过 YOLOv4SORT 的方式快速实现了这一应用。关…

堆和栈的差别(转过无数次的文章)

一、预备知识—程序的内存分配 一个由C/C编译的程序占用的内存分为下面几个部分 1、栈区&#xff08;stack&#xff09;— 由编译器自己主动分配释放 &#xff0c;存放函数的參数值&#xff0c;局部变量的值等。其 操作方式相似于数据结构中的栈。 2、堆区&…