Redis,提高服務器性能的一把瑞士軍刀

原創做者,公衆號【程序員讀書】,歡迎關注公衆號,轉載文章請註明出處哦。git

影響服務器性能的因素有不少,好比CPU、內存、硬盤等硬件設備條件的限制,也有服務器總體架構、程序員的代碼質量、使用的算法和數據結構優劣等方方面面的因素。程序員

不過我的感受對服務器性能影響最大,應該是數據庫,服務器在面對高併發請求時,性能瓶頸每每出如今數據庫方面,由於數據庫扛不了那麼高的併發數,而使用數據庫集羣每每也意味着較高的硬件和軟件成本,所以,若是在代碼層與數據庫之間再加一層緩存,能夠有效緩解數據庫的壓力,大大提高服務器的性能。github

而提到緩存,咱們最早想到的是什麼,是Redis,或許這就是Redis給咱們的第一印象,雖然這樣理解Redis並不徹底正確,由於Redis所能作,並不只僅於此,下面一塊兒探究一下吧。golang

什麼是Redis

Redis是一名叫Salvatore Sanfilippo的人在2009年使用ANSI C編寫的開源的內存數據結構存儲系統,Redis的做者開發Redis很大一部分緣由,也是由於數據庫沒法知足他的需求。redis

固然啦,咱們能夠把Redis簡單地理解爲內存數據庫(NoSQL)或者Key-Value鍵值對服務器算法

Redis提供了多種數據結構和不一樣編程語言的客戶端API,另外,也提供了持久化、主從複製、事務等多種功能和特性,就像一把瑞士軍刀通常,是服務器開發中的一把利器。docker

Redis就像這樣一把瑞士軍刀

雖然Redis提供了很是強大的功能,但Redis的代碼卻很是簡單,其最初的版本只有23000行代碼,而最近的某一個版本代碼也只有50000多行而已,所以,感興趣的人能夠研究一下Redis源碼。數據庫

Redis的特性

下面列出一些Redis的特性,讓咱們對Redis有個比較全面的瞭解,其實,從這些特性中,也能夠看出Redis的強大。編程

速度快

Redis的響應速度很是快,之因此這麼快,最大的緣由是Redis對數據的操做都是在內存中進行的,咱們從下面的存儲器層次結構圖即可以看到,內存的讀寫速度比硬盤(不管是固態仍是機械硬盤)都在快不少,所以Redis天然就很是快速。windows

存儲器層次結構圖 【摘自《深刻理解計算機系統》】

持久化

前面咱們說Redis將數據放在內存中,,但Redis也提供了持久化機制,這樣能夠將用戶存儲到內存中的數據,定時持久化到硬盤等存儲設備中,保證服務器斷電重啓時,數據不會消失,Redis支持RDBAOF兩種持久化機制,有機會,咱們在之後的文章中講講這兩種機制的區別。

多種數據類型

Redis支持多種類型的數據結構,這也是RedisMemcached的區別之一,Memcached只支持String類型,而Redis除了StringHashListSetSort Set這些基本的數據類型外,還有BitMaps(位圖)HyperLogLog(超小內存惟一值計數)GEO(地理信息定位)等高級的數據類型。

支持多種編程語言客戶端

Redis爲大多數編程語言都提供了客戶端API,這些API有些是官方提供的,有些則來自開源社區的貢獻,因此無論你使用什麼語言來開發服務器應用,均可以很方便鏈接Redis。

下面是Redis官網上列出全部編程語言API列表的地址

# redis支持的客戶端列表
https://redis.io/clients
複製代碼

發佈訂閱

Redis支持訂閱與發佈的功能,所以可使用Redis來實現一個簡單消息隊列,一端做爲發佈者把消息發佈到Redis,而另外一端做爲消費者,處理來自Redis的消息。

Lua腳本

Redis在V2.6u新增了腳本功能,容許客戶端使用Lua語言編寫腳本傳到Redis中執行,這樣作的好處是:減小網絡開銷原子操做和腳本複用,關於Redis中如何使用Lua腳本,有空再說。

事務

Redis支持事務,當咱們須要執行多條命令時,保證多條命令執行原子性,由於在事務中,多條命令的執行,要麼都成功,要麼都失敗,固然,要執行多個命令,使用Lua腳本也許更加方便。

主從複製

Redis支持主從複製功能,即主服務器的數據,能夠同步到多臺從服務器上,因此主從複製實際是爲Redis的高可用和分佈式提供了基礎。

主從複製示例圖

高可用分佈式

Redis也支持高可用和分佈式,實際主從複製只是實際高可用的基礎,但要經過主從複製實現高可用是不太可能的,Redis的高可用是經過Redis Sentinel(哨兵)來實現的,Redis Sentinel是在V2.8增長的功能,而分佈式則須要Redis cluster功能的支持,Redis_cluster是在v3.0以後增長的功能。

單線程

Redis是單線程的,這裏所說的單線程,指其在Redis做爲服務器在接收客戶端網絡請求時採用是單線程,因此在同一時刻,Redis沒法同時處理兩個請求,只有一個請求處理完成再處理下一個請求,不過Redis在實現某個功能時,仍是使用的多線程的,好比將數據持久化到硬件,就是開啓另外一個線程來實現的。

安裝並啓動Redis

Redis的安裝很是簡單,這裏介紹兩種安裝方式,一種是從Redis官網上下載源碼,而後編譯安裝,另一種更加方便,直接從Docker Hub上拉取Redisdocker鏡像。

下面介紹的是在Linux系統上安裝Redis的過程。

使用源碼編譯安裝

# 下載redis源碼安裝包
wget http://download.redis.io/releases/redis-5.0.5.tar.gz

