如何使用REDIS做限定登錄和LIST快取?
- 2019 年 11 月 14 日
- 筆記
在工作中redis還是經常被使用到,所以對於一些簡單的redis的使用還是要會使用的,在學習的過程中用用單機的就行,真實的生產環境用單機的redis還是較少的。
首先我們使用docker安裝下redis,關於docker還不會用的可以去百度學習下,安裝使用還是非常簡單的。
1.拉取下redis鏡像
docker pull redis:3.2
2.啟動容器
dcker run -p 6699:6379 --name myredis -v $PWD/redis.conf:/etc/redis/redis.conf -v $PWD/data:/data -d redis:3.2 redis-server /etc/redis/redis.conf --appendonly yes --requirepass "123456"
命令說明:
--name myredis : 指定容器名稱,這個最好加上,不然在看docker進程的時候會很尷尬。 -p 6699:6379 : 埠映射,默認redis啟動的是6379,至於外部埠,隨便玩吧,不衝突就行。 -v $PWD/redis.conf:/etc/redis/redis.conf : 將主機中當前目錄下的redis.conf配置文件映射。 -v $PWD/data:/data -d redis:3.2 :將主機中當前目錄下的data掛載到容器的/data --redis-server --appendonly yes :在容器執行redis-server啟動命令,並打開redis持久化配置 --requirepass "123456" 設置redis密碼為123456
docker ps 查看下運行狀態

使用RedisDesktopManager工具連接下redis測試下

接下就可以集成redis操作起來了。

