接下來學習redis多實例的部署、數據分片,以及jedis API的使用。
redis多實例部署
一般單個redis的進程是不能滿足實際需求的,需要在單台服務器上部署多個redis進程,充分發揮cpu的效能,多台服務器上的redis進程將組成龐大的集群,多的一般部署達到數千個redis進程。
暫時不考慮高可用的情況,下面在一台centos6.5上部署三個redis實例,要想實現部署需要修改redis.conf文件,需要修改服務端口號、日志文件編號、rdb文件編號等,下面邊查看常用配置邊修改。
(1)units單位,定義了基本的度量單位,不區分大小寫。
8 # Note on units: when memory size is needed, it is possible to specify 9 # it in the usual form of 1k 5GB 4M and so forth: 10 # 11 # 1k => 1000 bytes 12 # 1kb => 1024 bytes 13 # 1m => 1000000 bytes 14 # 1mb => 1024*1024 bytes 15 # 1g => 1000000000 bytes 16 # 1gb => 1024*1024*1024 bytes 17 # 18 # units are case insensitive so 1GB 1Gb 1gB are all the same.
(2)bind設置,如果要讓客戶端都可以連接到redis服務,就不需要設置綁定的ip,如果客戶端只能連上某個或某幾個redis服務,bind后需綁定具體的服務ip,如果bind 127.0.0.1,代表只能通過127.0.0.1來訪問redis服務,這樣只能在提供redis服務的當台機器上訪問,其他客戶端無法訪問,這里先不bind ip。
40 # By default, if no "bind" configuration directive is specified, Redis listens 41 # for connections from all the network interfaces available on the server. 42 # It is possible to listen to just one or multiple selected interfaces using 43 # the "bind" configuration directive, followed by one or more IP addresses. 44 # 45 # Examples: 46 # 47 # bind 192.168.1.100 10.0.0.1 48 # bind 127.0.0.1 ::1
58 # IF YOU ARE SURE YOU WANT YOUR INSTANCE TO LISTEN TO ALL THE INTERFACES
59 # JUST COMMENT THE FOLLOWING LINE.
60 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
61 # bind 127.0.0.1
(3)protected-mode默認是開啟的,這樣就只能本機訪問redis,如果想讓其他客戶端免密也能訪問到當前redis服務,就需要設置為no。如果設置為no,配置文件中建議使用bind綁定ip地址,並且客戶端需提供密碼才能訪問redis。
76 # By default protected mode is enabled. You should disable it only if 77 # you are sure you want clients from other hosts to connect to Redis 78 # even if no authentication is configured, nor a specific set of interfaces 79 # are explicitly listed using the "bind" directive. 80 protected-mode no
可以測試使用requirepass 123456來設置密碼,然后redis-cli登錄后嘗試操作redis,發現提示權限不足,需要使用auth 密碼命令來獲取權限,獲取權限后再查看發現可以執行命令,可以看出保護模式關,密碼為123456。
# config get 屬性名 來獲取配置文件內容,發現還是未修改的值
127.0.0.1:6379> config get protected-mode 1) "protected-mode" 2) "yes" 127.0.0.1:6379> shutdown not connected> quit You have new mail in /var/spool/mail/root [root@node01 ~]# redis-cli
# redis-server redis.conf 加載修改后配置文件啟動redis后,使用config get命令會提示權限不足 127.0.0.1:6379> config get protected-mode (error) NOAUTH Authentication required.
# auth 密碼 獲取權限 127.0.0.1:6379> auth 123456 OK
# 保護模式為關 127.0.0.1:6379> config get protected-mode 1) "protected-mode" 2) "no"
# 密碼為123456 127.0.0.1:6379> config get requirepass 1) "requirepass" 2) "123456"
這里不設置密碼,並且保護模式關。
(4)port 端口號,redis為外提供服務的端口號,默認為6379,如果配置多個實例,需要修改端口號,本次3台端口號分別為6379 6380 6381,此外其他需要區分的文件也使用端口號點綴,如每個redis服務的日志文件,以及rdb持久化文件,還有/var/run/redis_xxxx.pid文件。
# Accept connections on the specified port, default is 6379 (IANA #815344). # If port 0 is specified Redis will not listen on a TCP socket. port 6379
(5)timeout 0,如果設置為0,代表客戶端不主動斷開連接就一直會連接,如果設置了N秒,就會在N秒空閑后斷開與redis服務的連接,這里設置為0,節約資源。
106 # Close the connection after a client is idle for N seconds (0 to disable) 107 timeout 0
(6)daemonize默認設置為no,代表啟動redis會在前台啟動,如果設置為yes就默認在后台啟動,這里設置為yes。
128 # By default Redis does not run as a daemon. Use 'yes' if you need it. 129 # Note that Redis will write a pid file in /var/run/redis.pid when daemonized. 130 daemonize yes
(7)不同的redis進程,會與不同的pid號,這個pid號就保存在這個文件里,不同的redis服務,需要點綴端口號,其他兩台設置為redis_6380.pid和redis_6381.pid。
150 # Creating a pid file is best effort: if Redis is not able to create it 151 # nothing bad happens, the server will start and run normally. 152 pidfile /var/run/redis_6379.pid
查看一下,當前pid文件里服務進程號為1930,使用ps -ef|grep redis命令查看當前服務進程號也為1930,兩者一致。
[root@node01 ~]# cat /var/run/redis_6379.pid 1930 [root@node01 ~]# ps -ef|grep redis root 1930 1424 0 19:51 pts/0 00:00:02 redis-server *:6379 root 1934 1477 0 19:51 pts/1 00:00:00 redis-cli root 2084 1524 0 20:01 pts/2 00:00:00 vim redis.conf root 2508 2477 0 20:14 pts/3 00:00:00 grep redis
(8)logfile指定日志文件名,可以點綴上端口號。日志文件為redis在運行時的記錄,內容和前台運行輸出的內容一致,如果設置為空字符串,就將日志保存到/dev/null,代表日志文件進入''黑洞'',即不保存。
162 # Specify the log file name. Also the empty string can be used to force 163 # Redis to log on the standard output. Note that if you use standard 164 # output for logging but daemonize, logs will be sent to /dev/null 165 logfile "redis6379.log"
(9)rdb持久化策略,即自動save保存數據到磁盤的頻率,數據變動頻率越快保存次數越多,測試部署按照默認值來就行,不修改。
191 # In the example below the behaviour will be to save: 192 # after 900 sec (15 min) if at least 1 key changed 193 # after 300 sec (5 min) if at least 10 keys changed 194 # after 60 sec if at least 10000 keys changed 195 # 196 # Note: you can disable saving completely by commenting out all "save" lines. 197 # 198 # It is also possible to remove all the previously configured save 199 # points by adding a save directive with a single empty string argument 200 # like in the following example: 201 # 202 # save "" 203 204 save 900 1 #900秒至少變動1次數據,調用save 205 save 300 10 #300秒至少變動10次數據,調用save 206 save 60 10000 #60秒至少變動10000次數據,調用save
(10)dbfilename指定rdb持久化文件名,需要點綴上端口號,不同的redis服務使用不同的文件名,可以避免redis數據混亂。
238 # The filename where to dump the DB 239 dbfilename dump6379.rdb
注意需要准備三個redis.conf文件,公共配置修改成上面一樣,其他如端口號、日志文件名和rdb持久化文件名需要個性化修改,即使用端口號來區分。這里修改完redis.conf文件默認為6379端口號的,其他兩台在此基礎上vim命令行模式下使用:%s/6379/6380或:%s/6379/6381來批量修改個性化配置,其他公用的一樣即可。
(11)修改完后,使用'redis-server redis.conf配置文件'命令來加載配置文件啟動服務,三台啟動后,使用ps -ef|grep redis來查看是否都正常啟動。
[root@node01 /home/software/redis-3.2.11]# redis-server redis6379.conf [root@node01 /home/software/redis-3.2.11]# redis-server redis6380.conf [root@node01 /home/software/redis-3.2.11]# redis-server redis6381.conf
# 三台均啟動,對應不同的端口號 [root@node01 /home/software/redis-3.2.11]# ps -ef|grep redis root 2912 1 0 20:47 ? 00:00:00 redis-server *:6379 root 2916 1 0 20:47 ? 00:00:00 redis-server *:6380 root 2920 1 0 20:47 ? 00:00:00 redis-server *:6381 root 2924 1424 0 20:47 pts/0 00:00:00 grep redis
以上,就完成了多個redis實例的部署,實現了分布式,接下來客戶端連接如果想具體連接哪台就-p指定端口號即可。
[root@node01 ~]# redis-cli -p 6380 127.0.0.1:6380> keys * (empty list or set) 127.0.0.1:6380> quit You have new mail in /var/spool/mail/root [root@node01 ~]# redis-cli -p 6381 127.0.0.1:6381> keys * (empty list or set) 127.0.0.1:6381> quit [root@node01 ~]# redis-cli -p 6379 127.0.0.1:6379> get name (nil)
數據分片
上面部署redis多實例后,實現了分布式,接下來就產生了數據分片的問題。所謂分片,就是指海量的key-value要存入redis分布式集群,由於單個節點無法承受這么大的並發量,不能將數據整體存到一個redis節點里,而是根據一定的計算規則,分攤到各個redis里的數據。其中規則的選擇可以對具有業務意義的key的值使用hash取余,類似MapReduce里的map階段的計算分區,即(key.hashCode()&Integer.MAX_VALUE)%3來計算分區編號[0,1,2],這樣根據具體的數字編號,將key-value落到相應的redis節點。
上面(key.hashCode()&Integer.MAX_VALUE)%3里的計算,對應的意思如下:
(1)key.hashCode(),key如果是字符串,代表將字符串數據區間映射到整數區間的值,是一個可正可負的整數,如果key值不變,hashcode的結果就不變。
(2)Integer.MAX_VALUE,為整形最大值,換算成二進制就是31位的1,即0111 1111 1111 1111 1111 1111 1111 1111。
(3)&就是與運算,hashcode計算結果進行與運算后就截取其二進制數的后31位,即31位保真運算,結果為正整數。
jedis的使用
創建jedis實例對象后,就相當如創建了一個可以連接redis-server的客戶端實例,通過它的API,可以實現類似命令行的操作,而且它API的名字和命令非常的類似,可以說是見名知意。
(1)如果是maven工程,需在pom文件需要導入redis的依賴
<!--springboot添加redis依賴--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-redis</artifactId> </dependency>
(2)寫一個測試類,使用jedis實例來進行五種value類型的操作,需要在測試之前先service iptables stop命令關閉centos6.5的防火牆,要不然報錯'連接拒絕'。
package com.boe; import org.junit.Test; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.Tuple; import java.util.List; import java.util.Set; import java.util.UUID; /** * 測試使用redis */ public class JedisClient { /* * 1 創建jedis連接對象 * 2 選擇一個服務端進行連接,需要提供ip和端口號 * 3 如果服務端設置了密碼,還通過密碼獲取權限,獲取到權限后就可以使用jedis的api,來發送底層命令 */ @Test public void test01(){ String host="192.168.200.140";//redis server ip int port=6380; Jedis jedis=new Jedis(host,port); //發送命令 //string類型 System.out.println("-------string類型操作-------"); String s = jedis.set("name", "messi"); System.out.println(s); String name = jedis.get("name"); System.out.println(name); Long setnx = jedis.setnx("name", "messi"); System.out.println(setnx); //hash類型 System.out.println("-------hash類型操作-------"); Long hset = jedis.hset("user", "name", "clyang"); System.out.println(hset); String hget = jedis.hget("user", "name"); System.out.println(hget); //list類型 System.out.println("-------list類型操作-------"); Long list = jedis.lpush("list", "100", "200", "300"); System.out.println(list); List<String> lrange = jedis.lrange("list", 0, -1); System.out.println(lrange.toString()); //set類型 System.out.println("-------set類型操作-------"); Long sadd = jedis.sadd("likes", "football", "basketball", "waterball"); System.out.println(sadd); Boolean sismember = jedis.sismember("likes", "football"); System.out.println(sismember); //zset類型 System.out.println("-------zset類型操作-------"); jedis.zadd("movie",100,"hero"); jedis.zadd("movie",40,"king"); jedis.zadd("movie",90,"queue"); //獲取zset Long count = jedis.zcard("movie"); System.out.println(count); } }
運行后控制台輸出,發現正確的執行了命令。
redis查看6380端口的數據,ok。
192.168.200.140:6380> keys * 1) "name" 2) "list" 3) "likes" 4) "user" 5) "movie"
(3)上面分片有用到哈希取余,代碼中也可以實現,並且還可實現權重,具體參考代碼。
//測試hash取余算法 @Test public void test02(){ Jedis jedis1=new Jedis("192.168.200.140",6379); Jedis jedis2=new Jedis("192.168.200.140",6380); Jedis jedis3=new Jedis("192.168.200.140",6381); for (int i = 0; i < 100; i++) { //模擬key-value String key=UUID.randomUUID().toString(); String value=""; //hash取余的公式 //hashCode(),字符串數據區間映射到正數區間的值,結果可正可負 //&上Integer.MAX_VALUE就是保真運算,變成一個31位的正數,效率比取絕對值計算高 //(key.hashCode()&Integer.MAX_VALUE)%3; int result=(key.hashCode()&Integer.MAX_VALUE)%3; if(result==0) jedis1.set(key,value); if(result==1) jedis2.set(key,value); if(result==2) jedis3.set(key,value); //下面的方法可以實現權重 //int result1=(key.hashCode()&Integer.MAX_VALUE)%6; //if(result1==(0|1|2)) jedis1.set(key,value); //if(result1==(3|4)) jedis2.set(key,value); //if(result1==5) jedis3.set(key,value); } }
執行成功后,可以去redis登錄不同端口的服務,查看數據,發現大體上實現了三個redis節點1:1:1的分配,不過有個節點數據量會多一點,這就是數據的偏移,后面大數據里也會有這個概念,先記錄一下。
keys * 查看三個redis節點的數據情況

[root@node01 ~]# redis-cli -h 192.168.200.140 -p 6379 192.168.200.140:6379> keys * 1) "591d29e7-b4a0-4a0a-9659-698c05e9ff82" 2) "1a15811b-0b15-404c-beb1-3dbb745bd1dd" 3) "5db35091-5272-450c-b961-6a9c800d5643" 4) "8bf10dc7-dd56-4e91-9d50-57a041ff0d0c" 5) "e0f49161-eeb5-4b4e-9077-c8912356e758" 6) "e9393c5b-3f71-4d86-af1f-b42d6b5be8db" 7) "69fabfab-3ebc-44f5-bcaf-ebe8887c6fd1" 8) "63985acf-059c-4da9-8ed8-5db5980b5f83" 9) "04cd163b-52c5-4d17-bb95-ca99fb967603" 10) "ee4db2f6-c6bd-4d2a-a322-947112e858eb" 11) "e036856a-31e1-438a-9398-255388861025" 12) "27bfa164-1cdf-4404-82ce-026a9dbb0baa" 13) "db1f15dd-0b61-43d2-9cf2-3cb3059f16d7" 14) "7126f3b3-eb66-43be-96ac-dcc7a57ef717" 15) "b3363d55-d66a-4ae9-a753-186ac5673b67" 16) "2254689c-ede6-4108-8fc8-8d4d9bce5605" 17) "836e52cb-2c73-4017-b4bc-7ea6022d4381" 18) "18ad35e2-c6f7-42b8-8f26-6e24f4e3147f" 19) "12662f06-693f-4790-95cd-0ae7a55ba68b" 20) "c2e7ac34-6f85-48df-9fb8-a23ada69678a" 21) "93b95368-94df-431d-9145-493db6e9c5fc" 22) "a4b63d27-7e70-4ba2-9b76-9bd9b7f1a254" 23) "e9f264b7-0626-46ab-a75e-8a537b34dad8" 24) "7288dcb8-4d33-428a-b6a5-0e8ad0f4d515" 25) "58e5cb4c-e779-4689-b085-bdebedb72731" 26) "2daac8fd-4d7a-43e5-9f5f-679ce29f4018" 27) "ac436bcd-edc7-4ee9-9137-220d847bc4f4" 28) "1cbdc3dd-c162-4257-9a83-288cd7ce2d9d" 29) "ba1e37d3-197e-42fb-901e-a1700141cb18" 30) "4cc254e7-67ec-4aad-8695-9cc1eeef0f68" 31) "bf2b9c40-0540-4d1e-97b4-fc99c2da3c74" 32) "02f83409-f09c-46ae-88c8-746e2ffa9ae7" 33) "1066a146-6da9-40fb-8207-538a5f98d13c" 34) "c9f2ab89-038d-4691-9ba8-eb98067273da" 35) "2ccf58df-bd74-488e-8bde-150b1806715c" 36) "154b4bf6-3c10-4bc5-885d-2cc97a98eea2" 37) "6cf530e4-7ede-40f5-adee-b11f095c5d06" 38) "23e8a78d-43b4-4627-b4dc-6ef46565c1fc" 192.168.200.140:6379> quit [root@node01 ~]# redis-cli -h 192.168.200.140 -p 6380 192.168.200.140:6380> keys * 1) "10bc105b-3153-4a36-a137-844b35180b0b" 2) "30c5f630-9204-4408-bed6-007668d16404" 3) "a566f597-9c8e-4167-a702-55f93c842b65" 4) "cd2cdc0c-cf85-4f60-b752-a0f23e9e8b9f" 5) "59973a7f-e6b6-48ec-a0aa-a2dfc4cbee37" 6) "21064f13-543c-4935-9bc1-6a4d6b4b8af6" 7) "e101dcb0-2b4a-4f65-bcce-41849422f40e" 8) "9b625da5-1e98-48b1-9797-2f4cb9a035ba" 9) "97bf8782-ec48-4b69-81f0-f1ef9da91ee0" 10) "35ec04bc-64a2-42f2-85b6-234237c0bb5c" 11) "38f621fc-b854-4281-9b9e-5e81b42b75ab" 12) "2eb7e614-bbf4-4eee-a7d8-0c022a93d3d1" 13) "42a2d2aa-fab5-45e4-861f-307d7c9d9657" 14) "16453f29-c925-46cd-9ce3-de881a051fff" 15) "d33b7dfa-2774-478a-9e52-d0cf4929940a" 16) "67c62fa6-e4ce-4f22-82db-24edcbd4f978" 17) "a8d92b3d-ff73-439f-92d9-329250fbe596" 18) "03506ad5-a729-47ed-9c61-b50efbbf8d91" 19) "77408f78-4e54-46a9-ad4d-bd0a10a40333" 20) "154a431b-f964-44ac-96b3-347a464b928d" 21) "904593e2-7691-4cbe-a42b-d6e7d3132da1" 22) "df07d672-b7e2-41d7-8f65-3e372149dd85" 23) "98cbe692-5f79-4403-96ef-1a8804cd552c" 24) "f4822e11-e72b-4970-a99c-7995428cc6a0" 25) "91326ca5-8093-4aff-af0a-c05f6ab3f67c" 26) "e8f2643b-0d17-41d2-9e1c-87bd91bd2fe2" 27) "6d87dba3-b326-477a-985c-023e9e59bb7a" 28) "ce714a8b-507c-4c9b-ae07-eadecc8c47b2" 29) "64ad3dba-2c06-4e1e-9dd9-694dbef94eb8" 30) "f651e61a-c84c-478e-b34d-130a03613f13" 31) "d507b9d7-ed15-401f-abf7-9ce113b1237d" 32) "d3de56aa-9abe-46e5-aa82-e2739db00c61" 33) "f56d86a8-42dd-4889-82c9-c809e5dfb4e9" 192.168.200.140:6380> quit [root@node01 ~]# redis-cli -h 192.168.200.140 -p 6381 192.168.200.140:6381> keys * 1) "fc8b0bc4-dd19-4817-9fe0-9e8e5b015492" 2) "de2c277b-1af1-43a3-bc26-4838ade9211b" 3) "e29cc1d1-566d-4975-b8da-654b7df701b5" 4) "93d43a98-d6b6-444d-b1d3-6e2558929abb" 5) "ec0a63f4-01e2-4853-9c5e-7f7f88aa7d2d" 6) "e68bf85b-9751-411c-85e0-e71f8c50d4cc" 7) "e24a7f8a-6469-4873-b546-e9d861a4ed49" 8) "dffb8776-dd3e-4e68-b0f2-95efae1f06bb" 9) "eba3c6b5-00df-433f-bce0-b434a088712d" 10) "1b807663-ccde-4b68-b62f-84f8725f2888" 11) "70bdc2f4-82bb-4a60-b446-35f66adb28fa" 12) "471a0db6-1dad-4ecc-a1d8-f7d9bee1bd3e" 13) "07f551c4-48a7-4b8a-b9c3-550666217170" 14) "92db8e28-a981-4db2-9376-6a4779b2f431" 15) "124c36ec-575e-41cb-a572-b80c3257bb8f" 16) "59386a43-5f05-4a20-850b-0cad845662a5" 17) "6413579b-fc76-4b0c-811a-f984458463c9" 18) "055c86d3-0668-439f-b4bd-0e04bb4df317" 19) "78f77451-1d0c-41c4-bf38-9914df3866ff" 20) "322cb478-f4e3-4295-abae-399aecb2b219" 21) "34768304-a285-4f3e-ab1e-5d8a7073c24e" 22) "21493487-cdf3-4eee-84a2-e743f762b998" 23) "d85559de-0b20-46bb-b2f2-afc81c5fc33c" 24) "7ae7f256-5556-4997-bf50-49465fc4c23e" 25) "38789a36-04cb-49e4-b65d-c7caac671480" 26) "68712f1d-3fc1-49f3-a38d-284beb3c203d" 27) "c894ba32-e7aa-4c2c-80cd-04c9479387ff" 28) "810de36d-6db5-473c-be6c-6e177440c967" 29) "e7c620b0-cb33-4bfc-9c57-d8dea8491e75"
以上是對redis多實例部署,分片概念和jedis使用的記錄,后續繼續補充redis的相關知識。
參考博文:
(1)https://www.cnblogs.com/peter1018/p/9765585.html redis.conf目錄介紹