日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

redis的一些坑

發(fā)布時間:2025/7/25 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 redis的一些坑 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

from:http://my.oschina.net/u/875730/blog/378086

0 redis跨機(jī)房使用問題

? 一般地,redis的每個實例都是一個master加上一個slave,這一主一備一般要放在同一個機(jī)房idc,否則會出現(xiàn)各種莫名其妙的問題。為了防止一個idc出問題,可以用scp或者rsync命令把redis數(shù)據(jù)定時(譬如每隔10分鐘或者半小時)地備份到另一個機(jī)房。

1?redisContext盡量在一個線程內(nèi)使用

? ?《從hiredis使用出core談?wù)剅edis多線程的使用》一文中提到:redis是單線程異步模型,hiredis這個客戶端看來也只支持單線程。


2 發(fā)送二進(jìn)制數(shù)據(jù)

《Redis C語言客戶端庫hiredis文檔翻譯》一文提到:

當(dāng)你需要發(fā)送二進(jìn)制安全的命令可以采用%b的格式化方式,同時需要一個字符串指針和size_t類型的字符串長度參數(shù),如下

reply = redisCommand(context, "SET foo %b", value, (size_t) valuelen);

在API內(nèi)部,Hiredis根據(jù)不同的參數(shù)分割命令轉(zhuǎn)化為操作redis數(shù)據(jù)庫的標(biāo)準(zhǔn)命令,你可以格式化多個參數(shù)來構(gòu)造redis的命令,如下

reply = redisCommand(context, "SET key:%s %s", myid, value);

《C++ Redis mset 二進(jìn)制數(shù)據(jù)接口封裝方案》一文作者貌似不知道這個用法,他通過redisCommandArgv這個函數(shù)繞了一圈來發(fā)送二進(jìn)制數(shù)據(jù)。


3 兩級hash

http://www.cnblogs.com/restran/p/4295184.html

每個key-vaulue結(jié)構(gòu),Redis本身的維護(hù)開銷就要80幾字節(jié),即便value存儲的是純數(shù)字(會使用long類型,占用4個字節(jié)),也依然很大,1000萬的數(shù)據(jù),就要占用快1G內(nèi)存。

依據(jù)官方文檔的內(nèi)存優(yōu)化方法,以及這篇文章 節(jié)約內(nèi)存:Instagram的Redis實踐,建議對ID分段作為key,并使用 hash 來存儲第一級 key 的 value,第二級存儲較少的數(shù)據(jù)量(推薦1000),因此第二級的key使用ID的后3位。


4 redis-cli 在非交互模式下直接執(zhí)行命令時附帶模糊參數(shù)

? ?redis-cli -h 127.0.0.1 -p 6379 keys '*'

or redis-cli ?-h 127.0.0.1 -p 6379 keys "*"


5 老版本的sentinel問題注意

最近使用v2.8.19的sentinel,監(jiān)控一個服務(wù)器的配置為:

sentinel monitor server1 127.0.0.1 36379 1

sentinel down-after-milliseconds server1 3000

sentinel parallel-syncs server1 1

sentinel failover-timeout server1 15000

sentinel auth-pass server1 r23456

測試時候一切正常,但是在線上服務(wù)器部署后,發(fā)生主fail的情況的時候,主從切換并沒有發(fā)生,檢查了線上版本的sentinel版本,為v2.6.11。

講過一番檢查,添加了can-failover,就正常了,修改后的配置項為:

sentinel monitor server1 127.0.0.1 36379 1

sentinel can-failover server1 yes

sentinel down-after-milliseconds server1 3000

sentinel parallel-syncs server1 1

sentinel failover-timeout server1 15000

sentinel auth-pass server1 r123456

另外,使用這個版本的sentinel的時候請把conf文件中原有的mymaster相關(guān)配置注釋掉,否則就坑爹了,你會發(fā)現(xiàn)你的監(jiān)控項多了一項mymaster。


6 在一個腳本中批量執(zhí)行多個寫入操作

先把插入操作放入操作文本insert.bat:

?
1 2 3 4 set?a?b set?1?2 set?h?w set?f?u

如果是在unix上寫的insert.bat,請用命令"unix2dos ?insert.bat"轉(zhuǎn)換其格式。

然后執(zhí)行命令:cat insert.bat | ./redis-cli --pipe,或者如下腳本:

?
1 2 3 4 5 #!/bin/sh host=$1 port=$; password=$3 cat?insert.bat?|?./redis-cli?-h?$host?-p?$port?-a?$password?--pipe

7 twemproxy及時感知死掉的redis server

from:http://www.oschina.net/translate/twemproxy-a-twitter-redis-proxy?評論

我在虛擬機(jī)上安裝了twemproxy,使用的是nutcracker-0.2.2.tar。配置文件如下:

lpha:
listen: 127.0.0.1:22121
hash: fnv1a_64
distribution: ketama
auto_eject_hosts: true
redis: true
server_retry_timeout: 2000
server_failure_limit: 1
servers:
- 127.0.0.1:6379:1
- 127.0.0.1:6380:1
- 127.0.0.1:6381:1

三個redis都啟動時,服務(wù)正常。當(dāng)我把 127.0.0.1:6379停掉時,該服務(wù)節(jié)點不自動摘除,執(zhí)行set命令時一直有服務(wù)拒絕的命令。

[root@localhost?redis]# ./redis-cli -p 22121 set 1 1
(error) ERR Connection refused
當(dāng)我把故障的redis恢復(fù)后,發(fā)現(xiàn)服務(wù)正常了。結(jié)果全部是OK
以上測試可以看出,故障節(jié)點沒有自動摘除。
請問專家,這是為何?我沒有配置好?

