Rumah pangkalan data tutorial mysql libmemcached的MEMCACHED_MAX_BUFFER问题

libmemcached的MEMCACHED_MAX_BUFFER问题

Jun 07, 2016 pm 04:27 PM
max memcached

最近给服务增加了一个cache_put_latency指标,加了之后,吓了一跳。发现往memcached put一个10KB左右的数据,latency居然有7ms左右,难于理解,于是花了一些精力找原因。我分别写了一个shell和C++的测试程序。 1、shell脚本使用nc发送set命令。 #/bin/env ba

最近给服务增加了一个cache_put_latency指标,加了之后,吓了一跳。发现往memcached put一个10KB左右的数据,latency居然有7ms左右,难于理解,于是花了一些精力找原因。我分别写了一个shell和C++的测试程序。

1、shell脚本使用nc发送set命令。

#/bin/env bash
let s=1
let i=0
let len=8*1024
while true
do
	if (( i >= $len ))
	then
		break
	fi
	str=${str}1
	let i++
done
let i=0
begin_time=`date +%s`
while true
do
	if (( i >= 1000 ))
	then
		break
	fi
	printf "set $i 0 0 $len\r\n${str}\r\n" | nc 10.234.4.24 11211
	if [[ $? -eq 0 ]]
	then
		echo "echo key: $i"
	fi
	let i++
done
end_time=`date +%s`
let use_time=end_time-begin_time
echo "set time consumed: $use_time"
let i=0
begin_time=`date +%s`
while true
do
	if (( i >= 1000 ))
	then
		break
	fi
	printf "get $i\r\n" | nc 10.234.4.22 11211 > /dev/null 2>&1
	let i++
done
end_time=`date +%s`
let use_time=end_time-begin_time
echo "get time consumed: $use_time"
Salin selepas log masuk

2、C++程序则通过libmemcached set。

