【Redis】Redis入门

一、压力测试

  • 命令

redis-benchmark -h 127.0.0.1 -p 6379 -c 50 -n 10000

  • 指令大全在这里插入图片描述

二、基本指令

  • 进入客户端:

redis-cli

  • 切换数据库

select 1(0~16)

  • 清空当前数据库

flushdb

  • 清空所有数据库数据

flushall

  • 查看当前库所有的key

key *

  • 插入/修改

get [key] / set [key] [value]

  • 当前库数据条目

dbsize

  1. 是否存在key

exists [key]

  1. 移动key / 移除key

move [key] 1 / del [key]

  1. k-v 的类型

type

  1. 获取修改

getset

过期时间

  • 设置过期时间

expire [k] [time]
ttl key

  • 过期时间

setex [k] [time] [v]

  • 分布式锁

SETNX [k] [v]

  • 批量设置k-v

MSET k1 v1 k2 v2 k3 v3

  • 批量获取

MGET k1 k2 k3

  • 批量分布式

MSETNX

三、五大数据类型

1、String

  • 追加字符串

append [k] [v]

  • 截取字符串

getrange [key] [start] [end]

  • 修改字符串

SETRANGE [key] [offset] [value]

  • +1

incr [key]

  • -1

decr [key]

  • 自定义加减

INCRBY [key] [自增数]

2、List

  • 头插

lPUSH [key] [values…]

  • 尾插

RPUSH [key] [values…]

  • 头弹出

LPOP [key]

  • 尾弹出

RPOP [key]

  • 取所有值

LRANGE [key] 0 -1

  • 下标取值

LINDEX [key] [index]

  • list长度

LLEN [key]

  • 删除指定的值

LREM [key] [count] [value]

  • 取出l1尾值放到l2头部

RPOPLPUSH l1 l2

3、Set

  • 无需不重复集合
  • 添加元素

SADD [key] [member…]

  • 查看所有值

SMEMBERS [key]

  • 判断是否在某个集合中

SISMEMBER [key] [member]

  • 获取集合长度

SCARD [key]

  • 移除指定元素

SREM [key] [member]

  • 随机抽选元素

SRANDMEMBER [key] [count]

  • 差集

SDIFF [key1] [key2] …

  • 交集

SINTER [key1] [key2] …

  • 并集

SUNION [key1] [key2] …

4、Hash

  • set

HSET [key] [field] [value]

  • get

HGET [key] [field] [value]

  • 设置多个值

HMSET [key] f1 v1 f2 v2 f3 v3

  • 获取所有k-v

HGETALL [key]在这里插入图片描述

  • 删除

HDEL [key] [field]

  • hash长度

HLEN [key]

  • 判断是否存在

HEXISTS [key] [field]

127.0.0.1:6379[2]> HEXISTS myhash g
(integer) 0
127.0.0.1:6379[2]> HEXISTS myhash a
(integer) 1

5、Zset

  • 有序的集合
  • 添加元素

// score下标
set [key] [score] [value]

  • 排序 按照score排序

ZRANGEBYSCORE myset2 -inf +inf

四、三种特殊数据类型

1、geospatial 地理位置

  • 基本命令
GEOADD
GEODIST
GEOHASH
GEOPOS
GEORADIUS
GEORADIUSBYMEMBER
  • GEOADD (设置)
命令:
GEOADD [key] [精度] [纬度] [member]

例子:
GEOADD [key] [精度] [纬度] [member]
127.0.0.1:6379[1]> GEOADD china:city 121.48 31.22 shanghai
(integer) 1
127.0.0.1:6379[1]> GEOADD china:city 102.73 25.04 yunan
(integer) 1
127.0.0.1:6379[1]> GEOADD china:city 104.06 30.67 sichuan
(integer) 1
  • GEOPOS (取值)
命令:
127.0.0.1:6379[1]> GEOPOS china:city shanghai
1) 1) "121.48000091314315796"
   2) "31.21999956478423854"
  • GEODIST(返回两个坐标距离)
参数unit:
m 表示单位为米。
km 表示单位为千米。
mi 表示单位为英里。
ft 表示单位为英尺。

命令:
GEODIST key member1 member2 [单位unit]

例:
127.0.0.1:6379[1]> GEODIST china:city shanghai yunan km
"1960.1311" 
  • GEORADIUS (返回半径之内的所有位置元素)
命令:
GEORADIUS [key] [longitude] [latitude] [radius 半径] [m|km|ft|mi] [withdist 直线距离] [withcoord 经纬度] [count 1 指定查询数量]

例:
127.0.0.1:6379[1]> GEORADIUS china:city 121 31 100 km withdist withcoord count 1

1) 1) "shanghai"
   2) "51.8477"
   3) 1) "121.48000091314315796"
      2) "31.21999956478423854"
  • GEORADIUSBYMEMBER (指定位置决定)
命令:
GEORADIUSBYMEMBER china:city shanghai 1000 km

例子:
127.0.0.1:6379[1]> GEORADIUSBYMEMBER china:city shanghai 1000 km
1) "shanghai"
2) "sh-songjiang"

2、hyperloglogs 基数统计

  • 基数 (不重复的元素)
# 添加
127.0.0.1:6379[1]> PFADD mypf d sad d d da d d d ad as
(integer) 1

# 不重复元素数量
127.0.0.1:6379[1]> PFCOUNT mypf
(integer) 5

# 合并两个集合
127.0.0.1:6379[1]> PFMERGE mypf3 mypf mypf2
OK

3、bitmaps

  • 位存储 (二进制进行记录 0101010)
  • 记录一周的打卡情况
# 周一:0  周二:1  周三:1  周四:0 ......

# setbit
127.0.0.1:6379[1]> SETBIT sign 1 0
(integer) 0
127.0.0.1:6379[1]> SETBIT sign 2 1
(integer) 0
127.0.0.1:6379[1]> SETBIT sign 3 1
(integer) 0
127.0.0.1:6379[1]> SETBIT sign 4 0
(integer) 0
127.0.0.1:6379[1]> SETBIT sign 5 1
(integer) 0
127.0.0.1:6379[1]> SETBIT sign 6 1
(integer) 0
127.0.0.1:6379[1]> SETBIT sign 7 0
(integer) 0

# gitbit
127.0.0.1:6379[1]> GETBIT sign 1
(integer) 0

# bitcount 统计打卡记录
127.0.0.1:6379[1]> BITCOUNT sign
(integer) 4

五、事务

事务的基本操作

  • 开启事务(multi)
  • 事物入队
127.0.0.1:6379[1]> MULTI  # 开启事物
OK
127.0.0.1:6379[1]> HSET myset f1 v1  # 入队
QUEUED
127.0.0.1:6379[1]> HSET myset f2 v2  # 入队
QUEUED
127.0.0.1:6379[1]> EXEC  # 执行入队的命令
1) (integer) 1
2) (integer) 1
  • 执行事务(exec)
  • 放弃事务(discard)

事务实现-乐观锁、悲观锁

  • 悲观锁(认为任何操作都会出错,无论做什么都加锁)
  • 乐观锁(认为任何操作都不会出错,只在跟新数据时候判断是否有人修改过这个数据)
# 监视这个key,在exec是否发生其他变化,发生变化执行失败
127.0.0.1:6379> WATCH money  
OK

# exec和discard也可以解锁

# 放弃当前的锁,,,,重新建一个锁,,,执行之后操作
127.0.0.1:6379> UNWATCH
OK

六、SpringBoot整合

  1. application.yml 配置连接参数:
## Redis 配置
spring:
  redis:
#    database: 0  #数据库索引(默认为0)
    host: 127.0.0.1
    port: 6379  #默认链接端口
    password:   #默认为空
    lettuce:
      pool:
        max-active: 20 #最大链接池
        max-wait: -1 #最大阻赛等待时间(使用负值没有限制)默认为-1
        max-idle: 20 #连接池中的最大空闲连接 默认 8
        min-idle: 0
  1. 自定义RedisConfig(由于redis的原生配置不支持序列化,所以需要手动配置config的template模版完善序列化操作
/**
 * @since 2020/9/10 20:01
 */
//配置类的注解
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {

    /**
     * retemplate相关配置
     * @param factory
     * @return
     */
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {

        System.out.println("11");
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        // 配置连接工厂
        template.setConnectionFactory(factory);

        //使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(默认使用JDK的序列化方式)
        Jackson2JsonRedisSerializer jacksonSeial = new Jackson2JsonRedisSerializer(Object.class);

        ObjectMapper om = new ObjectMapper();
        // 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        // 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jacksonSeial.setObjectMapper(om);

        // value采用json序列化
        template.setValueSerializer(jacksonSeial);
        //使用StringRedisSerializer来序列化和反序列化redis的key值
        template.setKeySerializer(new StringRedisSerializer());
        // 设置hash key 和value序列化模式
        template.setHashKeySerializer(new StringRedisSerializer());
        template.setHashValueSerializer(jacksonSeial);
        template.afterPropertiesSet();

        return template;
    }

    /**
     * 对hash类型的数据操作
     *
     * @param redisTemplate
     * @return
     */
    @Bean
    public HashOperations<String, String, Object> hashOperations(RedisTemplate<String, Object> redisTemplate) {
        return redisTemplate.opsForHash();
    }

    /**
     * 对redis字符串类型数据操作
     *
     * @param redisTemplate
     * @return
     */
    @Bean
    public ValueOperations<String, Object> valueOperations(RedisTemplate<String, Object> redisTemplate) {
        return redisTemplate.opsForValue();
    }

    /**
     * 对链表类型的数据操作
     *
     * @param redisTemplate
     * @return
     */
    @Bean
    public ListOperations<String, Object> listOperations(RedisTemplate<String, Object> redisTemplate) {
        return redisTemplate.opsForList();
    }

    /**
     * 对无序集合类型的数据操作
     *
     * @param redisTemplate
     * @return
     */
    @Bean
    public SetOperations<String, Object> setOperations(RedisTemplate<String, Object> redisTemplate) {
        return redisTemplate.opsForSet();
    }

    /**
     * 对有序集合类型的数据操作
     *
     * @param redisTemplate
     * @return
     */
    @Bean
    public ZSetOperations<String, Object> zSetOperations(RedisTemplate<String, Object> redisTemplate) {
        return redisTemplate.opsForZSet();
    }
}

  1. 配置RedisUtil
/**
 * @since 2020/9/11 23:02
 */
@Component
public final class RedisUtil {
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    // =============================common============================

    /**
     * 指定缓存失效时间
     *
     * @param key  键
     * @param time 时间(秒)
     * @return
     */
    public boolean expire(String key, long time) {
        try {
            if (time > 0) {
                redisTemplate.expire( key, time, TimeUnit.SECONDS );
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 根据key 获取过期时间
     *
     * @param key 键 不能为null
     * @return 时间(秒) 返回0代表为永久有效
     */
    public long getExpire(String key) {
        return redisTemplate.getExpire( key, TimeUnit.SECONDS );
    }

    /**
     * 判断key是否存在
     *
     * @param key 键
     * @return true 存在 false不存在
     */
    public boolean hasKey(String key) {
        try {
            return redisTemplate.hasKey( key );
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 删除缓存
     *
     * @param key 可以传一个值 或多个
     */
    @SuppressWarnings("unchecked")
    public void del(String... key) {
        if (key != null && key.length > 0) {
            if (key.length == 1) {
                redisTemplate.delete( key[0] );
            } else {
                redisTemplate.delete( CollectionUtils.arrayToList( key ) );
            }
        }
    }
    // ============================String=============================

    /**
     * 普通缓存获取
     *
     * @param key 键
     * @return 值
     */
    public Object get(String key) {
        return key == null ? null : redisTemplate.opsForValue().get( key );
    }

    /**
     * 普通缓存放入
     *
     * @param key   键
     * @param value 值
     * @return true成功 false失败
     */
    public boolean set(String key, Object value) {
        try {
            redisTemplate.opsForValue().set( key, value );
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 普通缓存放入并设置时间
     *
     * @param key   键
     * @param value 值
     * @param time  时间(秒) time要大于0 如果time小于等于0 将设置无限期
     * @return true成功 false 失败
     */
    public boolean set(String key, Object value, long time) {
        try {
            if (time > 0) {
                redisTemplate.opsForValue().set( key, value, time, TimeUnit.SECONDS );
            } else {
                set( key, value );
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 递增
     *
     * @param key   键
     * @param delta 要增加几(大于0)
     * @return
     */
    public long incr(String key, long delta) {
        if (delta < 0) {
            throw new RuntimeException( "递增因子必须大于0" );
        }
        return redisTemplate.opsForValue().increment( key, delta );
    }

    /**
     * 递减
     *
     * @param key   键
     * @param delta 要减少几(小于0)
     * @return
     */
    public long decr(String key, long delta) {
        if (delta < 0) {
            throw new RuntimeException( "递减因子必须大于0" );
        }
        return redisTemplate.opsForValue().increment( key, -delta );
    }

    // ================================Map=================================

    /**
     * HashGet
     *
     * @param key  键 不能为null
     * @param item 项 不能为null
     * @return 值
     */
    public Object hget(String key, String item) {
        return redisTemplate.opsForHash().get( key, item );
    }

    /**
     * 获取hashKey对应的所有键值
     *
     * @param key 键
     * @return 对应的多个键值
     */
    public Map<Object, Object> hmget(String key) {
        return redisTemplate.opsForHash().entries( key );
    }

    /**
     * HashSet
     *
     * @param key 键
     * @param map 对应多个键值
     * @return true 成功 false 失败
     */
    public boolean hmset(String key, Map<String, Object> map) {
        try {
            redisTemplate.opsForHash().putAll( key, map );
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * HashSet 并设置时间
     *
     * @param key  键
     * @param map  对应多个键值
     * @param time 时间(秒)
     * @return true成功 false失败
     */
    public boolean hmset(String key, Map<String, Object> map, long time) {
        try {
            redisTemplate.opsForHash().putAll( key, map );
            if (time > 0) {
                expire( key, time );
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 向一张hash表中放入数据,如果不存在将创建
     *
     * @param key   键
     * @param item  项
     * @param value 值
     * @return true 成功 false失败
     */
    public boolean hset(String key, String item, Object value) {
        try {
            redisTemplate.opsForHash().put( key, item, value );
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 向一张hash表中放入数据,如果不存在将创建
     *
     * @param key   键
     * @param item  项
     * @param value 值
     * @param time  时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间
     * @return true 成功 false失败
     */
    public boolean hset(String key, String item, Object value, long time) {
        try {
            redisTemplate.opsForHash().put( key, item, value );
            if (time > 0) {
                expire( key, time );
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 删除hash表中的值
     *
     * @param key  键 不能为null
     * @param item 项 可以使多个 不能为null
     */

    public void hdel(String key, Object... item) {
        redisTemplate.opsForHash().delete( key, item );
    }

    /**
     * 判断hash表中是否有该项的值
     *
     * @param key  键 不能为null
     * @param item 项 不能为null
     * @return true 存在 false不存在
     */
    public boolean hHasKey(String key, String item) {
        return redisTemplate.opsForHash().hasKey( key, item );
    }

    /**
     * hash递增 如果不存在,就会创建一个 并把新增后的值返回
     *
     * @param key  键
     * @param item 项
     * @param by   要增加几(大于0)
     * @return
     */
    public double hincr(String key, String item, double by) {
        return redisTemplate.opsForHash().increment( key, item, by );
    }

    /**
     * hash递减
     *
     * @param key  键
     * @param item 项
     * @param by   要减少记(小于0)
     * @return
     */
    public double hdecr(String key, String item, double by) {
        return redisTemplate.opsForHash().increment( key, item, -by );
    }
    // ============================set=============================

    /**
     * 根据key获取Set中的所有值
     *
     * @param key 键
     * @return
     */
    public Set<Object> sGet(String key) {
        try {
            return redisTemplate.opsForSet().members( key );
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 根据value从一个set中查询,是否存在
     *
     * @param key   键
     * @param value 值
     * @return true 存在 false不存在
     */
    public boolean sHasKey(String key, Object value) {
        try {
            return redisTemplate.opsForSet().isMember( key, value );
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 将数据放入set缓存
     *
     * @param key    键
     * @param values 值 可以是多个
     * @return 成功个数
     */
    public long sSet(String key, Object... values) {
        try {
            return redisTemplate.opsForSet().add( key, values );
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 将set数据放入缓存
     *
     * @param key    键
     * @param time   时间(秒)
     * @param values 值 可以是多个
     * @return 成功个数
     */
    public long sSetAndTime(String key, long time, Object... values) {
        try {
            Long count = redisTemplate.opsForSet().add( key, values );
            if (time > 0)
                expire( key, time );
            return count;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 获取set缓存的长度
     *
     * @param key 键
     * @return
     */
    public long sGetSetSize(String key) {
        try {
            return redisTemplate.opsForSet().size( key );
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 移除值为value的
     *
     * @param key    键
     * @param values 值 可以是多个
     * @return 移除的个数
     */
    public long setRemove(String key, Object... values) {
        try {
            Long count = redisTemplate.opsForSet().remove( key, values );
            return count;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }
    // ===============================list=================================

    /**
     * 获取list缓存的内容
     *
     * @param key   键
     * @param start 开始
     * @param end   结束 0 到 -1代表所有值
     * @return
     */
    public List<Object> lGet(String key, long start, long end) {
        try {
            return redisTemplate.opsForList().range( key, start, end );
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 获取list缓存的长度
     *
     * @param key 键
     * @return
     */
    public long lGetListSize(String key) {
        try {
            return redisTemplate.opsForList().size( key );
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 通过索引 获取list中的值
     *
     * @param key   键
     * @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推
     * @return
     */
    public Object lGetIndex(String key, long index) {
        try {
            return redisTemplate.opsForList().index( key, index );
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 将list放入缓存
     *
     * @param key   键
     * @param value 值
     * @return
     */
    public boolean lSet(String key, Object value) {
        try {
            redisTemplate.opsForList().rightPush( key, value );
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 将list放入缓存
     *
     * @param key   键
     * @param value 值
     * @param time  时间(秒)
     * @return
     */
    public boolean lSet(String key, Object value, long time) {
        try {
            redisTemplate.opsForList().rightPush( key, value );
            if (time > 0)
                expire( key, time );
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 将list放入缓存
     *
     * @param key   键
     * @param value 值
     * @return
     */
    public boolean lSet(String key, List<Object> value) {
        try {
            redisTemplate.opsForList().rightPushAll( key, value );
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 将list放入缓存
     *
     * @param key   键
     * @param value 值
     * @param time  时间(秒)
     * @return
     */
    public boolean lSet(String key, List<Object> value, long time) {
        try {
            redisTemplate.opsForList().rightPushAll( key, value );
            if (time > 0)
                expire( key, time );
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 根据索引修改list中的某条数据
     *
     * @param key   键
     * @param index 索引
     * @param value 值
     * @return
     */
    public boolean lUpdateIndex(String key, long index, Object value) {
        try {

            redisTemplate.opsForList().set( key, index, value );
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 移除N个值为value
     *
     * @param key   键
     * @param count 移除多少个
     * @param value 值
     * @return 移除的个数
     */
    public long lRemove(String key, long count, Object value) {
        try {
            Long remove = redisTemplate.opsForList().remove( key, count, value );
            return remove;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小鱼小鱼啊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值