Redis入门篇-五种基本数据类型及使用场景

前期准备工作(如无需要可直接跳过)

redis安装

具体的安装教程可参考之前的章节(https://www.jianshu.com/p/91f90adb782f

启动redis server(如果没有redis install,可在src目录下找到启动命令)

执行bin/redis-server命令,出现如下图就说明启动成功

redis server启动

bin/redis-server命令后面可以指定redis的配置文件(配置文件中配置了一些参数),具体的配置文件可关注博主,后期会不断更新,共同进步;

启动redis client(如果没有redis install,可在src目录下找到启动命令)

执行bin/redis-cli [-h ip] [-p port],出现如下图所示说明客户端启动并连接成功

redis client启动

执行ping命令,测试是否连接成功,出现如下图所示表示连接成功
ping测试连接

redis的五种类型

  • string:字符串类型
  • list:列表
  • hash:hash,类似于Java中的hashMap数据结构
    • 有序,顺序为插入的顺序
    • 允许重复值
  • set:无序去重列表,与Java中的set类似
    • 无序
    • 对值进行去重
  • zset(sorted set):有序去重列表
    • 结构体中有score的值,会根据这个score的值进行排序
    • 对值进行去重

string

部分基本命令
命令 解释说明 语法 实例
set 给一个key设置string的值 set key value set k1 v1
mset set的批量操作 mset key value [key value ...] mset k1 v1 k2 v2
setex set增强,添加过期时间 setex key seconds value setex k1 10 v1
setnx 只有当key不存在的时候才会设置值 setnx key value setnx k1 v1
setrange 重置指定位置的字符 setrange key offset value setrange k1 1 v2
get 获取指定key的string值 get key get k1
append 追加string值到一个key的末尾 append key value append k1 v2
mget get的批量操作 mget key [key ...] mget k1 k2 k3
incr 对int类型的值+1操作 incr key incr k1
incrby 对int类型的值+整数操作 incrbykey increment incrby k1 10
incrbyfloat 对int类型的值+浮点数操作 incrbyfloat key increment incrbyfloat k1 0.5
decr 对int类型的值-1操作 decr key decr k1
decrby 对int类型的值-整数操作 decrby key decrement decrby k1 10
decrbyfloat 对int类型的值-浮点数操作 decrbyfloat key decrement decrbyfloat k1 0.5

提示:可使用help @string查看所有string的相关命令以使用语法与含义;

应用场景
  • 分布式锁的实现(简易版jedis)
public class SimpleDistributedLock {
    // treadcount
    private static final int threadCount = 100;
    private static CountDownLatch countDownLatch = new CountDownLatch(threadCount);
    // 1000个库存
    private static int inv = 1;
    // 锁的key
    private static final String lockKey = "distributedLock:simple";
    // 锁超时时间
    private static final long expireSeconds = 10;
    // redisson
    private static RedissonClient redissonClient;
    // redis host
    private static final String redisHost = "127.0.0.1";
    // redis port
    private static final int redisPort = 6379;
    // 初始化连接redis
    static {
        Config config = new Config();
        config.useSingleServer().setAddress(redisHost + ":" + redisPort);
        redissonClient = Redisson.create(config);
    }
    public static void main(String[] args) throws InterruptedException {
        // 模拟并发 扣减库存
        for (int i = 0; i < threadCount; i++) {
            new Thread(() -> {
                RLock lock = redissonClient.getLock(lockKey);
                try {
                    // 设置过期时间 并 加锁(获取锁)
                    lock.lock(expireSeconds, TimeUnit.SECONDS);
                    // 业务 扣减库存
                    if (inv > 0) {
                        inv--;
                    }

                } catch (Exception e) {
                    // 回滚业务操作
                } finally {
                    lock.unlock();
                    countDownLatch.countDown();
                }
            }).start();
        }
        countDownLatch.await();
        System.out.println(inv);
        redissonClient.shutdown();
    }
}
  • 分布式计数器
public class Counter {
    private static int count = 0;
    // treadcount
    private static final int threadCount = 100;
    private static CountDownLatch countDownLatch = new CountDownLatch(threadCount);
    // 锁的key
    private static final String lockKey = "distributedLock:simple";
    // 锁超时时间
    private static final long expireSeconds = 10;
    // redisson
    private static RedissonClient redissonClient;
    // redis host
    private static final String redisHost = "127.0.0.1";
    // redis port
    private static final int redisPort = 6379;
    // 初始化连接redis
    static {
        Config config = new Config();
        config.useSingleServer().setAddress(redisHost + ":" + redisPort);
        redissonClient = Redisson.create(config);
    }
    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < threadCount; i++) {
            new Thread(() -> {
                RLock lock = redissonClient.getLock(lockKey);
                try {
                    lock.lock(expireSeconds, TimeUnit.SECONDS);
                    // 业务操作
                    count++;
                } finally {
                    countDownLatch.countDown();
                    lock.unlock();
                }
            }).start();
        }
        countDownLatch.await();
        System.out.println(count);
        redissonClient.shutdown();
    }
}
  • 统计用户一年内的登录情况