server_retry_timeout: 2000->60000
server_failure_limit: 1->0

試試修改以上兩個配置,第一個retry的間隔時間要拉長,不然你的nutcracker一直在重試連接,自然一直摘不掉機(jī)器;第二個容忍的錯誤數(shù)可以設(shè)置成0容忍,就是說有錯誤立馬摘掉這個機(jī)器。

我把server_retry_timeout: 20000000這個重連時間改的更長了
這次真的摘除了~謝謝啊!
原來這個參數(shù)代表的是發(fā)現(xiàn)故障后,恢復(fù)連接間隔時間,我還一直以為重試是內(nèi)部機(jī)制呢,原來不是。。這個有點坑爹

8 persistence

? redis的數(shù)目備份有rdb和aof兩種格式,rdb可以認(rèn)為是一個時刻的redis內(nèi)存數(shù)據(jù)的二進(jìn)制鏡像,而aof則是redis數(shù)據(jù)的mysql的binlog式的寫請求日志文件。

?rdb文件保存方式特點在于:1 在數(shù)據(jù)非常多的情況下,使用rdb會占用比aof文件更少的磁盤,也更適合遠(yuǎn)程數(shù)據(jù)備份,一旦創(chuàng)建完畢就不會再被修改;2 redis啟動后能夠很快加載rdb文件,如果要重放aof的命令則會很耗費時間;3 rdb文件是某個時間點redis所有數(shù)據(jù)的image,redis會fork一個進(jìn)程來進(jìn)行工作,短則數(shù)毫秒長則一秒多內(nèi)外部客戶端的請求不會被及時處理,不能及時保持所有時刻的數(shù)據(jù),一旦發(fā)生事故,最近一段時間內(nèi)的寫請求的數(shù)據(jù)就會丟失;4 redis執(zhí)行rdb文件保存的時候,會fork一個子進(jìn)程創(chuàng)建一個臨時文件進(jìn)行數(shù)據(jù)保存任務(wù),數(shù)據(jù)保存完畢后它會刪除老的文件并把新的文件rename為老文件的名字;

? aof文件保存方式的特點在于:1 aof保存有三種策略:無fsync(即不保存數(shù)據(jù)把redis作為一個cache)、每秒鐘進(jìn)行一次fsync和每次寫請求都執(zhí)行fsync,默認(rèn)是fsync每秒,這種策略被執(zhí)行的時候redis會創(chuàng)建一個線程進(jìn)行fsync任務(wù),所以不會影響主線程的工作,就算發(fā)生事故也僅僅丟掉了一秒鐘內(nèi)的請求數(shù)據(jù);2 aof保存的是文本格式的請求log,如果出現(xiàn)用戶不小心執(zhí)行了flushall這種命令,用戶可以手工修改aof文件后重啟redis即可;3 aof文件的缺點就在于size太大,而且執(zhí)行數(shù)據(jù)恢復(fù)的時間太長;4 redis執(zhí)行aof任務(wù)的時候與rdb流程比較相似,redis先fork一個子進(jìn)程創(chuàng)建一個新的aof文件,然后把當(dāng)前進(jìn)程中的數(shù)據(jù)以客戶端與服務(wù)端的通訊方式的寫請求形式保存下來,保存過程中如果有新的寫請求,主進(jìn)程會把這些寫請求寫進(jìn)老的aof文件的同時也創(chuàng)建一個內(nèi)存buffer,以保存這批新的請求命令,子進(jìn)程完成任務(wù)后會發(fā)送signal給父進(jìn)程,父進(jìn)程會delete old aof file并且rename new aof file,然后把buffer中的寫請求追加到new aof file中。

? ? 所以一般安全點的方法就是兩種文件保存方法并用。如果redis正在執(zhí)行rdb保存任務(wù),而用戶發(fā)送了BGREWRITEAOF 命令給redis,則redis會把任務(wù)排隊,返回ok給client,當(dāng)redis執(zhí)行完畢rdb任務(wù)的時候才會執(zhí)行aof任務(wù)。當(dāng)redis啟動執(zhí)行recovery的時候,它會優(yōu)先采用aof文件,因為aof文件的數(shù)據(jù)總比rdb新。

? ? redis執(zhí)行aof任務(wù)主要由rewriteAppendOnlyFileBackground->rewriteAppendOnlyFile完成,查看這個函數(shù)的源碼,可以看到所有的db都存在server.db(容量為server.dbnum)之中,每個db類型的redisDb,其主要成員為dict *dict,即所有key都是按照hashtable羅列的,這個hashtable的優(yōu)點是可以按照iterator那樣去遍歷。

9 codis

?我們線上的?redis?集群最大單服務(wù)的是?800G?左右,?分成32個分片,?對應(yīng)?codis?的32個?Server?group,?總的?qps?大概?10w?左右,?我們用了?2個?codis-proxy?抗著,基本沒壓力 。rocksdb?的存儲引擎:https://github.com/reborndb/qdb,其實啟動后就是個?redis-server,支持了?PSYNC?協(xié)議,所以可以直接當(dāng)成redis從來用 。

codis改進(jìn)了一下redis缺點:

1 redis數(shù)據(jù)量太大的話(22G以上),他的處理性能就開始下降;

2 無法區(qū)分冷熱數(shù)據(jù),內(nèi)存浪費嚴(yán)重;

3 RDB Block住整個服務(wù);

4 寫操作太頻繁,AOF刷盤太多,很容易rewrite

總結(jié)

以上是生活随笔為你收集整理的redis的一些坑的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。