# 解壓縮
tar -zxvf redis-5.0.5.tar.gz

# 進入redis源碼目錄
cd redis-5.0.5

# 編譯 & 安裝
make && make install
複製代碼

使用Docker鏡像安裝並啓動Redis

Redis提供了docker鏡像,所以咱們能夠很方便拉取並運行Redis鏡像,不過,前提是你的服務器上有安裝docker

# 從Docker Hub上拉取官方鏡像,redis:latest
docker pull redis

# 從鏡像中啓動一個容器
docker run --name my_redis -p 6379:6379 -d redis
複製代碼

這裏要說明一點,就是Redis做者並無開發Redis的Windows版本,可能Redis的做者以爲安裝Windows系統的服務器不適合運行Redis,又或者什麼緣由,不過微軟仍是提供了Redis的Windows版本。

# redis的windows版本
https://github.com/microsoftarchive/redis/releases
複製代碼

啓動Redis的幾種方式

不帶參數,使用默認配置啓動服務器

# 使用默認配置啓動
redis-server
複製代碼

指定命令行參數啓動服務器

# 使用命令參數配置啓動
redis-server --port 6380
複製代碼

使用配置文件啓動服務器

# 使用配置文件啓動
redis-server ~/redis-5.0.5/redis.conf
複製代碼

鏈接Redis

在使用前面介紹的幾種方式啓動Redis服務器後,咱們就可使用Redis客戶端鏈接服務器,向服務器寫入或讀取數據,前面咱們說過Redis支持大多數編程語言,所以大你們能夠根據本身的狀況選擇不一樣的API。

使用命令行客戶端鏈接Redis

在安裝好Redis以後,就可使用Redis安裝包中自帶的客戶端redis-cli,這是一個命令行客戶端,其使用示例以下:

# 直接使用,不帶參數,會鏈接本地服務器
redis-cli

# 指定地址和端口號
redis-cli -h 服務器地址 -p 端口號
複製代碼

使用代碼鏈接Redis服務器

在這裏演示使用golang的開發的redigo/redis包鏈接Redis服務器。

# 獲取go語言的某個redis客戶端庫
go get github.com/gomodule/redigo/redis
複製代碼

下面是使用redigo/redis庫鏈接Redis的簡單代碼示例:

package main

import (
    "fmt"
    "github.com/gomodule/redigo/redis"
)

var redisCon redis.Conn

func main() {
    var err error
    redisCon ,err = redis.Dial("tcp","localhost:6379")
    
    if err != nil{
    	panic(err)
    }
    
    defer redisCon.Close()
    
    rs,err := redisCon.Do("set","test_key","test_value")
    
    if err != nil{
    	panic(err)
    }
    fmt.Println(rs)
}

複製代碼

上面的代碼可能比較簡單,有機會咱們詳細瞭解如何使用Golang更好地鏈接和操做Redis。

應用場景

下面列出一些Redis的使用場景,咱們也能夠根據本身的須要,靈活使用Redis來達到提高服務器性能的目的。

緩存系統

Redis最常被使用的場景就是用於數據緩存,因爲其基於內存的數據快速讀寫操做,響應速度很是快,能夠用於緩存一些熱點數據或者不怎麼變化的數據,這樣,當用戶請求這些數據時,直接從Redis快速讀取,避免頻繁的數據庫讀寫,提高服務器的數據吞吐量及速度。

排行榜

Redissort set數據類型很是適合作排榜行功能,好比【掘金】的【推薦做者榜】其實實現的原理應該就是將計算後的做者排行權重放在Redissort set中來實現的,所以Redis在實現這類功能真的是很是方便簡單。

掘金推薦做者榜

實現社區功能

Redis的功能與一些社區功能有着自然的契合性,使用Redis所支持的數據結構,能夠容易存儲社區功能中的如關注數,粉絲數,關注列表,粉絲列表,共同共注等數據,好比關注數與粉絲數能夠用計數器,關注列表和粉絲列表可使用seto類型來存儲。

計數器

Redis內置的incr命令能夠很方便地單線程下進行計數,並且這種操做是原子性,不用擔憂某個時刻有兩個請求對同一個鍵值進行計數,這種計數器功能在某些場景下很是實用,好比掘金的文章,閱讀數、評論數、點贊數可使用Redis的計數功能來實現,想一想,若是這些數據直接寫入數據庫,那麼每次有人點贊、閱讀、評論都須要對數據庫進行操做,估計數據庫會掛掉,而使用Redis計數功能,則能夠快速輕鬆完成這種功能的實現。

消息隊列

Redis支持發佈訂閱功能,所以能夠把Redis看成一個簡單的消息隊列,當咱們有一些業務須要使用消息隊列時,能夠考慮使用Redis來實現,固然,成熟的消息隊列中間件系統有不少,如KafkaRabbitMQRocketMQActiveMQ,而後使用這些可能須要額外的軟硬件成本及學習成本,所以可使用Redis的消息隊功能來替代。

Redis消息隊列示意圖

實時系統

對於一些須要實時處理的數據,也能夠直接寫入Redis中,再由其餘系統進行處理,這其實也是利用了Redis發佈訂閱的功能,來達到數據實時處理的目的,好比一些垃圾郵箱處理系統等。

小結

在這篇文章中,咱們簡單地談了一下Redis是什麼,能夠作什麼,並瞭解其強大的特性和功能,經過演示如何安裝、啓動和鏈接Redis,也讓咱們知道如何使用Redis,固然啦,想要更好地瞭解和使用Redis,還須要更加深刻地學習,下面有機會,咱們繼續這方面的學習。


你的關注,是我寫做路上最大的鼓勵!

相關文章
相關標籤/搜索