# uid为key,每一位代表着一年中的一天
# 2016123240用户在第一天登录过
127.0.0.1:6379> SETBIT uid_2016123240 0 1
(integer) 0
# 2016123240用户在第八天登录过
127.0.0.1:6379> SETBIT uid_2016123240 7 1
(integer) 0
# 2016123240用户在第二十二天登录过
127.0.0.1:6379> SETBIT uid_2016123240 21 1
(integer) 0
# 2016123240用户在第三十一天登录过
127.0.0.1:6379> SETBIT uid_2016123240 30 1
(integer) 0
# 2016123240用户在第五十六天登录过
127.0.0.1:6379> SETBIT uid_2016123240 55 1
(integer) 0
# 2016123240用户在第三百六十六天登录过
127.0.0.1:6379> SETBIT uid_2016123240 365 1
(integer) 0
# 获取2016123240用户在这一年内的登录次数
127.0.0.1:6379> BITCOUNT uid_2016123240 0 -1
(integer) 6
  • 统计近7天登录过的用户数
127.0.0.1:6379> SETBIT 20210628 1 1
(integer) 0
127.0.0.1:6379> SETBIT 20210628 2 1
(integer) 0
127.0.0.1:6379> SETBIT 20210628 3 1
(integer) 0
127.0.0.1:6379> SETBIT 20210628 4 1
(integer) 0
127.0.0.1:6379> SETBIT 20210629 1 1
(integer) 0
127.0.0.1:6379> SETBIT 20210629 6 1
(integer) 0
127.0.0.1:6379> SETBIT 20210629 5 1
(integer) 0
127.0.0.1:6379> SETBIT 20210629 2 1
(integer) 0
127.0.0.1:6379> SETBIT 20210630 2 1
(integer) 0
127.0.0.1:6379> SETBIT 20210630 1 1
(integer) 0
127.0.0.1:6379> SETBIT 20210630 9 1
(integer) 0
127.0.0.1:6379> SETBIT 20210630 5 1
(integer) 0
127.0.0.1:6379> SETBIT 20210701 1 1
(integer) 0
127.0.0.1:6379> SETBIT 20210701 6 1
(integer) 0
127.0.0.1:6379> SETBIT 20210701 3 1
(integer) 0
127.0.0.1:6379> SETBIT 20210701 2 1
(integer) 0
127.0.0.1:6379> SETBIT 20210702 1 1
(integer) 0
127.0.0.1:6379> SETBIT 20210702 2 1
(integer) 0
127.0.0.1:6379> SETBIT 20210702 10 1
(integer) 0
127.0.0.1:6379> SETBIT 20210703 1 1
(integer) 0
127.0.0.1:6379> SETBIT 20210703 2 1
(integer) 0
127.0.0.1:6379> SETBIT 20210703 6 1
(integer) 0
127.0.0.1:6379> SETBIT 20210704 1 1
(integer) 0
127.0.0.1:6379> BITOP or orResult 20210628 20210629 20210630 20210701 20210702 20210703 20210704
(integer) 2
127.0.0.1:6379> BITCOUNT orResult 0 -1
(integer) 8
  • 统计最近7天连续登录的用户数
127.0.0.1:6379> SETBIT 20210628 1 1
(integer) 0
127.0.0.1:6379> SETBIT 20210628 2 1
(integer) 0
127.0.0.1:6379> SETBIT 20210628 3 1
(integer) 0
127.0.0.1:6379> SETBIT 20210628 4 1
(integer) 0
127.0.0.1:6379> SETBIT 20210629 1 1
(integer) 0
127.0.0.1:6379> SETBIT 20210629 6 1
(integer) 0
127.0.0.1:6379> SETBIT 20210629 5 1
(integer) 0
127.0.0.1:6379> SETBIT 20210629 2 1
(integer) 0
127.0.0.1:6379> SETBIT 20210630 2 1
(integer) 0
127.0.0.1:6379> SETBIT 20210630 1 1
(integer) 0
127.0.0.1:6379> SETBIT 20210630 9 1
(integer) 0
127.0.0.1:6379> SETBIT 20210630 5 1
(integer) 0
127.0.0.1:6379> SETBIT 20210701 1 1
(integer) 0
127.0.0.1:6379> SETBIT 20210701 6 1
(integer) 0
127.0.0.1:6379> SETBIT 20210701 3 1
(integer) 0
127.0.0.1:6379> SETBIT 20210701 2 1
(integer) 0
127.0.0.1:6379> SETBIT 20210702 1 1
(integer) 0
127.0.0.1:6379> SETBIT 20210702 2 1
(integer) 0
127.0.0.1:6379> SETBIT 20210702 10 1
(integer) 0
127.0.0.1:6379> SETBIT 20210703 1 1
(integer) 0
127.0.0.1:6379> SETBIT 20210703 2 1
(integer) 0
127.0.0.1:6379> SETBIT 20210703 6 1
(integer) 0
127.0.0.1:6379> SETBIT 20210704 1 1
(integer) 0
127.0.0.1:6379> BITOP and andResult 20210628 20210629 20210630 20210701 20210702 20210703 20210704
(integer) 2
127.0.0.1:6379> BITCOUNT andResult 0 -1
(integer) 1

list

部分基本命令
命令 解释说明 语法 实例
lpush 添加一个或者多个值到list中 lpush key value [value ...] lpush k1 v1 v2
lpop 移除且获取列表中第一个元素 lpop key lpop k1
llen 获取列表长度 llen key llen k1
lindex 获取列表中指定index的值 lindex key index lindex k1 0
linsert 向列表中指定元素前/后插入元素 linsert key before/after pivot value linsert k1 after v1
lrange 从列表中获取范围的值 lrange key start stop lrange k1 0 -1
lpushx 如果list存在,则添加一个值到list中 lpushx key value lpushx k1 v1
lrem 从列表中删除指定个数的指定元素 lrem key count value lrem k1 2 v1
lset 将列表中指定index的值设置为value lset key index value lset k1 1 v1
ltrim 将列表截取指定范围 ltrim key start stop ltrim k1 1 2
rpush 添加一个或者多个值到list最后中 rpush key value [value ...] rpush k1 v1 v2
rpop 移除且获取列表中最后一个元素 rpop key rpop k1
rpushx 如果list存在,则添加一个值到list最后 rpushx key value rpushx k1 v1
rpoplpush 移除一个列表中的最后一个元素,并将这个元素添加到另一个列表的第一个元素并返回 rpoplpush source destination rpoplpush k1 k2
blpop 移除且获取第一个元素(阻塞直到元素存在) BLPOP key [key ...] timeout blpop k1 10
brpop 移除且获取最后一个元素(阻塞直到元素存在) BRPOP key [key ...] timeout brpop k1 10
brpoplpush 移除一个列表中的最后一个元素,并将这个元素添加到另一个列表的第一个元素并返回(阻塞直到元素存在) brpoplpush source destination timeout brpoplpush k1 k2 10
应用场景
  • 消息队列:主要是通过blpush+brpop实现;
  • 常用数据结构实现
    • lpush + rpop 实现队列;
    • lpush + lpop 实现栈;

hash

部分基本命令
命令 解释说明 语法 实例
hget 获取hash的属性的值 hget key field hget k1 name
hgetall 获取所有的hash的属性和值 hgetall key hgetall k1
hmget 批量获取hash的属性的值 hmget key field [field ...] hmget k1 name age
hset 设置hash的指定属性的值 hset key field value hset k1 name n1
hsetnx 如果不存在,则设置hash的指定属性的值 hsetnx key field value hsetnx k1 name n1
hmset 批量设置hash的指定属性的值 hmset key field value [field value ...] hmset k1 name n1 age 18
hdel 删除指定key的属性 hdel key field [field ...] hdel k1 name age
hkeys 获取key的所有的属性 hkeys key hkeys k1
hvals 获取key的所有属性的值 hvals key hvals k1
hstrlen 获取指定key的指定属性的值的长度 hstrlen key field hstrlen k1 name
hlen 获取指定key的属性个数 hlen key hlen k1
hincrby 指定key的指定属性值增加整数值 hincrby key field increment hincrby k1 age 5
hincrbyfloat 指定key的指定属性值增加浮点值 hincrbyfloat key field increment hincrbyfloat k1 age 5.5
hexists 判断是否存在某一个属性 hexists key field hexists k1 name
应用场景
  • 存储对象(object):set user name zhangsan age 13
  • 购物车:
    • 添加到购物车:hset shop_car product_1001 1
    • 增加商品个数:hincrby shop_car product_1001 2
    • 删除商品:hdel shop_car product_1001
    • 计算购物车商品种类数:hlen shop_car

set

部分基本命令
命令 解释说明 语法 实例
sadd 添加一个或多个元素 sadd key member [member ...] sadd k1 v1 v2 v3
scard 获取set的元素个数 scard key scard k1
sdiff 差集 sdiff key [key ...] sdiff k1 k2
sdiffstore 计算差集并将结果存储在另一个key sdiffstore destination key [key ...] sdiffstore result k1 k2
sinter 交集 sinter key [key ...] sinter k1 k2
sinterstore 计算交集并将结果存储在另一个key sinterstore destination key [key ...] sinterstore result k1 k2
sismember 判断是否存在值 sismember key member sismember k1 v1
smembers 获取set的所有值 smember key smember k1
smove 移动set的指定值到另一个set中 smove source destination member smove k1 target v1
spop 移除并返回指定个数的数 spop key [count] spop k1 2
srandmember 获取指定范围的一个或多个值 srandmember key [count] srandmember k1 2
srem 删除指定值 srem key member [member ...] srem k1 v1
sscan 迭代 sscan key cursor [MATCH pattern] [COUNT count] ``
sunion 并集 sunion key [key ...] sunion k1 k2
sunionstore 计算并集并将结果存储到新的set中 sunionstore destination key [key ...] sunionstore result k1 k2
应用场景
  • 微博关注/粉丝列表:sadd follow 1 2 3/ sadd fans 1 2 3
  • 共同关注列表:sinter follow1 follow2
  • 猜你喜欢:sdiff follow1 follow2
  • 随机抽奖:spop award_pool 10

zset

部分基本命令
命令 解释说明 语法 实例
zadd 添加一个或多个元素(带有score) zadd key score member [score member ...] zadd k1 1 v1 2 v2
zcard 获取set的元素个数 zcard key zcard k1
zcount 计算value在min-max中的个数 zcount key min max zcount k1 1 10
zincrby 指定值增加指定整数值 zincrby key increment member zincrby k1 10 v1
zinterstore 交集并将结果存储到另一个zset zinterstore destination numkeys key [key ...] [WEIGHTS weight] [AGGREGATE SUM] zinterstore result k1 k2
zlexcount 计算zset中score在min-max的值得个数 zlexcount key min max zlexcount k1 1 10
zpopmax 弹出并返回count个最高分的元素 zpopmax key [count] zpopmax k1 2
zpopmin 弹出并返回count个最低分的元素 zpopmin key [count] zpopmin k1 2
zrangebyscore 获取根据分数获取指定范围内的值 zrangebyscore key min max [WITHSCORES] [LIMIT offset count] zrangebyscore k1 1 10
zrank 获取指定元素的index zrank key member zrank k1 v1
zscan 迭代 zscan key cursor [MATCH pattern] [COUNT count] ``
zscore 获取指定值得score zscore key member zscore k1 v1
zunionstore 计算并集并将结果存储到另一个zset zunionstore destination numkeys key [key ...] [WEIGHTS weight] [AGGREGATE SUM] zset result k1 k2
zrem 删除一个或多个元素 zrem key member [member ...] zrem k1 v1 v2 v3
应用场景
  • 微博热搜
  • 最新列表

应用场景实战,后续待更新,如果您觉得有帮助,麻烦点个三连,给个关注。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,905评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,140评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,791评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,483评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,476评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,516评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,905评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,560评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,778评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,557评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,635评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,338评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,925评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,898评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,142评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,818评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,347评论 2 342

推荐阅读更多精彩内容