Redis:08---字符串對象

一、字符串對象概述

  • 字符串類型是Redis最基礎的數據結構。首先鍵都是字符串類型,而且其他幾種數據結構都是在字符串類型基礎上構建的,所以字符串類型能為其他四種數據結構的學習奠定基礎

  • 字符串就是一個由字節組成的序列

  • 如下圖所示,字符串類型的值實際可以是:

    • 字符串(簡單的字符串、復雜的字符串(例如JSON、XML))

    • 數字?(整數、浮點數)

    • 二進制(圖片、音頻、視頻),但是值最大不能超過512MB

二、命令

設置值(SET、SETEX、SETNX)

  • set:設置值。參數如下:

    • ex seconds:為鍵設置秒級過期時間

    • px milliseconds:為鍵設置毫秒級過期時間

    • nx:鍵必須不存在,才可以設置成功,用于添加

    • xx:與nx相反,鍵必須存在,才可以設置成功,用于更新

set key value [ex seconds] [px milliseconds] [nx|xx]

  • setex、setnx:它們的作用和set命令的ex和nx選項是一樣的

    • setex:設置鍵的時候同時設置過期時間

    • setnx:鍵必須不存在,才可以設置成功,否則出錯

setex key seconds value
setnx key value

  • setnx和setxx在實際使用中有什么應用場景嗎?

    • 以setnx命令為例子,由于 Redis的單線程命令處理機制,如果有多個客戶端同時執行setnx key value, 根據setnx的特性只有一個客戶端能設置成功,setnx可以作為分布式鎖的一種實現方案,Redis官方給出了使用setnx實現分布式鎖的方法:http://redis.io/topics/distlock

獲取值(GET)

get key
  • 如果要獲取的鍵不存在,則返回nil(空)

批量設置值(MSET)

mset key value [key value ...]
  • 例如下面依次設置4個鍵值對:

批量獲取值(MGET)

  • 如果有些鍵不存在,那么它的值為nil(空)

mget key [key ...]
  • 例如下面獲取鍵為a、b、c、d、e的值,其中e鍵不存在

批量操作的好處

  • 批量操作命令可以有效提高開發效率,假如沒有mget這樣的命令,要執行n次get命令需要耗時如下:

n次get時間 = n次網絡時間 + n次命令時間

  • 使用mget命令后,要執行n次get命令操作只需要耗時:

n次get時間 = 1次網絡時間 + n次命令時間

  • Redis可以支撐每秒數萬的讀寫操作,但是這指的是Redis服務端的處理能力,對于客戶端來說,一次命令除了命令時間還是有網絡時間,假設網絡時間為1毫秒,命令時間為0.1毫秒(按照每秒處理1萬條命令算),那么執行1000次get命令和1次mget命令的區別如下圖所示,因為Redis的處理能力已經足夠高,對于開發人員來說,網絡可能會成為性能的瓶頸

  • 學會使用批量操作,有助于提高業務處理效率,但是要注意的是每次批 量操作所發送的命令數不是無節制的,如果數量過多可能造成Redis阻塞或 者網絡擁塞。

字符串的自增命令和自減命令:

命令用例和描述
INCRINCR key-name 將鍵存儲的值加上l
DECRDECR key-name 將鍵存儲的值減去Ⅰ
INCRBYINCRBY key-name amount 將鍵存儲的值加上整數amount
DECRBYDECRBY key-name amount 將鍵存儲的值減去整數amount
INCRBYELOAT工NCRBYFLOAT key-name amount 將鍵存儲的值加上浮點數amount,這個命令在Redis 2.6或以上的版本可用

概念:

    • 用戶可以通過給定一個任意的數值,對存儲著整數或者浮點數的字符串執行自增(increment)、自減操作(decrement)

    • 在需要的時候,Redis還會將整數轉換為浮點數

    • 整數的取值范圍和系統的長整數(long integer)的取值范圍相同(32位系統中就是32位有符號整數;64位系統中就是64位有符號整數)

    • 而浮點數的取值范圍和精度則與IEEE 754標準的雙精度浮點數(double)相同

  • 返回值:

    • INCR:返回增加后鍵的值。返回值分為三種:

    • DECR:返回刪除后鍵的值

    • INCRBY:返回增加后鍵的值

    • DECRBY:返回刪除后鍵的值

    • INCRBYFLOAT:返回增加后鍵的值

  • 注意事項:

    • 如果對一個不存在的鍵或者一個保存了空串的鍵執行自增或者自減操作,那么Redis在執行操作時會將這個鍵的值作為0來處理

    • 如果所操作的字符串不是一個能被解釋為整數或者浮點數的字符串,那么這些命令的操作將返回一個錯誤

  • 很多存儲系統和編程語言內部使用CAS機制實現計數功能,會有一定的CPU開銷,但在Redis中完全不存在這個問題,因為Redis是單線程架構,任 何命令到了Redis服務端都要順序執行

  • 演示案例如下:

? ? ?STRLEN:獲取字符串長度(備注:中文占3個字節)

strlen key

?

  • GETSET:設置并返回原值。

  • getset和set一樣會設置值,但是不同的是,它同時會返回鍵原來的值

getset key value

  • 下面給出了其他一些演示案例:

  • 注意SETRANGE的用法:

  • 下圖是字符串類型命令的時間復雜度:

  • 命令

    時間復雜度

    set key value

    o(l)

    get key

    o(1)

    del key [key ...]

    o(k),k是鍵的個數

    mset key value [ key value ...]

    O(k),t是鍵的個致

    mget key [key ...]

    o(),I是鍵的個致

    incr key

    o1)

    decr key

    o(1)

    incrby key increment

    o(1)

    decrby key decrement

    o(1)

    incrbyfloat key increment

    o(1)

    append key value

    o(1)

    strlen key

    o(1)

    setrange key offset value

    o(1)

    getrange key start end

    oo),n是寧符串長度,由于獲取字符串非常快,所以

    如果字符非不是很長,可以視阿為O(1)

三、內部編碼

  • 字符串類型的內部編碼有3種:

    • int:8個字節的長整型

    • embstr:小于等于39個字節的字符串

    • raw:大于39個字節的字符串

演示說明

  • Redis會根據當前值的類型和長度決定使用哪種內部編碼實現

  • 整數類型示例如下:

  • 短字符串示例如下:

  • 長字符串示例如下:

四、典型使用場景

①緩存功能

  • 下圖是比較典型的緩存使用場景,其中Redis作為緩存層,MySQL作為存儲層,絕大部分請求的數據都是從Redis中獲取。由于Redis具有支撐高并發的特性,所以緩存通常能起到加速讀寫和降低后端壓力的作用

  • 下面偽代碼模擬了上圖的訪問過程:

//1.該函數用于獲取用戶的基礎信息UserInfo getUserInfo(long id){...}//2.首先從Redis獲取用戶信息:// 定義鍵userRedisKey = "user:info:" + id;// 從Redis獲取值value = redis.get(userRedisKey);if (value != null) {// 將值進行反序列化為UserInfo并返回結果userInfo = deserialize(value);return userInfo;}//3.如果沒有從Redis獲取到用戶信息,需要從MySQL中進行獲取,并將結果回寫到Redis,添加1小時(3600秒)過期時間://從MySQL獲取用戶信息userInfo = mysql.get(id);// 將userInfo序列化,并存入Redisredis.setex(userRedisKey, 3600, serialize(userInfo));// 返回結果return userInfo
  • 整個功能的偽代碼如下:

UserInfo getUserInfo(long id){userRedisKey = "user:info:" + idvalue = redis.get(userRedisKey);UserInfo userInfo;if (value != null) {userInfo = deserialize(value);} else {userInfo = mysql.get(id);if (userInfo != null)redis.setex(userRedisKey, 3600, serialize(userInfo));}return userInfo;}
  • 應用場景1:緩存熱門圖片

set redis-log.jpg redis-log-data
  • 應用場景2:存儲文章。當用戶想在博客中撰寫一篇新文章的時候,程序就需要把文章的標題、內容、作者、發表時間等多 項信息存儲起來,并在用戶閱讀文章的時候取出來這些信息。可以使用 mset mget msetnx 命令來進行

  • 開發提示:

    • 與MySQL等關系型數據庫不同的是,Redis沒有命令空間,而且也沒有對鍵名有強制要求(除了不能使用一些特殊字符)

    • 但設計合理的鍵名,有利于防止鍵沖突和項目的可維護性,比較推薦的方式是使用“業務名:對象 名:id:[屬性]”作為鍵名(也可以不是分號)

    • 例如MySQL的數據庫名為 vs,用戶表名為user,那么對應的鍵可以用"vs:user:1","vs:user:1:name"來表示,如果當前Redis只被一個業務使用,甚至可以去掉“vs:”。如 果鍵名比較長,例如“user:{uid}:friends:messages:{mid}”,可以在能描 述鍵含義的前提下適當減少鍵的長度,例如變為“u:{uid}:fr:m:{mid}”,從而減少由于鍵過長的內存浪費

②計數

  • 許多應用都會使用Redis作為計數的基礎工具,它可以實現快速計數、 查詢緩存的功能,同時數據可以異步落地到其他數據源

  • 應用場景1:文章長度計數功能、文章摘要、文章計數

    • 文章長度:STRLEN article:10086:content

    • 文章摘要:GETRANGE article:10086:content 0 5

    • 文章閱讀計數:INCRBY article:10086:count

  • 應用場景2:例如筆者所在團隊的視頻播放數系統就是使用Redis作為視頻播放數計數的基礎組件,用戶每播放一次視頻,相應的視頻播放數就會自增1。代碼如下所示

long incrVideoCounter(long id) {
key = "video:playCount:" + id;
return redis.incr(key);
}
  • 開發提示:實際上一個真實的計數系統要考慮的問題會很多:防作弊、按照不同維度計數,數據持久化到底層數據源等

③共享Session

  • 如下圖所示,一個分布式Web服務將用戶的Session信息(例如用戶登錄信息)保存在各自服務器中,這樣會造成一個問題,出于負載均衡的考慮,分布式服務會將用戶的訪問均衡到不同服務器上,用戶刷新一次訪問可能會發現需要重新登錄,這個問題是用戶無法容忍的

  • 為了解決這個問題,可以使用Redis將用戶的Session進行集中管理,如下圖所示,在這種模式下只要保證Redis是高可用和擴展性的,每次用戶更新或者查詢登錄信息都直接從Redis中集中獲取

④限速器

  • 應用場景1:很多應用出于安全的考慮,會在每次進行登錄時,讓用戶輸入手機驗證 碼,從而確定是否是用戶本人。但是為了短信接口不被頻繁訪問,會限制用 戶每分鐘獲取驗證碼的頻率,例如一分鐘不能超過5次,如下圖所示

  • 此功能可以使用Redis來實現,下面的偽代碼給出了基本實現思路:

phoneNum?=?"138xxxxxxxx";key?=?"shortMsg:limit:"?+?phoneNum;//SET?key?value?EX?60?NXisExists?=?redis.set(key,1,"EX?60","NX");if(isExists?!=?null?||?redis.incr(key)?<=5){//?通過}else{//?限速}
  • 應用場景2:防止用戶的賬號遭到暴力破解,如果同個賬號連續好幾次輸入錯誤的密碼,則限制賬號的登錄,只 能等 30 分鐘后再次登錄,比如設置 3 次

    • 1)SET max:execute:times 3

    • 2)密碼出錯時 DECR max:execute:times

    • 3)當 max:execute:times 的值小于 0 時則禁止登錄,并可以設置 SETEX login:error:darren 1800 "Incorrect password",然后使用 TTL login:error:darren 1800 檢測對應剩余的時間

  • 應用場景3:例如一些網站為了防止網頁內容被網絡爬蟲瘋狂抓取,限制一個IP地址在固定的時間段內能夠訪問的頁面數量.

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/444480.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/444480.shtml
英文地址,請注明出處:http://en.pswp.cn/news/444480.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

