DAY05
知識回顧+遺留問題
2018年1月15日
19:32
前4天的脈絡
複習的順序:將其中的所有非代碼技術先複習
把代碼敲一遍,分別的引入技術
1 nginx 一個服務器7萬/秒 轉發 併發 5萬 3萬
是京淘中提升併發的第一道關卡
20臺nginx集羣就可以搞定每秒100萬併發
2 屬性注入
擴展Bean加載數據
後處理bean注入擴展類把數據傳遞給僞service
後臺controller圖片上傳注入僞service使用屬性
3 nginx的匹配規則(與優先級)
· 精確匹配=
· 字符串前綴匹配 ^~
· 按照配置順序的正則匹配(AB都匹配上了,配置在前的匹配)
· 不帶任何修飾的前綴匹配/images/
· 當所有匹配成功時,停止匹配,按照當前匹配規則處理請求
· 前綴匹配,有包含關係時,按最大匹配長度原則匹配
· 最低優先級是通配符 /
location = /images{
return 205;}
location ^~ /images {
return 200;}
location ^~ /images/test.png {
return 201;}
location ~* \.png$ {
return 203;}
location ~ \.(gif|jpg|png|js|css)$ {
return 202;}
location / {
return 204;}
http://localhost/ 返回204
http://localhost/images 205和204?
http://localhost/images/id 200
http://localhost/images/test.png 返回201 前綴最長匹配原則
http://localhost/haha.png 返回203 順序正則原則
4 nginx負載均衡
輪詢:將所有的訪問平均分配給服務器庫中配置的服務器;
nginx負載均衡
2018年1月16日
10:05
權重:
根據不同機器性能,計算相對的訪問負載承受,從而使用權重配置
負載的量
upstream jt1710{
server 192.168.40.170:8081 ;
server 192.168.40.170:8082 ;
server 192.168.40.170:8080 ;
server 192.168.40.170:8081 ;
server 192.168.40.170:8081 ;
server 192.168.40.170:8081 ;
server 192.168.40.170:8081 ;
server 192.168.40.170:8081 ;}
權重的關鍵字
weight:權重的優先量級;數字越大,訪問次數越多
down;宕機狀態永不訪問;
當服務器宕機不可恢復時,nginx會根據權重或者輪詢配置
繼續訪問,連接超時訪問失敗,但是不會停止訪問,
down一定程度的減少了資源的損耗
session黏着
負載均衡中的session共享問題
解決session共享問題
session黏着
當用戶通過ngnix訪問某一個tomcat後,使用session黏着,保證後續訪問永遠
訪問者一臺
1 ip_hash
利用客戶端請求的ip和端口(192.168.40.170:661)獲取其字符串的hash值
String str="192.168.40.160:8080";
str.hashCode();(未必是正值,&Integer.max_value)
System.out.println(user1.hashCode()&Integer.MAX_VALUE);
System.out.println(user2.hashCode()&Integer.MAX_VALUE);
System.out.println(user3.hashCode()&Integer.MAX_VALUE);
獲取到字符串的整數然後對已有的負載均衡服務器庫數量進行取餘(三臺爲例)
哈希整數N%3=[0,1,2]
如果是4臺呢?對4取餘,依次類推
2 url_hash黏着(依賴第三方插件實現)
訪問服務器的url地址字符串做hash取餘運算
order.jt.com/*****/***.html
具有某一個固定功能的服務器,固定
springSession(HttpSession+redis)
將虛擬機中的後臺系統做完全,還差訪問數據庫
需要修改war包中的jdbc.properties
需要獲取linux系統訪問windows系統的ip地址
商品描述
2018年1月16日
10:57
查看電商中的描述信息,需要大字段屬性保存圖片信息和文本信息
blob/text破壞表的索引,商品描述不能添加到商品列表中
單獨創建一個商品描述表格 tb_item_desc
開發過程
pojo,mapper,service,controller
service不用單獨編寫,直接和ItemService一起保證事務的有效性
級聯新增時從表(tb_item_desc),主表(tb_item)
關聯的鍵是itemId
mybatis+mysql底層實現
調用sql
select last_insert_id;
商品描述的修改(包括數據回顯和修改過程)
http://manage.jt.com/item/query/item/desc/1474391958
點擊編輯按鈕彈出item-edit頁面,以上一個請求
$.getJSON('/item/query/item/desc/'+data.id,function(_data){
if(_data.status == 200){ itemEditEditor.html(_data.data.itemDesc);
}
});
第一個參數:'/item/query/item/desc/'+data.id
第二個參數:回調函數function(_data) _data就是SysResult 的json字符串
傳遞給controller的參數是data.id 以restFul形式傳參
回顯就是查詢,在itemController和itemService中添加查詢代碼
修改部分
修改的前臺js代碼
$.post("/item/update",$("#itemeEditForm").serialize(), function(data){
if(data.status == 200){
$.messager.alert('提示','修改商品成功!','info',function(){
$("#itemEditWindow").window('close');
$("#itemList").datagrid("reload");
});
}
});
/item/update:請求地址
$("#itemeEditForm").serialize():參數將表單內所有標籤封裝成一個模擬的get請求參數
字符串傳遞
function(data):回調函數,data是SysResult的json轉化的js對象
商品詳情的刪除工作
Redis
2018年1月16日
15:09
情景討論
在後臺功能已經完成了,
後臺系統的高併發思路:
技術:tomcat集羣+nginx
引入20臺nginx --100萬/s;
考慮一個問題:當100萬個用同時增刪改查操作時;
系統瓶頸在哪:數據庫,尤其是查詢
Redis
分佈式,nosql,可以持久化,內存,數據庫
分佈式:數據被劃分
nosql:not only sequence query language
不僅僅支持關係型數據--結構化的數據
還支持非關係型數據--非結構化數據
可持久化+內存:啓動回覆機制
數據庫存儲;
可以分佈式的存儲大量海量的數據,存放到內存中,
可以做緩存數據庫
京淘中的緩存架構可以如何設計
緩存可以如何添加
數據庫緩存
執行的過程包括sql,組織查詢結果resultSet
根據sql可以創建緩存,存儲已經查過的resultset,節省了
資源的調度重組resultSet
持久層緩存
減少從數據庫獲取的結果轉化成對象的過程,緩存存在直接調用其中
保存的對象結果;
業務層緩存
減少調用層次
控制層緩存
較少調用層次
<問題>可不可以過多使用緩存
緩存是佔用內存空間的,過多的緩存插入,容易造成數據的冗餘
在內存不夠時,清空邏輯會交叉導致數據失效
結論緩存引入的最終目的
1 減少數據庫的訪問壓力
2 減少網絡傳輸
3 減少封裝層次
Redis這個技術就可以在京淘中實現提升性能的目的,緩存
介紹緩存
主流的緩存架構
1 ehcache (很多數據庫底層緩存使用ehcache)併發量差
2 memoryCache,10年,高併發的100萬/s; 缺點:不落地
3 Redis:持久化可以在宕機恢復後迅速解決數據丟失
<問題>:如果在緩存服務器宕機後,無法進行數據恢復/沒有解決數據重新加載
的問題,會導致“雪崩”/”緩存擊穿“
雪崩/緩存擊穿
海量用戶訪問請求湧入,一旦緩存失效(宕機數據丟失);所有的訪問
湧入數據庫;數據庫無法承受海量數據的查詢,導致數據庫服務器宕機;
重啓數據庫,請求查詢沒消失,數據庫--宕機--重啓循環,導致系統崩潰
解決雪崩:
1 緩存用不宕機;啓動集羣,永遠讓集羣中的一部分起作用
2 緩存技術必須可以恢復數據,持久化
安裝redis
2018年1月16日
15:47
1 下載安裝包解壓
使用對象存儲的源站地址獲取資源
"
創建管理目錄
[root@10-9-62-65 ~]# cd /home/
[root@10-9-62-65 home]# mkdir software
[root@10-9-62-65 home]# cd software/
[root@10-9-62-65 software]#
使用wget獲取資源
解壓
redis使用
make && make install
2 啓動redis
啓動redis的服務
#redis-server
使用redis需要啓動redis客戶端
#redis-cli
如果想在同一個操作控制檯啓動服務和客戶端
啓動客戶端時可以使用後臺運行命令
#redis-server &
停止redis服務
1 佔用控制檯的redis服務直接ctrl+c停止服務
2 在後臺運行服務的時候,登陸客戶端
shutdown;
3 檢查後臺運行的redis服務
ps -ef|grep redis;
redis-server 表示redis服務
*:表示能夠訪問當前redis服務的所有ip地址,都可以
如果列出一系列的ip地址,除這些ip意外的所有訪問redis服務的請求
都被拒絕
Redis的基礎命令
操作字符串
redis存儲數據是以key-value的形式,key-{key,value},key-list
keys:查詢當前的存儲空中的所有存在key;
127.0.0.1:6379> keys *
(empty list or set)
127.0.0.1:6379>
set [key名] [value]
設置 key-value值,value是String字符串
127.0.0.1:6379> set name xiao
OK
127.0.0.1:6379> key *
(error) ERR unknown command 'key'
127.0.0.1:6379> keys *
1) "name"
127.0.0.1:6379>
get [key名]
獲取key對應的value值
127.0.0.1:6379> keys *
1) "gender"
2) "name"
3) "age"
4) "city"
127.0.0.1:6379> get name
"xiao"
127.0.0.1:6379>
select [整數值[0-15]]
redis存在嗎默認的0-15標號的數據分褲,默認使用0號;這個功能是早期
版本冗餘的功能,現在都使用默認0號數據庫;現在java的代碼不支持分庫
127.0.0.1:6379> select 1
OK
127.0.0.1:6379[1]> keys *
(empty list or set)
127.0.0.1:6379[1]>
exists [key名]
判斷當前key是否存在;與get的卻別
redis存儲的key-value結構的字符串數據 512M,當邏輯判斷只需要返回是與
否時,get命令獲取的大字符串就佔用了資源的調用
127.0.0.1:6379> exists name
(integer) 1
127.0.0.1:6379> exists xiao
(integer) 0
127.0.0.1:6379>
del [key名]
127.0.0.1:6379> del name
(integer) 1
127.0.0.1:6379> keys *
1) "gender"
2) "num"
3) "age"
4) "city"
type [key名]
127.0.0.1:6379> set num1 100
OK
127.0.0.1:6379> type num1
string
127.0.0.1:6379>
help type/help [命令名稱]
127.0.0.1:6379> help set
SET key value [EX seconds] [PX milliseconds] [NX|XX]
summary: Set the string value of a key
since: 1.0.0
group: string
127.0.0.1:6379>
實際問題可以到官網查詢對應的命令細節
flushall 將所有的當前內存數據(0-15號庫),flush到持久化文件
127.0.0.1:6379> keys *
1) "num1"
2) "gender"
3) "num"
4) "age"
5) "city"
127.0.0.1:6379> flushall
OK
127.0.0.1:6379> keys *
(empty list or set)
flushdb flush當前redis某一個標號的庫中的內容到持久化文件
127.0.0.1:6379> keys *
1) "name"
127.0.0.1:6379> selet
(error) ERR unknown command 'selet'
127.0.0.1:6379> selet 1
(error) ERR unknown command 'selet'
127.0.0.1:6379> select 1
OK
127.0.0.1:6379[1]> set name xiao
OK
127.0.0.1:6379[1]> keys *
1) "name"
127.0.0.1:6379[1]> flushdb
OK
127.0.0.1:6379[1]> keys *
(empty list or set)
127.0.0.1:6379[1]> select 0
OK
127.0.0.1:6379> keys *
1) "name"
127.0.0.1:6379>
===============================================================================
==========================================================================
DAY06
知識回顧
2018年1月17日
8:54
1 nginx負載均衡
權重;weight,down關鍵字
session黏着,解決session共享的負載均衡計算方式
ip_hash
url_hash,以來第三方插件;
2 商品描述
大字段內容,不破壞商品表的索引,單獨使用一張表來記錄
單獨的desc表數據特別大的時候,分庫,分表保存(早期)
現在幾乎所有的可見查詢功能都使用緩存
完成商品詳情的增刪改查
改和查一體(回顯和修改)
3 Redis介紹
後臺的訪問併發量已經使用nginx+tomcat可以達到很高
程序性能未必能支持如此大的併發量請求
緩存的引入;
分佈式,nosql,可持久化,內存,緩存,數據庫
ehcache,
memoryCache
雪崩:緩存由於各種原因數據丟失,大量請求湧入數據庫,數據庫無法
承受,宕機重啓,緩存沒數據,請求未消失,數據庫繼續宕機,惡性循環
解決雪崩:沒有持久化的功能,必須保證緩存集羣永遠保持部分可使用
在緩存技術中添加持久化,在宕機後可以讀取持久化文件
恢復數據
4 安裝redis+key-value類型數據使用的部分命令
keys*;get,set,exists,flushdb,flushall,type,help,select,del
Redis基礎命令
2018年1月17日
9:28
incr decr 自增自減
127.0.0.1:6379> set n1 100
OK
127.0.0.1:6379> type n1
string
127.0.0.1:6379> incr n1
(integer) 101
127.0.0.1:6379> get n1
"101"
127.0.0.1:6379> set school bjdx
OK
127.0.0.1:6379> incr school
(error) ERR value is not an integer or out of range
127.0.0.1:6379>
incrby 數字 decrby 數字
127.0.0.1:6379> incrby n1 5
(integer) 106
127.0.0.1:6379>
append 在value後追加數據
127.0.0.1:6379> set name xiao
OK
127.0.0.1:6379> apend name laoshi
(error) ERR unknown command 'apend'
127.0.0.1:6379> append name laoshi
(integer) 10
127.0.0.1:6379> get name
"xiaolaoshi"
127.0.0.1:6379>
mset mget 獲取或者設置一批key-value對
mset k1 v1 k2 v2
mget k1 k2
127.0.0.1:6379> mset n1 100 n2 200 n3 300
OK
127.0.0.1:6379> keys *
1) "name"
2) "n3"
3) "n2"
4) "n1"
127.0.0.1:6379> mget n1 n2 n3
1) "100"
2) "200"
3) "300"
127.0.0.1:6379>
支持的語言API不支持這個命令,這種羣體操作k-v對的過程
無法進行分片和集羣計算;早期redis版本遺留功能;
expire [key] 時間數字(單位秒)
設置當前key對應的value的過期時間
ttl 查看當前key-value對的存活時間
127.0.0.1:6379> set bomb c4
OK
127.0.0.1:6379> keys *
1) "name"
2) "n1"
3) "n2"
4) "n3"
5) "bomb"
127.0.0.1:6379> expire bomb 100
(integer) 1
127.0.0.1:6379> ttl
(error) ERR wrong number of arguments for 'ttl' command
127.0.0.1:6379> ttl bomb
(integer) 86
127.0.0.1:6379> ttl bomb
(integer) 85
127.0.0.1:6379> ttl bomb
(integer) 84
127.0.0.1:6379>
第二個案例
127.0.0.1:6379> set bread binbao
OK
127.0.0.1:6379> expire bread 5
(integer) 1
127.0.0.1:6379> ttl bread
(integer) 2
127.0.0.1:6379> ttl bread
(integer) 1
127.0.0.1:6379> ttl bread
(integer) 0
127.0.0.1:6379> ttl bread
(integer) -2
127.0.0.1:6379>
127.0.0.1:6379> ttl name
(integer) -1
127.0.0.1:6379>
-2代表過期,-1代表永久
可以使用數據中的過期來做倒計時
還可以秒殺;
pexpire [key] 時間數字(毫秒)
127.0.0.1:6379> pexpire bomb 5000
(integer) 1
127.0.0.1:6379> ttl bomb
(integer) 3
127.0.0.1:6379> ttl bomb
(integer) 2
HASH+LIST
2018年1月17日
9:47
1 HASH結構
key-value字符串類型中的key本身也是key-value對兒
HSET和HGET賦值和取值
HSET key field value
HGET key field
HMSET key field value [field value…]
HMGET key field value [field value…]
HGETALL key
127.0.0.1:6379> hset user username chenchen
(integer) 1
127.0.0.1:6379> hget user username
"chenchen"
127.0.0.1:6379> hset user username chen
(integer) 0
127.0.0.1:6379> keys user
1) "user"
127.0.0.1:6379> hgetall user
1) "username"
2) "chen"
127.0.0.1:6379>
127.0.0.1:6379> hset user age 30
(integer) 1
127.0.0.1:6379> hgetall user
1) "username"
2) "chen"
3) "age"
4) "30"
127.0.0.1:6379>
HSET命令不區分插入和更新操作,當執行插入操作時HSET命令返回1,當執行更新操作時返回0。
HMSET和HMGET設置和獲取對象屬性
127.0.0.1:6379> hmset person username tony age 18
OK
127.0.0.1:6379> hmget person age username
1) "18"
2) "tony"
127.0.0.1:6379> hgetall person
1) "username"
2) "tony"
3) "age"
4) "18"
127.0.0.1:6379>
注意:上面HMGET字段順序可以自行定義
HEXISTS屬性是否存在
127.0.0.1:6379> hexists killer
(error) ERR wrong number of arguments for 'hexists' command
127.0.0.1:6379> hexists killer a
(integer) 0
127.0.0.1:6379> hexists user username
(integer) 1
127.0.0.1:6379> hexists person age
(integer) 1
127.0.0.1:6379>
HDEL刪除對象字段
127.0.0.1:6379> hdel user age
(integer) 1
127.0.0.1:6379> hgetall user
1) "username"
2) "chen"
127.0.0.1:6379> hgetall person
1) "username"
2) "tony"
3) "age"
4) "18"
127.0.0.1:6379>
只獲取字段名HKEYS或字段值HVALS
127.0.0.1:6379> hkeys person
1) "username"
2) "age"
127.0.0.1:6379> hvals person
1) "tony"
2) "18"
獲取字段數量HLEN
127.0.0.1:6379> hlen user
(integer) 1
127.0.0.1:6379> hlen person
(integer) 2
127.0.0.1:6379>
List
key-value(雙向鏈表,左-上,右-下)
查看list
redis 127.0.0.1:6379> lrange mylist3 0 -1
lrange key start length
LPUSH
在key對應list的頭部添加字符串元素
redis 127.0.0.1:6379> lpush mylist "world"
(integer) 1
redis 127.0.0.1:6379> lpush mylist "hello"
(integer) 2
redis 127.0.0.1:6379> lrange mylist 0 -1
1) "hello"
2) "world"
redis 127.0.0.1:6379>
RPUSH
在key對應list的尾部添加字符串元素
redis 127.0.0.1:6379> rpush mylist2 "hello"
(integer) 1
redis 127.0.0.1:6379> rpush mylist2 "world"
(integer) 2
redis 127.0.0.1:6379> lrange mylist2 0 -1
1) "hello"
2) "world"
redis 127.0.0.1:6379>
linsert
在key對應list的特定位置之前或之後添加字符串元素
redis 127.0.0.1:6379> rpush mylist3 "hello"
(integer) 1
redis 127.0.0.1:6379> rpush mylist3 "world"
(integer) 2
redis 127.0.0.1:6379> linsert mylist3 before "world" "there"
(integer) 3
redis 127.0.0.1:6379> lrange mylist3 0 -1
1) "hello"
2) "there"
3) "world"
redis 127.0.0.1:6379>
lset
設置list中指定下標的元素值
redis 127.0.0.1:6379> rpush mylist4 "one"
(integer) 1
redis 127.0.0.1:6379> rpush mylist4 "two"
(integer) 2
redis 127.0.0.1:6379> rpush mylist4 "three"
(integer) 3
redis 127.0.0.1:6379> lset mylist4 0 "four"
OK
redis 127.0.0.1:6379> lset mylist4 -2 "five"
OK
redis 127.0.0.1:6379> lrange mylist4 0 -1
1) "four"
2) "five"
3) "three"
redis 127.0.0.1:6379>
大於0是正數
小於0倒數
lrem
從key對應list中刪除count個和value相同的元素,count>0時,
按從頭到尾的順序刪除
redis 127.0.0.1:6379> rpush mylist5 "hello"
(integer) 1
redis 127.0.0.1:6379> rpush mylist5 "hello"
(integer) 2
redis 127.0.0.1:6379> rpush mylist5 "foo"
(integer) 3
redis 127.0.0.1:6379> rpush mylist5 "hello"
(integer) 4
redis 127.0.0.1:6379> lrem mylist5 2 "hello"
(integer) 2
redis 127.0.0.1:6379> lrange mylist5 0 -1
1) "foo"
2) "hello"
redis 127.0.0.1:6379>
count<0時,按從尾到頭的順序刪除
redis 127.0.0.1:6379> rpush mylist6 "hello"
(integer) 1
redis 127.0.0.1:6379> rpush mylist6 "hello"
(integer) 2
redis 127.0.0.1:6379> rpush mylist6 "foo"
(integer) 3
redis 127.0.0.1:6379> rpush mylist6 "hello"
(integer) 4
redis 127.0.0.1:6379> lrem mylist6 -2 "hello"
(integer) 2
redis 127.0.0.1:6379> lrange mylist6 0 -1
1) "hello"
2) "foo"
redis 127.0.0.1:6379>
count=0時,刪除全部
redis 127.0.0.1:6379> rpush mylist7 "hello"
(integer) 1
redis 127.0.0.1:6379> rpush mylist7 "hello"
(integer) 2
redis 127.0.0.1:6379> rpush mylist7 "foo"
(integer) 3
redis 127.0.0.1:6379> rpush mylist7 "hello"
(integer) 4
redis 127.0.0.1:6379> lrem mylist7 0 "hello"
(integer) 3
redis 127.0.0.1:6379> lrange mylist7 0 -1
1) "foo"
redis 127.0.0.1:6379>
ltrim
保留指定key 的值範圍內的數據
redis 127.0.0.1:6379> rpush mylist8 "one"
(integer) 1
redis 127.0.0.1:6379> rpush mylist8 "two"
(integer) 2
redis 127.0.0.1:6379> rpush mylist8 "three"
(integer) 3
redis 127.0.0.1:6379> rpush mylist8 "four"
(integer) 4
redis 127.0.0.1:6379> ltrim mylist8 1 -1
OK
redis 127.0.0.1:6379> lrange mylist8 0 -1
1) "two"
2) "three"
3) "four"
redis 127.0.0.1:6379>
lpop
從list的頭部刪除元素,並返回刪除元素
redis 127.0.0.1:6379> lrange mylist 0 -1
1) "hello"
2) "world"
redis 127.0.0.1:6379> lpop mylist
"hello"
redis 127.0.0.1:6379> lrange mylist 0 -1
1) "world"
redis 127.0.0.1:6379>
rpop
從list的尾部刪除元素,並返回刪除元素:
redis 127.0.0.1:6379> lrange mylist2 0 -1
1) "hello"
2) "world"
redis 127.0.0.1:6379> rpop mylist2
"world"
redis 127.0.0.1:6379> lrange mylist2 0 -1
1) "hello"
redis 127.0.0.1:6379>
rpoplpush
從第一個list的尾部移除元素並添加到第二個list的頭部,最後返回被移除的元素值,整個操作是原子的.如果第一個list是空或者不存在返回nil:
redis 127.0.0.1:6379> lrange mylist5 0 -1
1) "three"
2) "foo"
3) "hello"
redis 127.0.0.1:6379> lrange mylist6 0 -1
1) "hello"
2) "foo"
redis 127.0.0.1:6379> rpoplpush mylist5 mylist6
"hello"
redis 127.0.0.1:6379> lrange mylist5 0 -1
1) "three"
2) "foo"
redis 127.0.0.1:6379> lrange mylist6 0 -1
1) "hello"
2) "hello"
3) "foo"
redis 127.0.0.1:6379>
lindex
返回名稱爲key的list中index位置的元素:
redis 127.0.0.1:6379> lrange mylist5 0 -1
1) "three"
2) "foo"
redis 127.0.0.1:6379> lindex mylist5 0
"three"
redis 127.0.0.1:6379> lindex mylist5 1
"foo"
redis 127.0.0.1:6379>
llen
返回key對應list的長度:
redis 127.0.0.1:6379> llen mylist5
(integer) 2
redis 127.0.0.1:6379>
數據的分佈存儲
2018年1月17日
10:44
要完成數據的分片存儲,需要至少多個redis實例
啓動多個redis實例
前面的單個redis節點實例的啓動時默認配置
端口號6379
配置文件
/redis根目錄/redis.conf
配置文件的修改內容
p61 bind 用#註釋掉
p80 保護模式不啓動
p84 6379是默認端口(要啓動其他的redis實例需要修改端口)
p105 當客戶端空閒時間一小時,就會自動斷開連接,0秒錶示
不啓用超時配置
p128 daemonize 設置成yes讓redis服務器啓動有守護進程管理
(後臺執行)
p150 對應不同的redis實例,pid的文件名稱需要和端口同名
save 900(秒) 1(變動的數據條數)
當900以內,至少有1條數據變動,看是flush保存數據到文件
save 300 10
300秒以內至少10條數據變動,保存文件
save 60 10000
啓動第二和第三個redis實例
redis-server redis.conf(指定啓動文件)
需要第二個實例的配置文件
需要第三個實例的配置文件
拷貝redis.conf,用redis6380.conf,redis6381.conf
將拷貝的文件中只修改與端口有關內容
port
pid文件
6381的略
啓動另外兩個節點
#redis-server redis6380.conf
#redis-server redis6381.conf
#ps -ef|grep redis
指定端口登錄客戶端redis-cli -p [端口號]
#redis-cli -p 6380
#redis-cli -p 6381
6380和6381會共享6379的dump.db文件
所以不同的節點實例在同一個機器上運行時,可以修改dump.db
指定端口文件;
三個節點,怎麼分佈式保存數據?
數據來源:代碼的邏輯執行
如何使用代碼來操作redis執行分佈式的數據存儲過程?
引出了Jedis客戶端
Jedis
2018年1月17日
11:36
測試jedis控制redis的命令功能
需要導入jedis包
自定義分片
準備數據:
葵花寶典A,B,C三部分數據
將三部分數據分別存儲到redis 6379 6380 6381
哈希取餘
利用hash的散列特性,可以處理海量非結構化數據的散列分佈的分片計算
代碼
jedis分片
沒有在分片時使用哈希取餘,hash一致性
經過代碼發現,一般的自定義分片邏輯計算無法做到散列
不散列無法均衡
jedis池
HASH一致性
2018年1月17日
15:27
作爲散列算法
考慮哈西取餘的問題
1 容易產生大規模的數據傾斜(散列必定傾斜)
hash一致性一定程度的解決了數據傾斜;
2 哈希取餘算法,導致數據遷移量過大
當redis集羣數量進行增加減少的時候,哈希取餘算法中的n變化了
由於n的變化,數據命中變化量非常大,需要遷移的數據量非常大,
jedis中引入另外一種hash散列算法--hash一致性
1997麻省理工學生髮明;引入一個2^32-1(43億)整數環,
把節點使用ip+端口做哈希散列計算,得到43億中一個值,投射到環中
將所有的數據key進行哈希散列計算,得到43億中的一個
node1,2,3個節點啓動着redis
數據分別是key1,2,3,4
根據hash散列算法都投射到一個整數上
順時針尋找最近節點的映射規則,將key值進行存放
key1,2存儲在node1
key3存儲在node2
key4存儲在node3
當增加刪除節點時,遷移量有何變化?
增加node4,根據散列得到43億中一個整數,投射到環上
根據順時針尋找最近節點存儲的原則,只需要遷移key4
而且可以判斷,原節點數量越多,遷移量越小
節點刪除,將node2刪除,遷移key3
解決數據平衡性
單獨的使用節點的ip+端口做映射,畢竟節點數量是有限的
有可能在映射時的各自分佈位置並不平均,導致數據偏移量非常大
解決數據的平衡性引入虛擬節點
node1的ip是192.168.40.156
node2的ip是192.168.40.157
各自引入2個虛擬節點(虛擬節點的數量是非常大的)
node1-1=hash(192.168.40.156#1)
node1-2=hash(192.168.40.156#2)
node2-1=hash(192.168.40.157#1)
node2-2=hash(192.168.40.157#2)
每一個虛擬節點在哈希環上也會接收順時針尋找最近節點的key們
通過增加節點數量(虛擬的),完成數據的映射平衡
凡是投影到node1-1,node1-2的key,都會中真實存儲在node1中
所以虛擬節點越多平衡性越好
京淘的緩存引入
2018年1月17日
16:24
根據在模擬緩存的邏輯,思考後臺什麼位置可以做緩存?
商品分類樹(緩存版本1)
商品列表(不好做,有分頁參數)
商品新增,修改,刪除
商品詳情新增,修改,刪除
補充內容
2018年1月17日
10:19
HASH取餘數據分片
原子級操作
一系列操作如果稱之爲原子級,不可分割,一旦分隔開
系列操作不成功
當天問題
2018年1月17日
16:51
版本1的緩存引入京淘時
商品分類樹查詢
Name [spring.liveBeansView.mbeanDomain] is not bound in this Context. Unable to find [spring.liveBeansView.mbeanDomain].. Returning null.
原因,從mysql查詢的數據沒有text,state
返回json需要text和state,ItemCat類中的兩個get方法,導致MAPPER轉化字符串和對象時的錯誤
在ItemCat中添加一個註解,讓MAPPER轉化時忽略這兩個屬性