本文主要記錄ehcache和redis實現緩存(redis版本號:5.0.3)java
1、ehcachemysql
1.ehcache:用來管理Java中緩存的輕量級工具,其核心經過CacheManager使用,通常使用於單機版,能夠部署集羣,可是不推薦,通常使用redis或者其餘框架來實現分佈式緩存。redis
2.緩存過時策略:FIFO(先進先出原則)、LRU(最近最少使用,即目前最久未被使用的優先淘汰)、LFU(最近不經常使用[算法相似於JVM中垃圾回收器的s0和s1區],在一段時間中使用次數最少)算法
3.使用場景:通常用作一級緩存[單機版],redis作二級緩存[集羣版]spring
4.示列代碼(給出核心部分)sql
2、redis(單機版)(如下給出核心代碼,須要完整代碼在GitHub上獲取(連接在首頁))數據庫
注意事項:1.在阿里雲上購買的服務器,須要在阿里雲的安全策略中開啓redis的端口,默認是6379。bootstrap
2.安裝時須要將 bind 127.0.0.1 改爲 bind 0.0.0.0表示外網訪問。網上說註釋掉 我用版本5.0.3 不行。緩存
3.daemonize no 改爲daemonize yes 表示後臺開啓。安全
4.requirepass 123 表示設置訪問密碼。
5.修改pidfile文件路徑 pidfile /home/pro_install/redis/stand_alone/pid/redis_6379.pid
6.修改log路徑 logfile /home/pro_install/redis/stand_alone/log/redis.log redis.log文件由redis本身創建
7.修改緩存數據路徑 dir /home/pro_install/redis/stand_alone/cache_data
8.須要關閉防火牆。systemctl stop firewalld 表示臨時關閉。
9.啓動、中止、重啓 比較簡單這裏再也不贅述了。
受權對象:0.0.0.0/0 表示任何ip均可以訪問。
3、redis(主從複製)
同步原理:
1:當一個從數據庫啓動時,會向主數據庫發送sync命令。
2:主數據庫接收到sync命令後會開始在後臺保存快照(執行rdb操做),並將保存期間接收到的命令緩存起來。
3:當快照完成後,redis會將快照文件和全部緩存的命令發送給從數據庫。
4:從數據庫收到後,會載入快照文件並執行收到的緩存的命令。
搭建:環境爲阿里雲服務器,搭建一主兩備一哨兵,其中端口:6380爲master、6385和6386爲slave、26379爲哨兵監控(因爲投票選舉策略,搭建哨兵的數量最好爲奇數)。
注意事項:1.在叢服務器中 masterauth + 主服務器的密碼。
2.redis3.2版本以前採用 slaveof 指向主服務器ip,在以後用 eplicaof 指向主機的ip和端口 。
3.哨兵中sentinel monitor <master-name> <ip> <redis-port> <quorum> 便可,參數依次爲: 哨兵名字,主服務器ip,主端口,投票選舉數量(eg:2表示,作集羣后當主服務宕機後須要幾個哨兵選舉叢服務器後才能競選爲主服務)。
4.其餘配置項都比較簡單,這裏再也不贅述。
4、redis(集羣版) 3主3從
因爲redis版本升級的問題,按照網上其餘教程,可能安裝不了,在這裏記錄下安裝過,本文采用redis版本是目前最新的5.0.3。
1.集羣版先不要設置密碼,否者在安裝卡槽時會出錯。
2.安裝ruby:yum install ruby
3.安裝gem:gem update --system 若是報錯則按下面方式安裝
報錯:gpg2 --keyserver hkp://pool.sks-keyservers.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDBInstalling RVM to /usr/local/rvm
gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3(這個來源於某博客,忘記名字了,補充一下)
按照圖示刷新配置 source /etc/profile.d/rvm.sh
4.yum install rubygems 和 gem install redis
以上是環境轉變,下面搭建redis
分別創建6個保存redis數據文件夾data和6個保存pid的文件夾,若是採用端口來區分的話,能夠創建6個redis.config的文件
修改redis_6390.conf
開啓集羣 使用rdb或者aof看我的配置了
建立集羣:老版本用的是另外一個啓動,在目前的redis中是移除了
./redis/src/redis-cli --cluster create 127.0.0.1:6390 127.0.0.1:6391 127.0.0.1:6392 127.0.0.1:6393 127.0.0.1:6394 127.0.0.1:6395 --cluster-replicas 1
以上就搭建成功了。
注意:若先設置了密碼會報一下錯誤
======================================
1、緩存Map(ehcache)
1 @Component 2 public class EhcacheMap<K, V> { 3 4 private Map<K, V> echcache = new ConcurrentHashMap<>(); 5 6 public void put(K key, V value) { 7 echcache.put(key, value); 8 } 9 10 public V get(K key) { 11 return echcache.get(key); 12 } 13 14 public void remove(K key) { 15 echcache.remove(key); 16 } 17 }
ehcache.xml(ehcache)
<?xml version="1.0" encoding="UTF-8"?> <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"> <diskStore path="java.io.tmpdir/ehcache-rmi-4000" /> <!-- 多臺機器配置 rmiUrls=//192.168.8.32:400002/demoCache|//192.168.5.231:400003/demoCache --> <cacheManagerPeerProviderFactory class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory" properties="peerDiscovery=manual,rmiUrls=//127.0.0.1:5000/userCache"> </cacheManagerPeerProviderFactory> <!-- 配置 rmi 集羣模式 --> <cacheManagerPeerListenerFactory class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory" properties="hostName=127.0.0.1,port=4000,socketTimeoutMillis=120000" /> <!-- 多播方式配置 搜索某個網段上的緩存 timeToLive 0是限制在同一個服務器 1是限制在同一個子網 32是限制在同一個網站 64是限制在同一個region 128是限制在同一個大洲 255是不限制 <cacheManagerPeerProviderFactory class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory" properties="peerDiscovery=automatic, multicastGroupAddress=224.1.1.1, multicastGroupPort=40000, timeToLive=32" /> --> <!-- 默認緩存 --> <defaultCache maxElementsInMemory="1000" eternal="true" timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true" diskSpoolBufferSizeMB="30" maxElementsOnDisk="10000000" diskPersistent="true" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU"> </defaultCache>
<!-- name: Cache的名稱,必須是惟一的(ehcache會把這個cache放到HashMap裏)。
maxElementsInMemory:在內存中緩存的element的最大數目。
maxElementsOnDisk:在磁盤上緩存的element的最大數目,默認值爲0,表示不限制。
eternal:設定緩存的elements是否永遠不過時。若是爲true,則緩存的數據始終有效,若是爲false那麼還要根據timeToIdleSeconds,timeToLiveSeconds判斷。
overflowToDisk: 若是內存中數據超過內存限制,是否要緩存到磁盤上。
-->
<cache name="userCache" maxElementsInMemory="1000" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true" diskSpoolBufferSizeMB="30" maxElementsOnDisk="10000000" diskPersistent="false" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU"> <cacheEventListenerFactory class="net.sf.ehcache.distribution.RMICacheReplicatorFactory" /> <!-- 用於在初始化緩存,以及自動設置 --> <bootstrapCacheLoaderFactory class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory" /> </cache> </ehcache>
controller(ehcache)
@RestController public class EhcacheSingleVersionController { @Autowired private UserService userService; @Autowired private CacheManager cacheManager; @Autowired private EhcacheMap<String, String> ehcacheMap; @RequestMapping("/clear") public String clear() { cacheManager.getCache("userCache").clear(); return "success"; } @RequestMapping("/getUser") public List<User> getUser(Long id) { return userService.getUser(id); } @RequestMapping("/save") public String save(String name, Long id) { ehcacheMap.put(id.toString(), name); return "success"; } }
dao(ehcache)
@CacheConfig(cacheNames = "userCache") public interface UserMapper { @Select("SELECT ID ,NAME,AGE FROM user where id=#{id}") @Cacheable List<User> getUser(@Param("id") Long id); }
手動修改數據庫值(ehcache)
2、redis單機版
1.yml配置文件
1 spring: 2 datasource: 3 url: jdbc:mysql://localhost:3306/mytest?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC 4 username: root 5 password: 123456 6 driver-class-name: com.mysql.cj.jdbc.Driver 7 test-while-idle: true 8 test-on-borrow: true 9 validation-query: SELECT 1 FROM DUAL 10 time-between-eviction-runs-millis: 300000 11 min-evictable-idle-time-millis: 1800000 12 # 緩存配置 13 cache: 14 type: ehcache 15 ehcache: 16 config: classpath:ehcache.xml 17 # redis 18 redis: 19 database: 0 20 host: xxx 21 port: 6379 22 password: xxx 23 jedis: 24 pool: 25 # 鏈接池最大鏈接數(使用負值表示沒有限制) 26 max-active: 8 27 # 鏈接池最大阻塞等待時間(使用負值表示沒有限制) 28 max-wait: -1 29 # 鏈接池中的最大空閒鏈接 30 max-idle: 8 31 # 鏈接池中的最小空閒鏈接 32 min-idle: 0 33 timeout: 10000 34
2.redisUtil
1 @Component 2 public class RedisUtil { 3 4 @Autowired 5 private StringRedisTemplate stringRedisTemplate; 6 7 public void set(String key, Object obj, Long timeout) { 8 if(obj instanceof String) { 9 setString(key, obj); 10 } else if(obj instanceof Set) { 11 setSet(key, obj); 12 } 13 // 設置有效期 14 if(timeout != null) { 15 stringRedisTemplate.expire(key, timeout, TimeUnit.SECONDS); 16 } 17 } 18 19 private void setSet(String key, Object obj) { 20 21 @SuppressWarnings("unchecked") 22 Set<String> value = (Set<String>) obj; 23 for (String str : value) { 24 stringRedisTemplate.opsForSet().add(key, str); 25 } 26 } 27 28 private void setString(String key, Object obj) { 29 30 String value = (String)obj; 31 32 stringRedisTemplate.opsForValue().set(key, value);; 33 } 34 35 }
3.Controller
1 @RestController 2 public class RedisSingleVersionController { 3 4 @Autowired 5 private RedisUtil redisUtil; 6 7 @RequestMapping("/setStr") 8 public String setStr(String key, String value) { 9 10 String result = "success"; 11 12 try { 13 redisUtil.set(key, value, null); 14 } catch (Exception e) { 15 e.printStackTrace(); 16 result = "error"; 17 } 18 19 return result; 20 } 21 22 @RequestMapping("/set") 23 public String set(String key) { 24 25 String result = "success"; 26 27 try { 28 Set<String> value = new HashSet<String>(); 29 value.add("t1"); 30 value.add("t2"); 31 value.add("t3"); 32 redisUtil.set(key, value, null); 33 } catch (Exception e) { 34 e.printStackTrace(); 35 result = "error"; 36 } 37 38 return result; 39 } 40 }
4.運行