如何使用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 是怎麼部署的?

Tags: