非關系型數據庫分類:
分類 |
典型代表 |
典型應用場景 |
數據類型 |
優點 |
缺點 |
鍵值 (key-value) |
Tokyo Cabinet/Tyrant, Redis, Voldemort, Oracle BDB |
內容緩存,主要用於處理大量數據的高訪問負載,也用於一些日志系統等等。 |
Key 指向 Value 的鍵值對,通常用hash table來實現 |
查找速度快 |
數據無結構化,通常只被當作字符串或者二進制數據 |
列存儲數據庫 |
Cassandra, HBase, Riak |
分布式的文件系統 |
以列簇式存儲,將同一列數據存在一起 |
查找速度快,可擴展性強,更容易進行分布式擴展 |
功能相對局限 |
文檔型數據庫 |
CouchDB, MongoDB |
Web應用(與Key-Value類似,Value是結構化的,不同的是數據庫能夠了解Value的內容) |
Key-Value對應的鍵值對,Value為結構化數據 |
數據結構要求不嚴格,表結構可變,不需要像關系型數據庫一樣需要預先定義表結構 |
查詢性能不高,而且缺乏統一的查詢語法。 |
圖形(Graph)數據庫 |
Neo4J, InfoGrid, Infinite Graph |
社交網絡,推薦系統等。專注於構建關系圖譜 |
圖結構 |
利用圖結構相關算法。比如最短路徑尋址,N度關系查找等 |
很多時候需要對整個圖做計算才能得出需要的信息,而且這種結構不太好做分布式的集群方案。 |
1.Redis介紹
Redis: remote dictionary service
Redis 特點
一、Redis數據庫完全在內存中,使用磁盤僅用於持久性。
二、相比許多鍵值數據存儲,Redis擁有一套較為豐富的數據類型。
三、Redis可以將數據復制到任意數量的從服務器。
Redis 優勢
1、異常快速:Redis的速度非常快,每秒能執行約11萬集合,每秒約81000+條記錄。
2、支持豐富的數據類型:Redis支持Redis支持五種數據類型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)。這使得它非常容易解決各種各樣的問題,因為我們知道哪些問題是可以處理通過它的數據類型更好。
3、操作都是原子性:所有Redis操作是原子的,這保證了如果兩個客戶端同時訪問的Redis服務器將獲得更新后的值。
4、多功能實用工具:Redis是一個多實用的工具,可以在多個用例如緩存,消息,隊列使用(Redis原生支持發布/訂閱),任何短暫的數據,應用程序,如Web應用程序會話,網頁命中計數等。
-----
2.redis 單機版安裝
教程使用redis3.0版本。3.0版本主要增加了redis集群功能。
安裝的前提條件:
需要安裝gcc:yum install gcc-c++ -y
1、下載redis的源碼包。 https://redis.io/download
2、把源碼包上傳到linux服務器
3、解壓源碼包
tar -zxvf redis-3.0.0.tar.gz
在/root/myapps/redis-3.0.0/中執行下面的語句 cd redis -3.0.0
4、make或者make MALLOC=libc(強制使用libc的內容來編譯)
5、make install PREFIX=/usr/local/redis 將redis安裝到/usr/local/redis目錄中
安裝完成之后,可以在/usr/local/redis/bin目錄下看到
redis-benchmark redis性能測試工具
redis-check-aof AOF文件修復工具
redis-check-rdb RDB文件檢查工具
redis-cli Redis命令行客戶端
redis-sentinel Redis軟連接指向redis-server
redis-server Redis服務器
-------------------
3. 啟動Redis的兩種方式
3.1 前置啟動
/usr/local/redis/bin/redis-server
在redis的安裝目錄的bin目錄,./redis-server
默認是前端啟動模式,端口是6379
ctrl+c停止前端模式的redis
3.2 后置啟動(守護進程)
從redis的源碼目錄中復制redis.conf到redis的安裝目錄。/usr/local/redis/bin cp redis.conf /usr/local/redis/bin
安裝vim yum install -y vim
修改配置文件 vim redis.conf
命令模式下搜索 /daemonize 改成yes
[root@bogon bin]# ./redis-server redis.conf
ps aux | grep redis 查看是否有有一個進程,它的名字包含了redis這個字符串
./redis-cli shutdown關閉redis服務器
指定IP地址和端口號的關閉redis服務器命令
./redis-cli -h 192.168.75.133 -p 1234 shutdown
./redis-cli -h 192.168.10.11 -p 6379 shutdown
./redis-cli空格-h 空格192.168.75.133(IP地址)空格 -p 空格1234(端口號)空格 shutdown
kill -9 <redis進程編號> 可以關閉服務器進程
4. Redis 配置文件介紹(Redis.conf)
4.1 端口號
port 6379
6379在是手機按鍵上MERZ對應的號碼,而MERZ取自意大利歌女Alessia Merz的名字。MERZ長期以來被Redis作者antirez及其朋友當作愚蠢的代名詞。后來Redis作者在開發Redis時就選用了這個端口。
4.2 數據庫數量
databases 16
這里的數據庫類似於MySQL的數據庫,在一個MySQL的實例中可以有多個數據庫,不同的應用使用不同的數據庫,同樣在一個redis實例中也可以有多個數據庫。
可以使用 select <數據庫ID>來選擇使用哪個數據庫。數據庫0 <= ID <= datebases - 1
4.3 持久化方式
4.3.1 rdb
Redis的所有數據都是保存在內存中,然后不定期的通過異步方式保存到磁盤上(這稱為“半持久化模式”)
快照是默認的持久化方式。這種方式是就是將內存中數據以快照的方式寫入到二進制文件中,默認的文件名為dump.rdb。可以通過配置設置自動做快照持久化的方式。我們可以配置redis在n秒內如果超過m個key被修改就自動做快照,下面是默認的快照保存配置
save 900 1 #900秒內如果超過1個key被修改,則發起快照保存
save 300 10 #300秒內容如超過10個key被修改,則發起快照保存
save 60 10000
4.3.2 aof
也可以把每一次數據變化都寫入到一個append only file(aof)里面(這稱為“全持久化模式”)。
aof 比快照方式有更好的持久化性,是由於在使用aof持久化方式時,redis會將每一個收到的寫命令都通過write函數追加到文件中(默認是 appendonly.aof)。當redis重啟時會通過重新執行文件中保存的寫命令來在內存中重建整個數據庫的內容。當然由於os會在內核中緩存 write做的修改,所以可能不是立即寫到磁盤上。這樣aof方式的持久化也還是有可能會丟失部分修改。不過我們可以通過配置文件告訴redis我們想要通過fsync函數強制os寫入到磁盤的時機。有三種方式如下(默認是:每秒fsync一次)
appendonly yes //啟用aof持久化方式
# appendfsync always //每次收到寫命令就立即強制寫入磁盤,最慢的,但是保證完全的持久化,不推薦使用
appendfsync everysec //每秒鍾強制寫入磁盤一次,在性能和持久化方面做了很好的折中,推薦
# appendfsync no //完全依賴os,性能最好,持久化沒保證
4.4 密碼驗證
Redis默認配置是不需要密碼認證的,可以啟用Redis的認證密碼,增加Redis服務器的安全性。
1、在redis.conf下找到:
取消注釋,foobared修改為要使用的密碼。
2、重啟redis服務器
# ./redis-cli shutdown 停止
# ./redis-server redis.conf 啟動
3、客戶端使用密碼登錄:
./redis-cli -a 123456
# ./redis-cli -h 127.0.0.1 -p 6379 -a myPassword
或者
# ./redis-cli -h 127.0.0.1 -p 6379
127.0.0.1:6379> auth myPassword
OK
4、如果Redis服務器,使用了集群。除了在master中配置密碼外,也需要在slave中進行相應配置。在slave的配置文件中找到如下行,去掉注釋並修改與master相同的密碼即可:
5. Redis 常見用命令
ping 測試redis是否鏈接
echo hello 測試redis是否鏈接
select 0 select 15 選擇數據庫(0-15)
quit 退出連接
dbsize 返回當前數據庫中的key的數目
5.1 Key 相關
set key1 100
get key1
del key1
keys * 查看數據庫中所有的鍵
exists key1 表示存在key1
expire key1 20 指定鍵的過期時間 20s,對哈希類型不起作用!
keys k* 查找所有以k開頭的鍵
ttl key 獲取鍵到期的剩余時間,單位是秒 expire key2 10 //設置過期時間10s persist key2 //去除key2的過期時間 ttl key2 //查看key2的剩余時間
5.2 Strings - 字符串
Redis的字符串是字節序列。在Redis中字符串是二進制安全的,這意味着他們有一個已知的長度,是沒有任何特殊字符終止決定的,所以可以存儲任何東西,最大長度可達512兆。
SET key value 設置指定 key 的值 set a 10
GET key 獲取指定 key 的值 get a
MGET key1 [key2..] 獲取所有(一個或多個)給定 key 的值 mget a b
SETEX key seconds value (expire) 將值 value 關聯到 key ,並將 key 的過期時間設為 seconds (以秒為單位)。 set world 10 “new world” get world
MSET key value [key value ...] 同時設置一個或多個 key-value 對。mset a a1 b b1 c c1
INCR key 原子操作 將 key 中儲存的數字值增一
127.0.0.1:6379> set num 0
OK
127.0.0.1:6379> incr num
(integer) 1
127.0.0.1:6379> incr num
(integer) 2
127.0.0.1:6379> incr num
(integer) 3
INCRBY key increment(整型) 將 key 所儲存的值加上給定的增量值(increment) incrby num 2
INCRBYFLOAT key increment 將 key 所儲存的值加上給定的浮點增量值(increment)
DECR key(整型數字) 將 key 中儲存的數字值減一
DECRBY key decrement(整型數字) key 所儲存的值減去給定的減量值(decrement)
APPEND key value 如果 key 已經存在並且是一個字符串, APPEND 命令將 value 追加到 key 原來的值的末尾
127.0.0.1:6379> get a
"b"
127.0.0.1:6379> append a 1234
(integer) 5
127.0.0.1:6379> get a
"b1234"
127.0.0.1:6379>
5.3 Hashes - 哈希值
Redis的哈希鍵值對的集合。 Redis的哈希值是字符串字段和字符串值之間的映射,所以它們被用來表示對象
每個哈希可存儲多達2³² - 1個 字段-值對(超過40+億)。
HMSET key field1 value1 [field2 value2 ] 同時將多個 field-value (域-值)對設置到哈希表 key 中 hmset user01 userId 1 username zhangsan password 123456 desc "one good man"
insert into tb_user (userId,username, password, desc) values (1, zhangsan, 123456 “one good man”);
HGET key field 獲取存儲在哈希表中指定字段的值 hget user01 username
Select username from tb_user where user_id=1;
HGETALL key 獲取在哈希表中指定 key 的所有字段和值 hgetall user01
Select * from tb_user where user_id=1;
HINCRBY key field increment 為哈希表 key 中的指定字段的整數值加上增量 increment hincrby user01 userId 3
HKEYS key 獲取哈希表中指定key的所有字段 hkeys user01
HMGET key field1 [field2] 獲取所有給定字段的值 hmget user01 userId username
select userId, username from tb_user where userkey=xxx
HDEL key field1 [field2] 刪除一個或多個哈希表字段 hdel user01 username password
HSET key field value 將哈希表 key 中的字段 field 的值設為 value 。如果哈希表中有這個字段,則設置該字段的值,如果沒有,則在哈希表中添加一個字段 hset user01 desc "this is zhangsan"
Update tb_user set a = avalue, b=bvalue where userID=xxx
HVALS key 獲取哈希表中所有值 hvals user01
Select * from tb_user where user_id = xxx
注意:hash沒有設置過期時間的命令
命令參考:http://doc.redisfans.com/
7.redis集群
7.1 搭建偽集群即可入
搭建集群需要使用到官方提供的ruby腳本。
需要安裝ruby的環境。
安裝ruby
yum -y install ruby -y
yum -y install rubygems -y
redis集群管理工具redis-trib.rb,此文件在redis源碼的src目錄中
cp redis-trib.rb /usr/local/redis/
腳本需要的ruby包:下載地址:https://rubygems.org/gems/redis/versions/3.0.0 下載 redis-3.0.0.gem 上傳服務器
安裝ruby的包 gem install redis-3.0.0.gem
集群的搭建
第一步:創建6個redis實例,端口號從7001~7006,實際上就是復制單機版(已安裝的!)六份到/usr/local/redis/redisCluster目錄中。
mkdir redisCluster
cp bin -r redisCluster/redis1
cd redis1
rm -f dump.rdb
cp redis1/ redis2 -r
cp redis1/ redis3 -r 等
第二步:修改redis的配置文件
1、修改端口號
vim redis1/redis.conf
/port i 7001 :wq
vim redis2/redis.conf
/port i 7002 :wq 等 。。。
2、打開cluster-enable前面的注釋。
vim redis1/redis.conf
/cluster i 刪掉#注釋
vim redis2/redis.conf
/cluster- i 刪掉#注釋 等 。。。
3、設置redis綁定的IP地址:
ifconfig
vim redis1/redis.conf /bind i
全部都新增 bind 192.168.10.100
第三步:把創建集群的ruby腳本redis-trib.rb復制到/usr/local/redis/redis-cluster目錄下。
mv redis-trib.rb redisCluster/
一定得刪除每個redis中的dump.rdb文件!
第四步:啟動6個redis實例 寫啟動腳本 權限 chmod +x start-redises.sh
vim start-redisCluster.sh 多行復制粘貼 2yy p
#!/bin/bash
cd /usr/local/redis/redisCluster/redis1
./redis-server redis.conf
cd /usr/local/redis/redisCluster/redis2
./redis-server redis.conf
cd /usr/local/redis/redisCluster/redis3
./redis-server redis.conf
cd /usr/local/redis/redisCluster/redis4
./redis-server redis.conf
cd /usr/local/redis/redisCluster/redis5
./redis-server redis.conf
cd /usr/local/redis/redisCluster/redis6
./redis-server redis.conf
關閉腳本
#!/bin/bash
/usr/local/redis/bin/redis-cli -h 192.168.10.100 -p 7001 shutdown/usr/local/redis/bin/redis-cli -h 192.168.10.100 -p 7002 shutdown /usr/local/redis/bin/redis-cli -h 192.168.10.100 -p 7003 shutdown /usr/local/redis/bin/redis-cli -h 192.168.10.100 -p 7004 shutdown /usr/local/redis/bin/redis-cli -h 192.168.10.100 -p 7005 shutdown
/usr/local/redis/bin/redis-cli -h 192.168.10.100 -p 7006 shutdown
給start-redisCluster.sh 執行權限
查看權限 ll
chmod +x start-redisCluster.sh
驗證 ll
啟動redis集群 ./start-redisCluster.sh
查看redis進程 ps aux | grep redis
第五步:創建集群 三主三從
./redis-trib.rb create --replicas 1 192.168.10.100:7001 192.168.10.100:7002 192.168.10.100:7003 192.168.10.100:7004 192.168.10.100:7005 192.168.10.100:7006
記得如果哪個redis有密碼(redis.conf)記得刪除 否則無法連接
>>> Performing hash slots allocation on 6 nodes...
Using 3 masters:
192.168.10.100:7001
192.168.10.100:7002
192.168.10.100:7003
Adding replica 192.168.10.100:7004 to 192.168.10.100:7001
Adding replica 192.168.10.100:7005 to 192.168.10.100:7002
Adding replica 192.168.10.100:7006 to 192.168.10.100:7003
M: b550aea51e29ac3569c846907e14cfbfc8885d4a 192.168.10.100:7001
slots:0-5460 (5461 slots) master
M: a36ca3f9388bc8a04805874a58933f904a2c050b 192.168.10.100:7002
slots:5461-10922 (5462 slots) master
M: 9ef8c5ebf7837b2427f3634cc21a6df8a351ebcd 192.168.10.100:7003
slots:10923-16383 (5461 slots) master
S: 4250f6d581683a3d23029f6d423cae6e375738b9 192.168.10.100:7004
replicates b550aea51e29ac3569c846907e14cfbfc8885d4a
S: 56d0617d19b2db0feee0e46958fc871481152c46 192.168.10.100:7005
replicates a36ca3f9388bc8a04805874a58933f904a2c050b
S: cae11b50524fc71318c5073090151ed426a4ccad 192.168.10.100:7006
replicates 9ef8c5ebf7837b2427f3634cc21a6df8a351ebcd
Can I set the above configuration? (type 'yes' to accept): yes
...
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
集群搭建成功!
測試
redis1/redis-cli -p 7001 -h 192.168.10.100
exit
redis1/redis-cli -p 7001 -h 192.168.10.100 -c 以集群登錄
客戶端連接 防火牆要放開 vim /etc/sysconfig/iptables 復制粘貼 yy p 刪除一行 dd service iptables restart
8. 集群原理
1 slot 槽
redis-cluster把所有的物理節點(redis的master服務器)映射到[0-16383]slot上,cluster 負責維護node<->slot<->value
Redis 集群中內置了 16384 個哈希槽(hash slot),當需要在 Redis 集群中放置一個 key-value 時,redis 先對 key 使用 crc16 算法算出一個結果,然后把結果對 16384 求余數,這樣每個 key 都會對應一個編號在 0-16383 之間的哈希槽,redis 會根據節點數量大致均等的將哈希槽映射到不同的節點
redis容錯:(主從容錯)
集群一定是奇數台redis主機,偶數台無法做投票選舉。
(1)選舉過程是集群中所有master參與,如果半數以上master節點與故障節點通信超時 (cluster-node-timeout),認為該節點故障,自動觸發故障轉移操作.
(2):什么時候整個集群不可用(cluster_state:fail)?
a:如果集群任意master掛掉,且當前master沒有slave,集群進入fail狀態,也可以理解成集群的slot映射[0-16383]不完整時進入fail狀態.
b:如果集群超過半數以上master掛掉,無論是否有slave,集群進入fail狀態.