leetcode252. 會議室

給定一個會議時間安排的數組&#xff0c;每個會議時間都會包括開始和結束的時間 [[s1,e1],[s2,e2],...] (si < ei)&#xff0c;請你判斷一個人是否能夠參加這里面的全部會議。 示例 1: 輸入: [[0,30],[5,10],[15,20]] 輸出: false 示例 2: 輸入: [[7,10],[2,4]] 輸出: tr…

(十八)深入淺出TCPIP之epoll的一些思考

Epoll基本介紹在linux的網絡編程中&#xff0c;很長的時間都在使用select來做事件觸發。在linux新的內核中&#xff0c;有了一種替換它的機制&#xff0c;就是epoll。相比于 select&#xff0c;epoll最大的好處在于它不會隨著監聽fd數目的增長而降低效率。因為在內核中的select…

leetcode292. Nim 游戲

你和你的朋友&#xff0c;兩個人一起玩 Nim 游戲&#xff1a;桌子上有一堆石頭&#xff0c;每次你們輪流拿掉 1 - 3 塊石頭。 拿掉最后一塊石頭的人就是獲勝者。你作為先手。 你們是聰明人&#xff0c;每一步都是最優解。 編寫一個函數&#xff0c;來判斷你是否可以在給定石頭…

C++:16---強制類型轉換和類型轉換

舊式的強制類型轉換 在早期C/C++中,顯式地進行強制類型的轉換有以下兩種形式:type (expr) ; //函數形式的強制類型轉換(type) expr; //C語言風格的強制類型轉換比如: char c = 12; int b = (int)c; float f = float(b); C++的新式強制類型轉換…

Nginx不停機優雅升級

最近線上運行的游戲越來越多,云服務商也給我推送提示系統升級,漏洞補丁升級,也有nginx更新的。 有一些比較關鍵性的系統補丁需要立即更新處理,有一些可以換一換不用升級,但此nginx升級的需求比較迫切,但更新可能需要重啟nginx。 這將會影響到我們這樣的一個登錄業務邏輯…

leetcode186. 翻轉字符串里的單詞 II

給定一個字符串&#xff0c;逐個翻轉字符串中的每個單詞。 示例&#xff1a; 輸入: ["t","h","e"," ","s","k","y"," ","i","s"," ","b","l…

Nginx大規模并發原理

Nginx在主流硬件上的并發數為十萬,網絡處理方面的領先地位,歸功于突破性的事件驅動架構。 Nginx在每顆內核上創建一個工作進程,有效利用硬件資源。 在單個工作進程中交替處理多個連接,應對突如其來的網絡流量。 Nginx資源管理 Nginx使用狀態機管理流量。 非阻塞事件…

使用 CXF 做 webservice 簡單例子

轉&#xff1a;http://www.cnblogs.com/frankliiu-java/articles/1641949.html Apache CXF 是一個開放源代碼框架&#xff0c;提供了用于方便地構建和開發 Web 服務的可靠基礎架構。它允許創建高性能和可擴展的服務&#xff0c;您可以將這樣的服務部署在 Tomcat 和基于 Spring …

老司機整理對Nginx性能優化

Nginx性能優化應遵循一個原則:一次只調整一項,調整不理想,將修改還原。 Linux參數 Nginx很多功能直接使用操作系統實現,操作系統決定nginx上限。 現代linux內核(2.6+)涵蓋了大多應用場景,查看linux內核日志,找出參數過低的提示消息,根據建議調整。 連接隊列 若傳入…

leetcode189. 旋轉數組

給定一個數組&#xff0c;將數組中的元素向右移動 k 個位置&#xff0c;其中 k 是非負數。 示例 1: 輸入: [1,2,3,4,5,6,7] 和 k 3 輸出: [5,6,7,1,2,3,4] 解釋: 向右旋轉 1 步: [7,1,2,3,4,5,6] 向右旋轉 2 步: [6,7,1,2,3,4,5] 向右旋轉 3 步: [5,6,7,1,2,3,4] 示例 2: 輸…

Nginx 配置UDP負載均衡