spring: redis: database: 5 #redis中的db5(在命令行可用 select 5 來切換到當前的db) # 配置Redis的主機地址 host: 192.168.1.174 port: 6379 password: 123456 timeout: 5000 jedis: pool: # 連接池中的最大空閑連接,默認值也是8。 max-idle: 500 # 連接池中的最小空閑連接,默認值也是0。 min-idle: 50 # 如果賦值為-1,則表示不限制;如果pool已經分配了maxActive個jedis實例,則此時pool的狀態為exhausted(耗盡) max-active: 1000 # 等待可用連接的最大時間,單位毫秒,默認值為-1,表示永不超時。如果超過等待時間,則直接拋出JedisConnectionException max-wait: 2000
封裝一下java操作redis的工具類
package lee.util; import lombok.extern.slf4j.Slf4j; import org.springframework.data.redis.core.*; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.io.Serializable; import java.util.List; import java.util.Set; import java.util.concurrent.TimeUnit; /** * @author :lyj * @email: : [email protected] * @date :2019/11/5 */ @Service @Slf4j public class RedisServiceUtil { @Resource private StringRedisTemplate stringRedisTemplate; public static final String userStringKey = "lyj:"; private RedisTemplate<Serializable, Object> redisTemplate; /** * set redis : string類型 * @param key key * @param value value */ public void setString(String key,String value){ ValueOperations<String,String> valueOperations = stringRedisTemplate.opsForValue(); valueOperations.set(key,value); } public String getString(String key){ return stringRedisTemplate.opsForValue().get(key); } /** * set redis: hash類型 * @param key key * @param filedKey filedkey * @param value value */ public void setHash(String key, String filedKey, String value){ HashOperations<String, Object, Object> hashOperations = stringRedisTemplate.opsForHash(); hashOperations.put(key,filedKey, value); } /** * get redis: hash類型 * @param key key * @param filedkey filedkey * @return */ public String getHash(String key, String filedkey){ return (String) stringRedisTemplate.opsForHash().get(key, filedkey); } /** * set redis:list類型 * @param key key * @param value value * @return */ public long setList(String key, String value){ ListOperations<String, String> listOperations = stringRedisTemplate.opsForList(); return listOperations.leftPush(key, value); } /** * get redis:list類型 * @param key key * @param start start * @param end end * @return */ public List<String> getList(String key, long start, long end) { return stringRedisTemplate.opsForList().range(key, start, end); } /** * 設置key失效時間 * @param key key * @param timeout timeout * @return */ public boolean setTimeOut(String key, long timeout){ return stringRedisTemplate.expire(key,timeout, TimeUnit.SECONDS); } /** * 根據key刪除值 * @param key * @return */ public boolean delKey(String key){ return stringRedisTemplate.delete(key); } /** * 設置值並設置失效時間 * @param key * @param value * @param timeOut */ public void setCachesData(String key,String value,long timeOut){ if (log.isDebugEnabled()) { log.debug("String, String, int - start"); //$NON-NLS-1$ } setString(key,value); setTimeOut(key,timeOut); if (log.isDebugEnabled()) { log.debug("String, String, int - start"); //$NON-NLS-1$ } } /** * 從快取中刪除數據 * * @param key * @return */ public boolean removeValue(String key) { if (log.isDebugEnabled()) { log.debug("String - start"); //$NON-NLS-1$ } boolean returnlong = delKey(key); if (log.isDebugEnabled()) { log.debug("String - end"); //$NON-NLS-1$ } return returnlong; } /** * 批量刪除對應的value * @param keys */ public void remove(final String... keys){ for (String key : keys){ remove(key); } } /** * 批量刪除key * * @param pattern */ public void removePattern(final String pattern) { Set<Serializable> keys = redisTemplate.keys(pattern); if (keys.size() > 0) redisTemplate.delete(keys); } /** * 刪除對應的value * * @param key */ public void remove(final String key) { if (exists(key)) { redisTemplate.delete(key); } } /** * 判斷快取中是否有對應的value * * @param key * @return */ public boolean exists(final String key) { return redisTemplate.hasKey(key); } /** * 讀取快取 * * @param key * @return */ public Object get(final String key) { Object result = null; ValueOperations<Serializable, Object> operations = redisTemplate .opsForValue(); result = operations.get(key); return result; } /** * 寫入快取 * * @param key * @param value * @return */ public boolean set(final String key, Object value) { boolean result = false; try { // ValueOperations<Serializable, Object> operations = redisTemplate // .opsForValue(); // operations.set(key, value); redisTemplate.opsForValue().set(key, value); result = true; } catch (Exception e) { e.printStackTrace(); } return result; } /** * 寫入快取 * * @param key * @param value * @return */ public boolean set(final String key, Object value, Long expireTime) { boolean result = false; try { ValueOperations<Serializable, Object> operations = redisTemplate .opsForValue(); operations.set(key, value); redisTemplate.expire(key, expireTime, TimeUnit.SECONDS); result = true; } catch (Exception e) { e.printStackTrace(); } return result; } public void batchDel(String... pattern){ for (String kp : pattern) { redisTemplate.delete(redisTemplate.keys(kp + "*")); } } public Set<Object> getKeys(){ return redisTemplate.opsForSet().members("*".getBytes()); } public void setRedisTemplate( RedisTemplate<Serializable, Object> redisTemplate) { this.redisTemplate = redisTemplate; } }
現在實現第一個功能限定用戶登錄非常的簡單

只需要登錄成功之後將用戶資訊設置到redis中給定一個過期時間,登錄之前根據key值去查詢下redis是否存在當前用戶如果有就直接返回當前用戶已被登錄。當然登出的時候我們也要做相應的操作。

接下來完成第二個功能我們需要用到一個工具類
package lee.util; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.ObjectMapper; import java.util.List; /** * @author :lyj * @email: : [email protected] * @date :2019/11/6 */ public class JsonUtils { private static final ObjectMapper MAPPER = new ObjectMapper(); public JsonUtils() { } public static String objectToJson(Object data) { try { String string = MAPPER.writeValueAsString(data); return string; } catch (JsonProcessingException var2) { var2.printStackTrace(); return null; } } public static <T> T jsonToPojo(String jsonData, Class<T> beanType) { try { T t = MAPPER.readValue(jsonData, beanType); return t; } catch (Exception var3) { var3.printStackTrace(); return null; } } public static <T> List<T> jsonToList(String jsonData, Class<T> beanType) { JavaType javaType = MAPPER.getTypeFactory().constructParametricType(List.class, new Class[]{beanType}); try { List<T> list = (List)MAPPER.readValue(jsonData, javaType); return list; } catch (Exception var4) { var4.printStackTrace(); return null; } } }

相同的道理在查詢之前將值轉成josn設置到redis中,查詢之前根據設置的key值查詢出來value值將轉換為list返回出去即可。
到這我們redis的操作的兩個簡單的功能就完成了,操作起來還是非常的簡單的,但是到了真實的項目中往往只會這些簡單的操作還是不行的。
可以思考思考如下的問題:
答案可以到這裡查看:https://doocs.github.io/advanced-java/#/?id=%e7%bc%93%e5%ad%98
1.在項目中快取是如何使用的?快取如果使用不當會造成什麼後果?
2.Redis 和 Memcached 有什麼區別?Redis 的執行緒模型是什麼?為什麼單執行緒的 Redis
3.比多執行緒的 Memcached 效率要高得多?
4.Redis 都有哪些數據類型?分別在哪些場景下使用比較合適?
5.Redis 的過期策略都有哪些?手寫一下 LRU 程式碼實現?
6.如何保證 Redis 高並發、高可用?Redis 的主從複製原理能介紹一下么?Redis 的哨兵原理能介紹一下么?
.Redis 的持久化有哪幾種方式?不同的持久化機制都有什麼優缺點?持久化機制具體底層是如何實現的?
8.Redis 集群模式的工作原理能說一下么?在集群模式下,Redis 的 key 是如何定址的?
9.分散式定址都有哪些演算法?了解一致性 hash 演算法嗎?如何動態增加和刪除一個節點?
10.了解什麼是 redis 的雪崩、穿透和擊穿?Redis 崩潰之後會怎麼樣?系統該如何應對
11.這種情況?如何處理 Redis 的穿透?
12.如何保證快取與資料庫的雙寫一致性?
13.Redis 的並發競爭問題是什麼?如何解決這個問題?了解 Redis 事務的 CAS 方案嗎?14.生產環境中的 Redis 是怎麼部署的?