#include <iostream>
#include <map>
#include <string>
#include <sys>
#include <time.h>
#include <stdlib.h>
#include "libmemcached/memcached.h"
using namespace std;
uint32_t item_size = 0;
uint32_t loop_num = 0;
bool single_server = false;
std::string local_ip;
std::map<:string uint32_t> servers;
int64_t getCurrentTime()
{
    struct timeval tval;
    gettimeofday(&tval, NULL);
    return (tval.tv_sec * 1000000LL + tval.tv_usec);
}
memcached_st* mc_init()
{
	memcached_st * mc = memcached_create(NULL);
	if (mc == NULL)
	{
		cout ::iterator iter;
    for (iter = servers.begin(); iter != servers.end(); ++iter)
    {
        if (single_server && iter->first != local_ip)
        {
            continue;
        }
	    memcached_return rc = memcached_server_add(mc, iter->first.c_str(), iter->second);
        if(rc != MEMCACHED_SUCCESS)
        {
            cout first first 
<p>测试发现二者的结果是相背的。shell脚本set 1000次8KB的item,只要3s左右,平均需要3ms。而C++版本则需要39s左右,平均耗时39ms。照理说shell脚本需要不断连接服务器和启动nc进程,应该更慢才对。我用ltrace跟踪了一下,发现8KB的数据需要发送两次,两次write都是非常快的,但是等memcached返回时用了很多时间,主要的时间就耗费在这个地方。</p>
<pre class="brush:php;toolbar:false">
23:32:37.069922 [0x401609]
memcached_set(0x19076200, 0x7fffdad68560, 32, 0x1907a570, 8192 <unfinished ...>
23:32:37.070034 [0x3f280c5f80]
SYS_write(3, "set 29 0 600
8192\r\naaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"..., 8196) = 8196 
23:32:37.071657 [0x3f280c5f80]
SYS_write(3, "aaaaaaaaaaaaaaa\r\n", 17) = 17 
23:32:37.071741 [0x3f280c5f00]
SYS_read(3, "STORED\r\n", 8196) = 8 (39ms)
</unfinished>
Salin selepas log masuk

和剑豪讨论下之后,剑豪马上去grep了一把代码,发现原来libmemcached居然有MEMCACHED_MAX_BUFFER这样一个常量,其值为8196。并且它还没有对应的memcached_behavior_set函数。在memcached_constants.h中将其直接改成81960,然后就欣喜地发现cache_put_latency从7ms降低到1ms左右。

问题完美虽然地解决了,但是意犹未尽,于是想搞明白为什么会出现这种奇怪的现象。瓶颈貌似在服务器端,于是对memcached做了一些修改。在状态切换的时候加上一个精确到微秒的时间。

static int64_t getCurrentTime()
{
    struct timeval tval;
    gettimeofday(&tval, NULL);
    return (tval.tv_sec * 1000000LL + tval.tv_usec);
}
static void conn_set_state(conn *c, enum conn_states state) {
    assert(c != NULL);
    assert(state >= conn_listening && state state) {
        if (settings.verbose > 2) { 
            fprintf(stderr, "%d: going from %s to %s, time: %lu\n",
                    c->sfd, state_text(c->state),
                    state_text(state), getCurrentTime());
        }    
        c->state = state;
        if (state == conn_write || state == conn_mwrite) {
            MEMCACHED_PROCESS_COMMAND_END(c->sfd, c->wbuf, c->wbytes);
        }    
    }    
}
Salin selepas log masuk

从打印的时间戳可以看出来,时间主要花在conn_nread状态处理代码中。最后定位到第二次read花费的时间非常多。

15: going from conn_waiting to conn_read, time: 1348466584440118
15: going from conn_read to conn_parse_cmd, time: 1348466584440155
 NOT FOUND 98
>15 STORED
15: going from conn_nread to conn_write, time: 1348466584480099(36ms)
15: going from conn_write to conn_new_cmd, time: 1348466584480145
15: going from conn_new_cmd to conn_waiting, time: 1348466584480152
Salin selepas log masuk

value的数据可能在conn_read中读完了,这个时候只需要memmove一下就好了。如果没有在conn_read状态中读完,那么就需要conn_nread自己来一次read了(因为套接字被设置成了异步,所以还可能需要多次read),关键就是这个read太慢了。

        case conn_nread:
            if (c->rlbytes == 0) { 
                complete_nread(c);
                break;
            }    
            /* first check if we have leftovers in the conn_read buffer */
            if (c->rbytes > 0) { 
                int tocopy = c->rbytes > c->rlbytes ? c->rlbytes : c->rbytes;
                if (c->ritem != c->rcurr) {
                    memmove(c->ritem, c->rcurr, tocopy);
                }    
                c->ritem += tocopy;
                c->rlbytes -= tocopy;
                c->rcurr += tocopy;
                c->rbytes -= tocopy;
                if (c->rlbytes == 0) { 
                    break;
                }    
            }    
            /*  now try reading from the socket */
            res = read(c->sfd, c->ritem, c->rlbytes);
            if (res > 0) { 
                pthread_mutex_lock(&c->thread->stats.mutex);
                c->thread->stats.bytes_read += res; 
                pthread_mutex_unlock(&c->thread->stats.mutex);
                if (c->rcurr == c->ritem) {
                    c->rcurr += res; 
                }    
                c->ritem += res; 
                c->rlbytes -= res; 
                break;
            }
Salin selepas log masuk

折腾了好久,在libmemcached的io_flush函数前后也打了不少时间戳,发现libmemcached发送数据是非常快的。突然灵感闪现,我想起来了TCP_NODELAY这个参数,于是在libmemcached memcached_connect.c文件中的set_socket_options函数中增加了这个参数(事实上set_socket_options函数里面可以设置TCP_NODELAY,没有仔细看)。

    int flag = 1;
    int error = setsockopt(ptr->fd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(flag) );
    if (error == -1) {
          printf("Couldn't setsockopt(TCP_NODELAY)\n");
            exit(-1);
    }else
    {   
          printf("set setsockopt(TCP_NODELAY)\n");
    }
Salin selepas log masuk

在不改MEMCACHED_MAX_BUFFER的情况下,现在set 100KB的item也是一瞬间的事情了。不过新的困惑又出现了,Nagle算法什么情况会起作用呢?为什么第一个包没被缓存,第二个包一定会被缓存呢?

libmemcached发送一个set命令是分成三部分的,首先是header(set 0 0 600 8192\r\n,共18个字节),然后是value(8192个字节),最后是’\r\n’(两个字节),一共是8212个字节。memcached在conn_read状态一共能读取2048+2048+4096+8196=16KB的数据,因此对于8KB的数据是完全可以在conn_read状态读完的。通过在conn_read状态处理的代码中增加下面的打印语句可以发现有些情况下,conn_read最后一次只读取了4个字节(正常情况应该是2048+2048+4096+20),剩下的16个字节放到conn_nread中读了。

        res = read(c->sfd, c->rbuf + c->rbytes, avail);
        if (res > 0) {
            char buf[10240] = {0};
            sprintf(buf, "%.*s", res, c->rbuf + c->rbytes);
            printf("avail=%d, read=%d, str=%s\n", avail, res, buf);
Salin selepas log masuk

未设置TCP_NODELAY选项时,使用netstat可以看到客户端socket的Send-Q一直会维持在8214和8215之间。

tcp        0   8215 10.232.42.91:59836          10.232.42.91:11211          ESTABLISHED 25800/t
Salin selepas log masuk

设置TCP_NODELAY选项时,客户端socket的Send-Q就一直为0了。

tcp        0      0 10.232.42.91:59890          10.232.42.91:11211          ESTABLISHED 26554/t.quick
Salin selepas log masuk
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn

Alat AI Hot

Undresser.AI Undress

Undresser.AI Undress

Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover

AI Clothes Remover

Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool

Undress AI Tool

Gambar buka pakaian secara percuma

Clothoff.io

Clothoff.io

Penyingkiran pakaian AI

AI Hentai Generator

AI Hentai Generator

Menjana ai hentai secara percuma.

Artikel Panas

R.E.P.O. Kristal tenaga dijelaskan dan apa yang mereka lakukan (kristal kuning)
1 bulan yang lalu By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Tetapan grafik terbaik
1 bulan yang lalu By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Cara Memperbaiki Audio Jika anda tidak dapat mendengar sesiapa
1 bulan yang lalu By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Arahan sembang dan cara menggunakannya
1 bulan yang lalu By 尊渡假赌尊渡假赌尊渡假赌

Alat panas

Notepad++7.3.1

Notepad++7.3.1

Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina

SublimeText3 versi Cina

Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1

Hantar Studio 13.0.1

Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6

Dreamweaver CS6

Alat pembangunan web visual

SublimeText3 versi Mac

SublimeText3 versi Mac

Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

iPhone 15 Pro Max vs iPhone 14 Pro Max: Apakah perbandingan dan perbezaan antara mereka? iPhone 15 Pro Max vs iPhone 14 Pro Max: Apakah perbandingan dan perbezaan antara mereka? Sep 19, 2023 pm 08:29 PM

iPhone 15 Pro lwn. iPhone 14 Pro: Perbandingan Spesifikasi Berikut ialah perbandingan spesifikasi antara iPhone 15 Pro Max dan iPhone 14 Pro Max: iPhone 15 Pro Max iPhone 14 Pro Max Saiz paparan 6.7 inci 6.7 inci Teknologi paparan Super Retina 2,000 nits Dimensi 6.29x3 .02x0.32 inci 6.33x3.06x0.31 inci Berat 221 gram 240 gram

Teknologi caching Memcached mengoptimumkan pemprosesan Sesi dalam PHP Teknologi caching Memcached mengoptimumkan pemprosesan Sesi dalam PHP May 16, 2023 am 08:41 AM

Memcached ialah teknologi caching yang biasa digunakan yang boleh meningkatkan prestasi aplikasi web dengan banyak. Dalam PHP, kaedah pemprosesan Sesi yang biasa digunakan adalah untuk menyimpan fail Sesi pada cakera keras pelayan. Walau bagaimanapun, kaedah ini tidak optimum kerana cakera keras pelayan akan menjadi salah satu kesesakan prestasi. Penggunaan teknologi caching Memcached boleh mengoptimumkan pemprosesan Sesi dalam PHP dan meningkatkan prestasi aplikasi Web. Sesi dalam PHP

Cara menggunakan HEIF Max (48 MP) dan mengoptimumkan storan pada iPhone 14 Pro Cara menggunakan HEIF Max (48 MP) dan mengoptimumkan storan pada iPhone 14 Pro Sep 21, 2023 pm 02:13 PM

Siri iPhone Pro terbaharu dilengkapi dengan sensor 48MP berkuasa yang memastikan gambar yang sangat terperinci dan jernih untuk merakam setiap detik berharga. Walau bagaimanapun, satu kelemahan yang berpotensi ialah saiz imej resolusi penuh, terutamanya dalam format ProRAW. Walaupun ruang storan maksimum yang ditawarkan oleh iPhone ialah 512GB, menangkap banyak imej ProRAW (kira-kira 75MP setiap satu) dan video (440MB seminit, 60FPS) boleh memakan ruang storan anda dengan cepat. Ini boleh menyebabkan masalah jika anda merancang untuk menggunakan iPhone anda sebagai kamera utama anda untuk projek besar atau perjalanan. Tetapi bukankah lebih bagus jika anda boleh mengambil gambar 48MP beresolusi tinggi itu tanpa perlu risau tentang had storan? ia cepat

Perbandingan hayat bateri semua siri iPhone 15: iPhone 15 Plus mengalahkan 15 Pro Max Perbandingan hayat bateri semua siri iPhone 15: iPhone 15 Plus mengalahkan 15 Pro Max Sep 30, 2023 pm 11:09 PM

Walaupun Apple akan melancarkan masa main balik video iPhone untuk memberitahu pengguna bahawa bateri iPhone hampir tersedia. Tetapi pengguna biasa tidak menggunakan iPhone mereka untuk menonton video sepanjang hari. 7 iPhone diuji untuk ketahanan dalam aplikasi harian. Termasuk 7 model termasuk iPhone15ProMax, iPhone15Pro, iPhone15Plus, iPhone15, iPhone14ProMax, iPhone14 dan iPhone13ProMax. Menjalankan beberapa aplikasi harian, seperti Spotify, Zoom, Tiktok, Headspace, fikirkan tentang Apl, permainan, dll., kita dapat melihat hayat bateri iPhone yang berbeza. ini

Caching perpustakaan dalam PHP8.0: Memcached Caching perpustakaan dalam PHP8.0: Memcached May 14, 2023 am 08:16 AM

Caching library dalam PHP8.0: Memcached Dengan perkembangan pesat Internet, aplikasi moden memerlukan teknologi caching yang cekap dan boleh dipercayai untuk meningkatkan prestasi dan mengendalikan sejumlah besar data. Disebabkan populariti PHP dan sifat sumber terbuka, perpustakaan caching PHP telah menjadi alat penting dalam komuniti pembangunan web. Memcached ialah sistem caching memori berkelajuan tinggi sumber terbuka yang digunakan secara meluas yang boleh mengendalikan berjuta-juta permintaan cache bersambung serentak dan boleh digunakan dalam pelbagai jenis aplikasi, seperti rangkaian sosial, dalam talian

Bagaimana untuk mendapatkan nilai maksimum dari aliran dalam java8 Bagaimana untuk mendapatkan nilai maksimum dari aliran dalam java8 May 14, 2023 pm 03:43 PM

Strim java8 mengambil maxpublicstaticvoidmain(String[]args){Listlist=Arrays.asList(1,2,3,4,5,6);Integermax=list.stream().max((a,b)->{if ( a>b){return1;}elsereturn-1;}).get();System.out.println(maks);}Nota: Saiz ditentukan di sini melalui nombor positif dan negatif serta 0 nilai. Daripada menulisnya terus jika(a>b){returna;}elseretur

Butiran Samsung S25 Ultra terdedah: lebar sama seperti iPhone 16 Pro Max, tetapi dengan skrin yang lebih besar Butiran Samsung S25 Ultra terdedah: lebar sama seperti iPhone 16 Pro Max, tetapi dengan skrin yang lebih besar Aug 23, 2024 pm 09:33 PM

Menurut berita pada 22 Ogos, ketika keluaran telefon bimbit perdana Samsung S25 Ultra semakin hampir, semakin banyak butiran mula muncul. Blogger terkenal @ibinguniverse mendedahkan lebih banyak spesifikasi S25 Ultra di Weibo hari ini yang paling menarik perhatian ialah lebar badannya sama dengan Apple iPhone 16 Pro Max, kedua-duanya 77.6mm. 1. Terima kasih kepada pengoptimuman lanjut reka bentuk bingkai Samsung, saiz skrin S25 Ultra telah ditingkatkan kepada 6.86 inci sambil mengekalkan lebar yang sama seperti iPhone 16 Pro Max, memberikan pengguna pengalaman visual yang lebih mengasyikkan. Blogger seterusnya menegaskan di kawasan komen bahawa tepi hitam S25 Ultra lebih baik daripada iPhone 16 Pro Max&

Bagaimana untuk mengoptimumkan penggunaan CPU aplikasi PHP menggunakan teknologi caching Memcached? Bagaimana untuk mengoptimumkan penggunaan CPU aplikasi PHP menggunakan teknologi caching Memcached? Jun 21, 2023 pm 05:07 PM

Dengan perkembangan Internet, aplikasi PHP telah menjadi lebih biasa dalam bidang aplikasi Internet. Walau bagaimanapun, capaian serentak yang tinggi oleh aplikasi PHP boleh menyebabkan penggunaan CPU yang tinggi pada pelayan, sekali gus menjejaskan prestasi aplikasi. Untuk mengoptimumkan prestasi aplikasi PHP, teknologi caching Memcached telah menjadi pilihan yang baik. Artikel ini akan memperkenalkan cara menggunakan teknologi caching Memcached untuk mengoptimumkan penggunaan CPU aplikasi PHP. Pengenalan kepada teknologi caching Memcached Memcached ialah a

See all articles