一、redis安裝
1.安裝redis
将redis安裝包放到指定目錄下。并用tar -zxvf redis.*****.tar.gz解壓
2.想把redis安裝到哪裡,就在哪裡建立redis檔案夾。
如 mkdir /home/chx/allSoftCert/redis
2.進入解壓後的目錄内,如redis4.0.0
3.cd src
4.sudo make install PREFIX=/home/chx/allSoftCert/redis
5.cp ../redis.conf /home/allSoft/redis/
6.運作測試:./home/chx/allSoftCert/redis/bin/redis-server /home/chx/allSoftCert/redis/redis.conf
錯誤:如果發生make[1]: Entering directory錯誤,則執行make distclean後再次安裝
7.開啟遠端的端口
ptables -I INPUT -p tcp --dport 6379 -j ACCEPT
iptables save
8.修改密碼
vi /home/chx/allSoftCert/redis/redis.conf
注釋bind 127.0.0.1
修改 daemonize no 為 daemonize yes
解注釋 requirepass foobared 并修改為 requirepass 123456
9.接下裡就可以進行java測試了
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
public class MainJedis {
private static final String REDIS_IP = "192.168.0.156";
private static final String REDIS_AUTH = "123456";
private static final int MAX_TOTAL = 100;//最大連接配接數
private static final int MAX_ID_LE = 10;//最大空閑數
private static final int REDIS_DUAN_KOU = 6379;
public static void main(String[] args) {
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(MAX_TOTAL);//設定最大連接配接數
config.setMaxIdle(MAX_ID_LE);//設定最大空閑數
JedisPool pool = null;
Jedis jedis =null;
try {
pool = new JedisPool(config,REDIS_IP,REDIS_DUAN_KOU);
jedis = new Jedis(REDIS_IP,6379);
jedis.auth(REDIS_AUTH);
jedis.set("chx", "boy");
System.out.println(jedis.get("chx"));
}catch (Exception e) {
e.printStackTrace();
}finally {
if(jedis!=null) {
jedis.close();
}
if(pool!=null) {
pool.close();
}
}
}
}
pom.xml對應如下:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>JedisTest</groupId>
<artifactId>firstJedis</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>firstJedis</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
</dependencies>
</project>
二、JAVA中使用redis
1.java對象存儲在redis内。
兩種方式:
(1).序列化和反序列化。
(2).轉換為json存儲。
2.redis的幾種資料結構
String: 字元串
Hash: 散列
List: 清單
Set: 集合
Sorted Set: 有序集合
3.Jedis基礎指令
jedis.del("key","key2");//删除key
jedis.auth(REDIS_AUTH);//操作密碼
jedis.set("chx", "boy");//放入普通的key-value
jedis.exists("chx");//判斷是否存在某個key
System.out.println("系統中所有鍵如下:");
//查詢系統所有key值
Set<String> keys = jedis.keys("*");
Iterator<String> it=keys.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
//設定key值的儲存時間,機關秒
jedis.expire("chx", 2);
//擷取key的存儲時間,永久生存或者不存在的都傳回-1
jedis.ttl("chx");
//移除key的生存時間
jedis.ttl("chx");
jedis.type("chx"));//檢視key所儲存的值的類
jedis.rename("old", "new");//修改key值
jedis.mset("chx2", "value2", "chx3", "value3");//一次性增加多個key-value
List<String> mget = jedis.mget("chx","chx1","chx2","chx3");//一次性擷取多個value
jedis.setnx("chx", "change");//放入key-value時防止覆寫舊值的方法
jedis.flushDB();//清空DB所有資料
Jedis 清單(List):
jedis.rpush("myList", "1","2","3","a");//從右邊添加,即尾插入
jedis.lrange("myList", 0, -1);//從左邊擷取
jedis.lrem("myList", 2, "1");//從左側删除2個值為1的資料
Jedis集合Set
System.out.println("清空庫中所有資料:" + jedis.flushDB());
jedis.sadd("mySet", "1","2","3");
System.out.println(jedis.smembers("mySet"));
Jedis hash
System.out.println("清空庫中所有資料:" + jedis.flushDB());
jedis.hset("myHash", "name", "chx");
Map<String, String> users = new HashMap<String, String>();
users.put("age", "18");
jedis.hmset("myHash", users)
System.out.println(jedis.hgetAll("myHash"));
4.切片和非切片連接配接池的概念
JedisPool連一台Redis,ShardedJedisPool連Redis叢集,通過一緻性雜湊演算法決定把資料存到哪台上。
5.redis有密碼的情況下關閉redis-server服務
./redis-cli -a 123456 shutdown
6.叢集下使用reids:
檢視此文章
三、常用redis資料類型
1.字元串:
在Redis中字元串類型的Value最多可以容納的資料長度是512M。
set xx(key) xx(value),傳回OK,如果key存在會覆寫。
get xx(key),隻能擷取String 類型的,不是String 會報錯。
append key value:在原有的value後追加;如果該key不存在,則重新建立一個key/value。
msetnx key1 value1 key2 value2:如果key1存在,則key2也放不進去。隻有都不存在時才能放進去。
2.list:
lset xx(key) index xx(value):設定連結清單中的index的腳标的元素值,0-連結清單的頭元素,-1-連結清單的尾元素。
lrem key count value:删除count個值為value的元素,count>0,從頭向尾删除count個值為value的元素,count<0,則從尾向頭删除。如果count=0,則删除連結清單中所有等于value的元素。
linsert key before|after pivot value:在pivot元素前|後插入value。
3.set:
Set集合中不允許出現重複的元素。
smembers xx(key):擷取set中所有的成員。
scard xx(key):擷取set中成員的數量。
sismember xx(setX) xxv(value):判斷xxv是否在setX中,1存在,0不存在。
srem xx(setX) xxv(value):删除value。
sdiff set1 set2:傳回set1中set2沒有的資料(既差集,按順序傳回)。
4.Hash:
結構為hash(key)-field(多個)-value(多個)。
每一個Hash可以存儲 232 - 1 鍵值對(40多億)。
hset hash field value:為指定的hash設定field/value對(鍵值對)。如果哈希表不存在,将建立HASH并進行操作。設定成功傳回 1,覆寫傳回0。
hget hash field:傳回指定hash的key的值。
hexists hash field:判斷指定的hash中的field是否存在。
hlen hash:hash中field的數量。
四、分布式情況下存儲使用者狀态
當單台機器不能滿足性能提升時,大多采用分布式,但是session是基于cookie進行擷取的,導緻不同機器的jsessionid會不同,而導緻使用者通路不同機器時會重新登入。
是以一般用redis等記憶體存儲的資料庫進行session存儲。原理是将sessionid為key值,使用者資訊為value進行存儲。每次通路先去redis擷取使用者資訊,沒有說明是非法登入。同時redis可以設定資料的過期時間,由此可以基本實作原session功能。
五、Redis面試相關
Redis是高可用,NoSQL(not-only sql,泛指非關系型資料庫)的資料庫。
1.緩存穿透:就是由于大量通路不在redis的資料(比如非法傳入ID為-1),導緻每次都需要去資料庫查詢,導緻資料庫無法承載而崩潰。此時重新開機都無法解決,因為新的通路仍會導緻崩潰。這裡可以用布隆過濾器做處理,布隆過濾器是一個 bit 向量或者說 bit 數組,資料的hash的每個數值位(如Hash值等于147)散落在bit數組内。是以查詢時如果1、4、7位有值說明此資料可能存在(之是以不是一定存在是因為Hash沖突),1、4、7位不存在的則一定不存在。參考此文,非常不錯。
2.緩存雪崩:由于熱點資料(注意是熱點)同一時間失效,導緻大量通路湧入時都通路的資料庫而導緻崩潰。
3.緩存擊穿:由于一個熱點資料通路量過大,而此資料失效的瞬間導緻擊穿崩潰。
4.Redis是單線程,至于為什麼這麼快。首先由于Redis的操作都基于記憶體,是以讀寫耗時問題可以忽略,更多的是CPU及網絡帶寬影響其上下限,單線程避免了CPU不必要的上下文切換和競争條件,也避免了鎖的耗時問題。再者,Redis采用Key-Value存儲,基本讀是O(1)的時間複雜度。
5.有關主從複制:從節點僅提供讀操作,主節點提供寫操作。從節點中的定時任務發現主節點資訊,連接配接建立後,主節點将所有資料發送給從節點(資料同步)。主節點把目前的資料同步給從節點後,便完成了複制的建立過程。接下來,主節點就會持續的把寫指令發送給從節點,保證主從資料一緻性。
6.Redis分片及Hash槽相關:首先Redis采用Hash槽來确定資料配置設定到叢集的哪個主機,每個節點的槽位(如0-5000)是需要人工配置的,最大槽位為2的14次方即16384。第一個槽位和最後一個槽位相連,形成一個圓環,需要放入新資料時,利用crc16求出hash值,對16384求餘而确定放入那個節點。之是以不用一緻性hash是為了避免資料傾斜問題。參考此篇文章。是以每次擴充或當機時,隻需要把該節點的所有槽位轉移到新節點即可。
7.有關哨兵:哨兵是一個獨立的程序,顧名思義,哨兵主要用于監控-Master和Slave是否運作正常、提醒-通過API向管理者或者其他應用程式發送通知、自動故障遷移-将失效Master的其中一個Slave更新為新的Master(就像電視裡的巡邏、吹哨、發現危險拿起武器操作一番)。多個哨兵使用投票協定(agreement protocols)來決定是否執行自動故障遷移,以及選擇哪個Slave作為新的Master。
哨兵個數最少是三個,并且建議是奇數個。主要是為了投票主節點是否下線,少數服從多數。幾個哨兵投票為多數的配置,在sentinel.conf裡配置sentinel monitor開頭的一行,最後一個數字即是投票數。
哨兵預設端口号:26379 redis預設端口号6379
redis是沒有復原的。其事務主要是為了能夠全部執行正确的操作。如果在執行時出錯,如轉賬功能,是不會復原的(效率第一的理念)。但是運作前的入隊操作,有文法錯誤是不會送出的。
8.Redis持久化:就兩種,一種是RDB(Redis DataBase),一種是AOF(Append Only File)。
RDB:指定時間間隔内,将記憶體的資料集快照,儲存到磁盤。Redis會建立一個子程序,将快照寫入臨時檔案中,等到持久化結束就覆寫上一次的備份。此過程主程序不進行IO操作。如上所述,很有可能丢失最後一次備份。是以适合完整性和一緻性要求不高的情況,Fork時候是克隆目前主程序,導緻兩倍的記憶體占比,需要考慮記憶體配置。在Redis.conf可以配置檔案名及自動備份時間。
AOF:利用檔案儲存所有寫操作,隻追加不能修改,Redis重新開機就會讀取此檔案進行恢複。如果遇到斷電等aof檔案錯亂的情況,可以用redis-check-aof --fix 檔案名 來修複。是以也會丢失近一段時間的資料,不過一般比RDB丢失的少。在redis.conf裡可修改當占用多大存儲(auto-aof-rewrite-min-size 64mb 預設64兆)時進行壓縮及比上次膨脹百分比(auto-aof-rewrite-percentage 100預設100%),
9.事務:MULTI開始事務,添加指令(任何符合規範的指令get set等),EXEC執行事務。一個指令在錄入時失敗則全失敗(即EXEC之前失敗)!如果是運作時失敗則其他的是成功的!!
Watch 一個或多個key表示監視一個或多個key,執行exec指令後,鎖都被釋放。如果期間有其他人改動過這些key的value值,則事務被打斷。
10.關于ACID:原子性(Atomicity)、一緻性(Consistency)、隔離性(Isolation)、持久性(Durability)是相對于事務而言。Redis保證了資料的一緻性(記憶體模式下,重新開機後為空,不會一部分儲存一部分未儲存)、隔離性(單線程不涉及其他事務),實作了部分原子性(如第九條,EXEC可以在運作失敗時完成其他成功語句),但是沒有持久性,因為Redis事務執行過程中如果崩潰,不一定能夠恢複。