Nginx 1.9.13開始支持UDP負載勻衡&#xff0c;現代應用通常使用多種協議&#xff0c;很多核心Internet協議都早于HTTP&#xff0c;支持UDP勢在必行。 UDP常用于非事務性的輕量級協議&#xff0c;如&#xff1a;DNS、syslog、RADIUS。 這些協議對可靠性沒有嚴格要求&#xff0…

leetcode191. 位1的個數

編寫一個函數&#xff0c;輸入是一個無符號整數&#xff0c;返回其二進制表達式中數字位數為 ‘1’ 的個數&#xff08;也被稱為漢明重量&#xff09;。 示例 1&#xff1a; 輸入&#xff1a;00000000000000000000000000001011 輸出&#xff1a;3 解釋&#xff1a;輸入的二進制…

Nginx location執行順序和匹配規則

nginx location執行順序和匹配原則根據location的特點分為普通和正則兩種,執行順序和匹配規則的差異也在于此。 執行順序 nginx會優先執行普通location,不管普通location是否匹配,都會再次轉向執行正則location,一旦第一個正則location被滿足,則停止向后執行。 匹配原則…

Nginx 配置TCP負載均衡

Nginx從1.9.0版本開始,新增加了一個stream模塊,用來實現四層協議的轉發、代理或者負載均衡等鑒于Nginx在負載均衡和web service上的成功,和Nginx良好的框架,stream模塊前景一片光明。 Nginx的stream模塊默認不會自帶安裝,需要編譯安裝的時候手動添加上這個模塊,不過我的系…

leetcode162. 尋找峰值 變種二分見過嗎

峰值元素是指其值大于左右相鄰值的元素。 給定一個輸入數組 nums&#xff0c;其中 nums[i] ≠ nums[i1]&#xff0c;找到峰值元素并返回其索引。 數組可能包含多個峰值&#xff0c;在這種情況下&#xff0c;返回任何一個峰值所在位置即可。 你可以假設 nums[-1] nums[n] -…

(十九)TCPIP面試寶典-進入大廠必備總結(上)

TCP 作為傳輸層的協議,是一個IT工程師素養的體現,也是面試中經常被問到的知識點。在此,我將 TCP 核心的一些問題梳理了一下,希望能幫到各位。 實際上這篇文章相當于是復習之前的網絡基礎部分。只不過這篇文章的提問方式更靈活,也是讓讀者們懂得變通,更熟悉TCP。 TCP 和 U…

leetcode348. 判定井字棋勝負 好麻煩的代碼

請在 n n 的棋盤上&#xff0c;實現一個判定井字棋&#xff08;Tic-Tac-Toe&#xff09;勝負的神器&#xff0c;判斷每一次玩家落子后&#xff0c;是否有勝出的玩家。 在這個井字棋游戲中&#xff0c;會有 2 名玩家&#xff0c;他們將輪流在棋盤上放置自己的棋子。 在實現這…

C++:17---sizeof運算符

功能:以字節位單位,返回一個表達式或一個數據類型所占的字節數返回值類型:是size_t類型sizeof有無括號:sizeof不加括號,后面不可以直接跟數據類型sizeof加括號,后面既可以跟表達式也可以跟數據類型注意事項對引用類型執行sizeof運算得到被引用對象所占空間的大小對指針執…

leetcode345. 反轉字符串中的元音字母

編寫一個函數&#xff0c;以字符串作為輸入&#xff0c;反轉該字符串中的元音字母。 示例 1: 輸入: "hello" 輸出: "holle" 示例 2: 輸入: "leetcode" 輸出: "leotcede" 說明: 元音字母不包含字母"y"。 思路&#xff1a…

Redis:10---List對象

一、列表對象概述列表類型是用來存儲多個有序的字符串&#xff0c;一個列表最多可以存儲多個元素。列表是一種比較靈活的數據結構&#xff0c;它可以充當棧和隊列的角色&#xff0c;在實際開發上有很多應用場景特點&#xff1a;一個列表可以存儲多個字符串&#xff0c;相同元素…