Redis入門及鎖和計數的實現

1、Redis簡介
Redis(Remote Dictionary Server ),即遠程字典服務,是一個開源的使用ANSI C語言編寫、支持網絡、可基於內存亦可持久化的日誌型、Key-Value數據庫,並提供多種語言的API。
Redis支持存儲的value類型相對更多,包括string(字符串)、list(鏈表)、set(集合)、zset(sorted set --有序集合)和hash(哈希類型)。這些數據類型都支持push/pop、add/remove及取交集並集和差集及更豐富的操做,並且這些操做都是原子性的。在此基礎上,redis支持各類不一樣方式的排序。與memcached同樣,爲了保證效率,數據都是緩存在內存中。區別的是redis會週期性的把更新的數據寫入磁盤或者把修改操做寫入追加的記錄文件,而且在此基礎上實現了master-slave(主從)同步。mysql

2、Redis的命令
命令行進入客戶端redis

$ redis-cli

進入遠程客戶端spring

$ redis-cli -h host -p port -a password

查看redis信息sql

127.0.0.1:6379> info all

Redis入門及鎖和計數的實現
一、String
增改mongodb

redis 127.0.0.1:6379> SET runoobkey redis
OK

數據庫

redis 127.0.0.1:6379> GET runoobkey
"redis"

刪(其餘類型命令也同樣)緩存

redis 127.0.0.1:6379> DEL runoobkey
(integer) 1

二、Hash
Redis hash 是一個 string 類型的 field 和 value 的映射表,hash 特別適合用於存儲對象。
增改網絡

127.0.0.1:6379>  HMSET runoobkey name "redis tutorial" description "redis basic commands for caching" likes 20 visitors 23000
OK

maven

127.0.0.1:6379>  HGETALL runoobkey
1) "name"
2) "redis tutorial"
3) "description"
4) "redis basic commands for caching"
5) "likes"
6) "20"
7) "visitors"
8) "23000"

三、List
分佈式

redis 127.0.0.1:6379> LPUSH runoobkey redis
(integer) 1
redis 127.0.0.1:6379> LPUSH runoobkey mongodb
(integer) 2
redis 127.0.0.1:6379> LPUSH runoobkey mysql
(integer) 3

redis 127.0.0.1:6379> LRANGE runoobkey 0 10
1) "mysql"
2) "mongodb"
3) "redis"

四、Set
Redis 的 Set 是 String 類型的無序集合。集合成員是惟一的,這就意味着集合中不能出現重複的數據。

Redis 中集合是經過哈希表實現的,因此添加,刪除,查找的複雜度都是 O(1)。

redis 127.0.0.1:6379> SADD runoobkey redis
(integer) 1
redis 127.0.0.1:6379> SADD runoobkey mongodb
(integer) 1
redis 127.0.0.1:6379> SADD runoobkey mysql
(integer) 1
redis 127.0.0.1:6379> SADD runoobkey mysql
(integer) 0

redis 127.0.0.1:6379> SMEMBERS runoobkey

1) "mysql"
2) "mongodb"
3) "redis"

五、sorted set
有序集合和集合同樣也是string類型元素的集合,且不容許重複的成員。

不一樣的是每一個元素都會關聯一個double類型的分數。redis正是經過分數來爲集合中的成員進行從小到大的排序。

有序集合的成員是惟一的,但分數(score)卻能夠重複。

redis 127.0.0.1:6379> ZADD runoobkey 1 redis
(integer) 1
redis 127.0.0.1:6379> ZADD runoobkey 2 mongodb
(integer) 1
redis 127.0.0.1:6379> ZADD runoobkey 3 mysql
(integer) 1
redis 127.0.0.1:6379> ZADD runoobkey 3 mysql
(integer) 0
redis 127.0.0.1:6379> ZADD runoobkey 4 mysql
(integer) 0

redis 127.0.0.1:6379> ZRANGE runoobkey 0 10 WITHSCORES

1) "redis"
2) "1"
3) "mongodb"
4) "2"
5) "mysql"
6) "4"

3、Jedis的應用
以maven工程爲例,引入jar包

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>2.9.0</version>
</dependency>
Jedis jedis = new Jedis("localhost");
        System.out.println("鏈接成功");
        String key = "myname1";
        try{
                String result = jedis.set(key,"test_set_key");//插入數據
                System.out.println(key+":"+result);
                result = jedis.get(key);//查詢數據
                if(null == result)result = "";
                System.out.println(key+":"+result);
        }catch (Exception e){
                e.printStackTrace();
                System.out.println("err:"+e.getMessage());
        }

打印結果:

鏈接成功
myname1:OK
myname1:test_set_key

4、結合SpringCloud應用
maven配置引入

<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-redis</artifactId>
    <version>1.8.1.RELEASE</version>
</dependency>

而後再service中引入RedisTemplate

@Autowired
    private RedisTemplate<String,String> redisTemplate;

增改
第一個參數key,第二個參數value,第三個參數過時時間,第四個參數過時時間單位

redisTemplate.opsForValue().set(key, value, 20, TimeUnit.DAYS);

String value = redisTemplate.opsForValue().get(key);

redisTemplate.delete(key);

5、分佈式鎖
Redis鎖實現方法

@Value("${redisConfig.lockName}")
private String LOCK_PREFIX;// 鎖名稱 "redis_lock_"
@Value("${redisConfig.lockTime}")
private int LOCK_EXPIRE; // 加鎖失效時間,毫秒
@Override
public boolean lock(String key){

        log.debug("LOCK_PREFIX:"+LOCK_PREFIX);
        log.debug("LOCK_EXPIRE:"+LOCK_EXPIRE);
        String lock = LOCK_PREFIX + key;
        // 利用lambda表達式
        return (Boolean) redisTemplate.execute((RedisCallback) connection -> {
                long expireAt = System.currentTimeMillis() + LOCK_EXPIRE + 1;
                //當key不存在時,咱們進行set操做;若key已經存在,則不作任何操做;
                Boolean acquire = connection.setNX(lock.getBytes(), String.valueOf(expireAt).getBytes());
                if (acquire) {
                        return true;
                } else {
                        byte[] value = connection.get(lock.getBytes());
                        if (Objects.nonNull(value) && value.length > 0) {
                                long expireTime = Long.parseLong(new String(value));
                                // 若是鎖已通過期
                                if (expireTime < System.currentTimeMillis()) {
                                        // 從新加鎖,防止死鎖
                                        byte[] oldValue = connection.getSet(lock.getBytes(), String.valueOf(System.currentTimeMillis() + LOCK_EXPIRE + 1).getBytes());
                                        return Long.parseLong(new String(oldValue)) < System.currentTimeMillis();//若未超時,返回true
                                }
                        }
                }
                return false;
        });
}

/**
 * 刪除鎖
 * @param key
 */
@Override
public void deleteLock(String key) {
        String lock = LOCK_PREFIX + key;
        redisTemplate.delete(lock);
}

調用方式:

if(redisService.lock(key)){
        //寫業務
        redisService.deleteLock(key);
}else{
        log.debug("該主鍵的數據正在被其餘服務處理,key:"+key);
}

6、計數
計數的方式主要採用redisTemplate的increment方法,第一個參數是key,第二個參數即增長的個數:

redisTemplate.opsForValue().increment("counter_total",1);
相關文章
相關標籤/搜索