SSM使用redis開發流程,你真的熟悉嗎?(包括redis安裝啓動,數據類型,持久化,集羣)

站在一級臺階上
自以爲窺見了天光。

1,什麼是redis

Redis(全稱:Remote Dictionary Server 遠程字典服務)是一個開源的使用ANSI C語言編寫、支持網絡、可基於內存亦可持久化的日誌型、Key-Value數據庫,並提供多種語言的API。

2,使用redis的優點

性能極高 – Redis能支持超過 100K+ 每秒的讀寫頻率。
豐富的數據類型 – Redis支持二進制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 數據類型操作。
原子 – Redis的所有操作都是原子性的,同時Redis還支持對幾個操作全並後的原子性執行。
豐富的特性 – Redis還支持 publish/subscribe, 通知, key 過期等等特性。

3,使用redis的缺點

是數據庫容量受到物理內存的限制,不能用作海量數據的高性能讀寫,因此Redis適合的場景主要侷限在較小數據量的高性能操作和運算上。

總結: Redis受限於特定的場景,專注於特定的領域之下,速度相當之快,目前還未找到能替代使用產品。

4,redis的安裝

Redis是c語言開發的。
安裝redis需要c語言的編譯環境。如果沒有gcc需要在線安裝。yum install gcc-c++

安裝步驟:
第一步:redis的源碼包上傳到linux系統。
第二步:解壓縮redis。
第三步:編譯。進入redis源碼目錄。make
第四步:安裝。make install PREFIX=/usr/local/redis
PREFIX參數指定redis的安裝目錄。一般軟件安裝到/usr目錄下

5,redis的連接

5.1,redis的啓動

前端啓動:在redis的安裝目錄下直接啓動redis-server.

[root@localhost bin]# ./redis-server 

後臺啓動:
把/root/redis-3.0.0/redis.conf複製到/usr/local/redis/bin目錄下

[root@localhost redis-3.0.0]# cp redis.conf /usr/local/redis/bin/

後臺啓動的話,需要修改配置文件,打開安裝的redis的文件目錄,打開裏面的redis.conf的配置文件,把配置文件的daemonize no改成daemonize yes,使用vim命令進行修改,使用“/內容”進行查找。

啓動

[root@localhost bin]# ./redis-server redis.conf

判斷是否啓動可查看系統進程

[root@localhost bin]# ps aux|grep redis

啓動成功

5.2,Redis-cli

命令行使用

[root@localhost bin]# ./redis-cli 

默認連接localhost運行在6379端口的redis服務

[root@localhost bin]# ./redis-cli -h 192.168.25.153 -p 6379

-h:連接的服務器的地址
-p:服務的端口號

關閉redis

[root@localhost bin]# ./redis-cli shutdown

5.3,Redis的五種數據類型

主要介紹常用的String和hash,有時間會出命令大全
keys * 查詢所有鍵

5.3.1,String類型

String:key-value(做緩存)
Redis中所有的數據都是字符串。命令不區分大小寫,key是區分大小寫的。Redis是單線程的。Redis中不適合保存內容大的數據。

存取數據,set和get方法

127.0.0.1:6379> set name zhangsan
OK
127.0.0.1:6379> get name
"zhangsan"

自增自減,incr和decr,沒有則自動創建

127.0.0.1:6379> incr ago
(integer) 1
127.0.0.1:6379> get ago
"1"

5.3.2,Hash類型(做緩存)

相當於一個key對於一個map,map中還有key-value
使用hash對key進行歸類。
Hset:向hash中添加內容
Hget:從hash中取內容

127.0.0.1:6379> hset key name zhangsan
(integer) 1
127.0.0.1:6379> hget key name
"zhangsan"

5.3.3,List類型

有順序可重複

5.3.4,Set類型

無序不重複

5.3.5,SortedSet類型

有序不重複

5.4,Key命令

expire key second:設置key的過期時間
ttl key:查看key的有效期(-1代表持久化,-2代表已過期)
persist key:清除key的過期時間。Key持久化

127.0.0.1:6379> expire a 50
(integer) 1
127.0.0.1:6379> ttl a
(integer) 34
127.0.0.1:6379> persist a
(integer) 1
127.0.0.1:6379> ttl a
(integer) -1

6,Redis的持久化方案

Redis的所有數據都是保存到內存中的。

:Rdb

Rdb:(默認方案)快照形式,定期把內存中當前時刻的數據保存到磁盤。Redis默認支持的持久化方案,存在丟失數據的風險。
—在redis.conf配置文件中配置

save 900 1
save 300 10
save 60 a0000

900秒內執行1次的話會在900秒的時候持久化數據…

:AOF

aof形式:append only file。把所有對redis數據庫操作的命令,增刪改操作的命令。保存到文件中。數據庫恢復時把所有的命令執行一遍即可,會降低redis的性能。
—在redis.conf配置文件中配置

appendonly  yes

7,Redis集羣的搭建

7.1,redis-cluster架構圖

在這裏插入圖片描述
redis-cluster投票:容錯,有超過一半的認爲其中一個出問題了,那真個redis就集體罷工了
在這裏插入圖片描述
架構細節:
(1)所有的redis節點彼此互聯(PING-PONG機制),內部使用二進制協議優化傳輸速度和帶寬.
(2)節點的fail是通過集羣中超過半數的節點檢測失效時才生效.
(3)客戶端與redis節點直連,不需要中間proxy層.客戶端不需要連接集羣所有節點,連接集羣中任何一個可用節點即可
(4)redis-cluster把所有的物理節點映射到[0-16383]slot上,cluster 負責維護node<->slot<->value

如何讓n太服務器共同承擔文件存儲任務,而不是由一個服務器工作?

Redis 集羣中內置了 16384 個哈希槽,當需要在 Redis 集羣中放置一個 key-value 時,redis 先對 key 使用 crc16 算法算出一個結果,然後把結果對 16384 求餘數,這樣每個 key 都會對應一個編號在 0-16383 之間的哈希槽,redis 會根據節點數量大致均等的將哈希槽映射到不同的節點

7.,2,Redis集羣的搭建

Redis集羣中至少應該有三個節點。要保證集羣的高可用,需要每個節點有一個備份機。
Redis集羣至少需要6臺服務器。
搭建僞分佈式。可以使用一臺虛擬機運行6個redis實例。需要修改redis的端口號7001-7006

7.2.1,集羣搭建環境

1、使用ruby腳本搭建集羣。需要ruby的運行環境。
安裝ruby
yum install ruby
yum install rubygems

2、安裝ruby腳本運行使用的包。

[root@localhost ~]# gem install redis-3.0.0.gem 
Successfully installed redis-3.0.0
1 gem installed
Installing ri documentation for redis-3.0.0...
Installing RDoc documentation for redis-3.0.0...

3.編譯rb腳本文件

查詢後綴名爲rb的文件
[root@localhost ~]# cd redis-3.0.0/src
[root@localhost src]# ll *.rb
-rwxrwxr-x. 1 root root 48141 4月   1 2015 redis-trib.rb
把腳本拷貝到6個redis的文件夾中
[root@Jeck1 src]# cp redis-trib.rb /usr/local/redis-cluster

rb腳本運行還需要第三方庫,redis3.0.0.gem

[root@Jeck1 local]# gem install redis-3.0.0

7.2.2,搭建步驟(關閉防火牆)

需要6臺redis服務器。搭建僞分佈式。
需要6個redis實例。
需要運行在不同的端口7001-7006

第一步:創建6個redis實例,每個實例運行在不同的端口。需要修改redis.conf配置文件。配置文件中還需要把cluster-enabled yes前的註釋去掉。
在這裏插入圖片描述
第二步:啓動每個redis實例。
設置啓動腳本文件start-all.sh

在這裏插入圖片描述
第三步:使用ruby腳本搭建集羣

[root@Jeck1 redis-cluster]# ./redis-trib.rb create --replicas 1 
192.168.240.129:7001 
192.168.240.129:7002 
192.168.240.129:7003 
192.168.240.129:7004 
192.168.240.129:7005 
192.168.240.129:7006

系統說把7001-7003作爲主數據庫
在這裏插入圖片描述
把7004-7006作爲備用數據庫,其中7001和7003相對應其他類似
在這裏插入圖片描述
每個數據庫分配的哈希槽也告訴了
在這裏插入圖片描述

7.2.3,集羣的使用方法

Redis-cli連接集羣

[root@localhost redis-cluster]# redis01/redis-cli -p 7002 -c
-c:代表連接的是redis集羣

8,Jedis

需要把jedis依賴的jar包添加到工程中。Maven工程中需要把jedis的座標添加到依賴。推薦添加到服務層。

8.1,連接單機版

第一步:創建一個Jedis對象。需要指定服務端的ip及端口。
第二步:使用Jedis對象操作數據庫,每個redis命令對應一個方法。
第三步:打印結果。
第四步:關閉Jedis

	@Test
	public void jedisTest() {
//		創建jedis對象
		Jedis jedis = new Jedis("192.168.240.129", 6379);
		//使用jedis對象執行操作
		jedis.set("name", "張三");
		jedis.set("name", "lisi");
		String string = jedis.get("name");
		System.out.println(string);
		//關閉連接
		jedis.close();
	}

8.2,連接單機版使用連接池

第一步:創建一個JedisPool對象。需要指定服務端的ip及端口。
第二步:從JedisPool中獲得Jedis對象。
第三步:使用Jedis操作redis服務器。
第四步:操作完畢後關閉jedis對象,連接池回收資源。
第五步:關閉JedisPool對象。

	@Test
	public void jedisPoolTest() {
		//創建連接池對象
		JedisPool jedisPool=new JedisPool("192.168.240.129",6379);
		//獲取jedis
		Jedis jedis = jedisPool.getResource();
		//執行操作
		String string = jedis.get("name");
		System.out.println(string);
		//關閉連接,連接池回收資源
		jedis.close();
		//關閉連接池
		jedisPool.close();
	}

8.3,連接集羣版

第一步:使用JedisCluster對象。需要一個Set參數。Redis節點的列表。
第二步:直接使用JedisCluster對象操作redis。在系統中單例存在。
第三步:打印結果
第四步:系統關閉前,關閉JedisCluster對象。

	@Test
	public void jedisClusterTest() {//集羣使用
		//創建一個JedisCluster對象,有一個參數nodes是一個set類型,set中包含着若干個HostAndPort對象
		Set<HostAndPort> nodes=new HashSet<>();
		nodes.add(new HostAndPort("192.168.240.129",7001));
		nodes.add(new HostAndPort("192.168.240.129",7002));
		nodes.add(new HostAndPort("192.168.240.129",7003));
		nodes.add(new HostAndPort("192.168.240.129",7004));
		nodes.add(new HostAndPort("192.168.240.129",7005));
		nodes.add(new HostAndPort("192.168.240.129",7006));
		JedisCluster jedisCluster=new JedisCluster(nodes);
		//直接使用JedisCluster對象操作redis
		jedisCluster.set("name", "zhangsan");
		jedisCluster.set("ago", "12");
		String string = jedisCluster.get("name");
		System.err.println(string);
		String string2 = jedisCluster.get("ago");
		System.err.println(string2);
		//關閉JidesCluster對象
		jedisCluster.close();
	}

9,向業務邏輯中添加緩存

9.1,接口封裝

常用的操作redis的方法提取出一個接口,分別對應單機版和集羣版創建兩個實現類

9.2 配置applicationContext-redis.xml

9.2.1,配置單機版

	<bean id="jedisClientPool" class="cn.e3mall.common.jedis.JedisClientPool">
		<property name="jedisPool" ref="jedisPool"></property>
	</bean>	
	<bean id="jedisPool" class="redis.clients.jedis.JedisPool">
		<!-- 構造方法參數使用constructor-arg -->
		<constructor-arg name="host" value="192.168.240.129"></constructor-arg>
		<constructor-arg name="port" value="6379"></constructor-arg>
	</bean>

9.2.2,配置集羣版

<bean id="jedisClientCluster" class="cn.e3mall.common.jedis.JedisClientCluster">
		<property name="jedisCluster" ref="jedisCluster"></property>
	</bean>
	<bean id="jedisCluster" class="redis.clients.jedis.JedisCluster">
		<constructor-arg name="nodes">
			<set>
				<bean class="redis.clients.jedis.HostAndPort">
					<constructor-arg name="host" value="192.168.240.129"></constructor-arg>
					<constructor-arg name="port" value="7001"></constructor-arg>
				</bean>
				<bean class="redis.clients.jedis.HostAndPort">
					<constructor-arg name="host" value="192.168.240.129"></constructor-arg>
					<constructor-arg name="port" value="7002"></constructor-arg>
				</bean>
				<bean class="redis.clients.jedis.HostAndPort">
					<constructor-arg name="host" value="192.168.240.129"></constructor-arg>
					<constructor-arg name="port" value="7003"></constructor-arg>
				</bean>
				<bean class="redis.clients.jedis.HostAndPort">
					<constructor-arg name="host" value="192.168.240.129"></constructor-arg>
					<constructor-arg name="port" value="7004"></constructor-arg>
				</bean>
				<bean class="redis.clients.jedis.HostAndPort">
					<constructor-arg name="host" value="192.168.240.129"></constructor-arg>
					<constructor-arg name="port" value="7005"></constructor-arg>
				</bean>
				<bean class="redis.clients.jedis.HostAndPort">
					<constructor-arg name="host" value="192.168.240.129"></constructor-arg>
					<constructor-arg name="port" value="7006"></constructor-arg>
				</bean>
			</set>
		</constructor-arg>
	</bean>

9.3,書寫Test進行操作實現

單機版和集羣版2選1,實現接口的好處,在開發階段可實現單機版進行開發,在正式上線的時候可修改配置文件,實現集羣版

	@Test
	public void demo1() {
		//初始化spring容器
		ApplicationContext ac=new ClassPathXmlApplicationContext("classpath:spring/applicationContext-redis.xml");
		//從spring容器中拿出jedisClient對象
		JedisClient jedis = (JedisClient) ac.getBean(JedisClient.class);//單機版和集羣版都是JedisClient的實現類
		//驚醒操作
		jedis.set("name","zhangsan");
		String string = jedis.get("name");
		System.out.println(string);
	}

9.4,給項目中正式添加redis

9.4.1,給service添加變量

	@Autowired
	private JedisClient jedisClient;

9.4.2,具體實現

		//查詢緩存
		try {
			String hget = jedisClient.hget(content_list, categoryId+"");
			if(!StringUtils.isEmpty(hget)) {
				List<TbContent> selectByExample = JsonUtils.jsonToList(hget, TbContent.class);
				
				EasyUIDataResult result=new EasyUIDataResult();
				result.setRows(selectByExample);
				//取分頁結果
				PageInfo<TbContent> pageInfo=new PageInfo<TbContent>(selectByExample);
				long total = pageInfo.getTotal();
				result.setTotal(total);
				return result;
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		//redis查詢不到就查詢數據庫,並把結果添加到緩存
		try {
			jedisClient.hset("content_list", categoryId+"", JsonUtils.objectToJson(selectByExample));
		} catch (Exception e) {
			e.printStackTrace();
		}

9.4.3,緩存同步

給查詢列表添加redis後,如果進行修改刪除更新操作,而redis中數據沒有改變,這時候就需要緩存同步到redis,已便修改刪除更新操作之後再redis中保存的是最新的數據。
思路是在修改更新刪除操作後刪除redis存儲的數據,重新從數據庫中查到最新數據保存到redis中。

		//緩存同步, 刪除緩存中對應的數據
		jedisClient.hdel(content_list, content.getCategoryId().toString());

文章持續更新,可以微信搜索「 紳堂Style 」第一時間閱讀,回覆【資料】有我準備的面試題筆記。
GitHub https://github.com/dtt11111/Nodes 有總結面試完整考點、資料以及我的系列文章。歡迎Star。
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章