Rumah  >  Artikel  >  pangkalan data  >  Apakah proses pemprosesan permintaan Redis?

Apakah proses pemprosesan permintaan Redis?

WBOY
WBOYke hadapan
2023-06-01 20:49:471037semak imbas

Ikhtisar#

  • Yang pertama ialah mendaftarkan pemproses; sambungan didengari ;

  • Kemudian Goroutine akan menunggu dalam gelung untuk menerima data permintaan, dan kemudian memadankan pemproses yang sepadan dalam jadual penghalaan pemproses mengikut alamat yang diminta, dan kemudian serahkan permintaan kepada pemproses untuk diproses ;

  • yang dinyatakan dalam kod adalah seperti ini:

    func (srv *Server) Serve(l net.Listener) error { 
        ...
        baseCtx := context.Background()  
        ctx := context.WithValue(baseCtx, ServerContextKey, srv)
        for {
            // 接收 listener 过来的网络连接
            rw, err := l.Accept()
            ... 
            tempDelay = 0
            c := srv.newConn(rw)
            c.setState(c.rwc, StateNew) 
            // 创建协程处理连接
            go c.serve(connCtx)
        }
    }
  • Ia sedikit berbeza untuk Redis, kerana ia adalah satu benang dan tidak boleh menggunakan berbilang benang untuk mengendalikan sambungan Oleh itu, Redis memilih untuk menggunakan pemacu peristiwa berdasarkan corak Reaktor untuk melaksanakan pemprosesan peristiwa serentak.

Apa yang dipanggil mod Reaktor dalam Redis adalah untuk memantau berbilang fd melalui epoll Setiap kali fd ini bertindak balas, epoll akan dimaklumkan dalam bentuk acara untuk panggilan balik Setiap acara mempunyai pengendali acara yang sepadan.

Apakah proses pemprosesan permintaan Redis?Contohnya: terima sepadan dengan pengendali acara acceptTCPHandler, baca & tulis sepadan dengan pengendali acara readQueryFromClient, dsb., dan kemudian acara itu diperuntukkan kepada pengendali acara untuk diproses melalui penghantaran gelung acara.

Jadi mod Reaktor di atas dilaksanakan melalui epoll Untuk epoll, terdapat tiga kaedah:

//创建一个epoll的句柄,size用来告诉内核这个监听的数目一共有多大
int epoll_create(int size);

/*
 * 可以理解为,增删改 fd 需要监听的事件
 * epfd 是 epoll_create() 创建的句柄。
 * op 表示 增删改
 * epoll_event 表示需要监听的事件,Redis 只用到了可读,可写,错误,挂断 四个状态
 */
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);

/*
 * 可以理解为查询符合条件的事件
 * epfd 是 epoll_create() 创建的句柄。
 * epoll_event 用来存放从内核得到事件的集合
 * maxevents 获取的最大事件数
 * timeout 等待超时时间
 */
int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);

Jadi kita boleh melaksanakan kaedah mudah berdasarkan tiga kaedah Pelayan:

// 创建监听
int listenfd = ::socket();

// 绑定ip和端口
int r = ::bind();  
// 创建 epoll 实例
int epollfd = epoll_create(xxx); 
// 添加epoll要监听的事件类型
int r = epoll_ctl(..., listenfd, ...);
 
struct epoll_event* alive_events =  static_cast<epoll_event*>(calloc(kMaxEvents, sizeof(epoll_event)));

while (true) {
    // 等待事件
    int num = epoll_wait(epollfd, alive_events, kMaxEvents, kEpollWaitTime);
	// 遍历事件,并进行事件处理
    for (int i = 0; i < num; ++i) {
        int fd = alive_events[i].data.fd;
        // 获取事件
        int events = alive_events[i].events;
		// 进行事件的分发
        if ( (events & EPOLLERR) || (events & EPOLLHUP) ) {
            ...
        } else  if (events & EPOLLRDHUP) {
            ...
        } 
        ...
    }   
}
.

Proses panggilan #

Jadi mengikut pengenalan di atas, anda boleh tahu bahawa untuk Redis, gelung acara tidak lebih daripada beberapa langkah:

Daftar fungsi mendengar acara dan panggilan balik;

  • Gelung untuk menunggu acara diperoleh dan diproses;

  • Tulis data kembali kepada Pelanggan

  • Daftar fd ke epoll , Dan tetapkan fungsi panggil balik acceptTcpHandler Jika terdapat sambungan baharu, fungsi panggil balik akan dipanggil; Kemudian kami akan kembali ke fungsi aeMain untuk menggelungkan fungsi aeProcessEvents

Apakah proses pemprosesan permintaan Redis?Apabila acara rangkaian datang, fungsi panggil balik acceptTcpHandler akan dipanggil sepenuhnya untuk readQueryFromClient untuk pemprosesan data akan menghuraikan data pelanggan dan mencari fungsi cmd yang sepadan. bukannya kembali serta-merta;

Keseluruhan acara di atas Sebenarnya, langkah kod proses gelung telah ditulis dengan sangat jelas, dan terdapat banyak artikel di Internet mengenainya, jadi saya tidak akan menerangkan secara terperinci.
  • Proses pelaksanaan perintah & klien tulis balik#

    Pelaksanaan perintah#
  • Mari kita bercakap tentang sesuatu yang banyak artikel di Internet tidak disebut dan lihat cara Redis melaksanakan arahan . , kemudian simpannya dalam cache, dan tulis semula data kepada klien daripada cache.

  • Kami juga menyebut dalam bahagian sebelumnya bahawa jika acara rangkaian datang, fungsi readQueryFromClient akan dipanggil, di mana arahan itu sebenarnya dilaksanakan. Kami hanya mengikut kaedah ini dan melihat ke bawah:

  • readQueryFromClient akan memanggil fungsi processInputBufferAndReplicate untuk memproses arahan yang diminta

  • dalam fungsi processInputBufferAndReplicate It; akan memanggil processInputBuffer dan menentukan sama ada arahan itu perlu disalin ke nod lain jika ia adalah mod kluster

fungsi processInputBuffer akan menggelung melalui arahan yang diminta dan memanggilnya mengikut protokol yang diminta processInlineBuffer; fungsi, selepas memanggil objek redisObject, processCommand dipanggil untuk melaksanakan perintah itu; arahan, dan kemudian pergi melalui siri pengesahan, panggil fungsi yang sepadan untuk melaksanakan arahan, dan panggil addReply untuk menulis data yang dikembalikan ke dalam penimbal output klien; 🎜> akan menambah semua data dalam fungsi populateCommandTable Arahan Redis didaftarkan sebagai jadual yang memperoleh fungsi arahan berdasarkan nama arahan.

Sebagai contoh, untuk melaksanakan perintah get, fungsi getCommand akan dipanggil:

void getCommand(client *c) {
    getGenericCommand(c);
}

int getGenericCommand(client *c) {
    robj *o;
	// 查找数据
    if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.nullbulk)) == NULL)
        return C_OK;
    ...
}

robj *lookupKeyReadOrReply(client *c, robj *key, robj *reply) {
    //到db中查找数据
    robj *o = lookupKeyRead(c->db, key);
    // 写入到缓存中
    if (!o) addReply(c,reply);
    return o;
}

Cari data dalam fungsi getCommand, dan kemudian panggil addReply untuk menulis data yang dikembalikan ke dalam output klien penampan .

Klien tulis balik data #

Selepas menulis arahan ke dalam penimbal, data perlu dikeluarkan daripada penimbal dan dikembalikan kepada klien. Untuk proses menulis data kembali kepada klien, ia sebenarnya telah selesai dalam gelung acara pelayan. Apakah proses pemprosesan permintaan Redis?

Apakah proses pemprosesan permintaan Redis?

  • Pertama, Redis akan memanggil fungsi aeSetBeforeSleepProc dalam fungsi utama untuk mendaftarkan fungsi beforeSleep bagi pakej tulis balik ke dalam eventLoop; >

    Kemudian apabila Redis memanggil fungsi aeMain untuk gelung acara, ia akan menentukan sama ada beforesleep telah ditetapkan. Pergi ke fungsi handleClientsWithPendingWrites, yang memanggil writeToClient untuk menulis kembali data kepada klien daripada penimbal.

Atas ialah kandungan terperinci Apakah proses pemprosesan permintaan Redis?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:yisu.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam