1.Redis系列之Docker本地部署及基本数据类型

1. Docker本地部署

介绍采用docker-compose快速部署redis7,供学习使用

1. 编写docker-compose.yml文件

version: '3'
services:
  redis:
    network_mode: bridge
    container_name: redis
    image: redis:7.0.5-alpine3.16
    ports:
      - 6379:6379
    command: redis-server /usr/local/redis/conf/redis.conf
    volumes:
      - ./data:/data
      - ./conf/redis.conf:/usr/local/redis/conf/redis.conf
    sysctls: # socket监听(listen)的backlog上限, 默认值同样为128。backlog就是socket的监听队列,当一个请求(request)尚未被处理或建立时,他会进入backlog。而socket server可以一次性处理backlog中的所有请求,处理后的请求不再位于监听队列中。当server处理请求较慢,以至于监听队列被填满后,新来的请求会被拒绝
      - net.core.somaxconn=1024
    # 使用该参数,container内的root拥有真正的root权限。否则,container内的root只是外部的一个普通用户权限
    privileged: true
    environment:
      - TZ=Asia/Shanghai
      - LANG=en_US.UTF-8

2. 修改redis.conf配置文件

# 密码设置为shenjian.online
requirepass shenjian.online
# 修改所有IP均可访问
bind * -::*

3. 服务启动

docker-compose up -d

服务启动后,我们登录redis,执行查询数据库0,OK

/data # redis-cli --askpass
Please input password: ***************
127.0.0.1:6379> select 0
OK

代码已上传至https://gitee.com/SJshenjian/blog-code/tree/master/src/main/java/online/shenjian/redis

2. Key操作

介绍redis键key基本操作

// 切换数据库,redis0-15,共16个数据库
127.0.0.1:6379> select 0
OK
// 查看所有的key
127.0.0.1:6379> keys *
(empty array)
// 赋值key键blog值为shenjian.online
127.0.0.1:6379> set blog shenjian.online
OK
// 查看blog类型
127.0.0.1:6379> type blog
string
// 查看blog值
127.0.0.1:6379> get blog
"shenjian.online"
// 设置blog过期时间10s
127.0.0.1:6379> expire blog 10
(integer) 1
// 查看blog还有多久过期,-1永不过期 -2已过期
127.0.0.1:6379> ttl blog
(integer) -2
// 删除key
127.0.0.1:6379> del blog
(integer) 1
// 非阻塞删除key:仅将key从keyspace元数据中删除,真正的删除会在后续异步操作
127.0.0.1:6379> unlink blog
(integer) 0
// 查看当前库key数量
127.0.0.1:6379> dbsize
(integer) 0
// 清空当前库!!!!!!!!
127.0.0.1:6379> flushdb
OK
// 清除所有库!!!!!!!!
127.0.0.1:6379> flushall
OK

3. 字符串String

我们学习redis五大常用数据类型之字符串String的基本操作及编码与底层数据结构

3.1 基本操作

// set key value设置键值对
127.0.0.1:6379> set blog shenjian.online
OK
// get查询对应键值
127.0.0.1:6379> get blog
"shenjian.online"
// EX表示10秒后key过期
127.0.0.1:6379> set blog shenjian EX 10
OK
// PX表示1000毫秒后key过期
127.0.0.1:6379> set blog shenjian PX 1000
OK
// NX表示不存在key则设置,nil不成功
127.0.0.1:6379> set blog shenjian NX
(nil)
// XX表示存在key则设置,OK成功
127.0.0.1:6379> set blog shenjian XX
OK
127.0.0.1:6379> get blog
"shenjian"
// 向key值中追加.online字符串
127.0.0.1:6379> append blog .online
(integer) 15
// 获取key值长度
127.0.0.1:6379> strlen blog
(integer) 15
// 当key不存在时设置值,0设置失败
127.0.0.1:6379> setnx blog shenjian
(integer) 0
127.0.0.1:6379> set count 0
OK
// 增加1
127.0.0.1:6379> incr count
(integer) 1
// 减少1
127.0.0.1:6379> decr count
(integer) 0
// 当前key值加5
127.0.0.1:6379> incrby count 5
(integer) 5
// 当前key值减4
127.0.0.1:6379> decrby count 4
(integer) 1
127.0.0.1:6379> get count
"1"
// mset批量赋值
127.0.0.1:6379> mset name shenjian sex man
OK
// 批量获取值
127.0.0.1:6379> mget name sex other
1) "shenjian"
2) "man"
3) (nil)
// msetnx批量赋值,原子性,一个失败全部失败
127.0.0.1:6379> msetnx name zhangsan other 3
(integer) 0
127.0.0.1:6379> mget name other
1) "shenjian"
2) (nil)
// 获取字符串指定位置
127.0.0.1:6379> getrange name 0 3
"shen"
// 在指定位置开始替换值
127.0.0.1:6379> setrange name 0 hao
(integer) 8
127.0.0.1:6379> get name
"haonjian"
// 获取旧值同时设置新值
127.0.0.1:6379> getset name shenjian
"haonjian"
// 设置过期时间10秒,上面也出现过奥
127.0.0.1:6379> setex name 10 shenjian
OK
127.0.0.1:6379> ttl name
(integer) 8

3.2 内部编码

127.0.0.1:6379> set name shenjianshenjianshenjianshenjianshenjianshen
OK
127.0.0.1:6379> strlen name
(integer) 44
127.0.0.1:6379> object encoding name
"embstr"
127.0.0.1:6379> set name shenjianshenjianshenjianshenjianshenjianshens
OK
127.0.0.1:6379> strlen name
(integer) 45
127.0.0.1:6379> object encoding name
"raw"
127.0.0.1:6379> set age 20
OK
127.0.0.1:6379> object encoding age
"int"

由上可以看出,当字节数少于等于44时,字符串编码为embstr,当大于44时,字符串编码为raw,对于整型编码为int

127.0.0.1:6379> set name shenjian
OK
127.0.0.1:6379> object encoding shenjian
(nil)
127.0.0.1:6379> append name shenjian
(integer) 16
127.0.0.1:6379> object encoding blog
"raw"

由上可以看出,redis中embstr实现为只读,只要是修改embstr对象,修改后的对象一定是raw的,无论是否达到了44个字节

  • embstr与raw都使用redisObject和sds保存数据
  • embstr只分配一次内存空间,因此redisObject和sds[稍后介绍]是连续的
  • raw需要分配两次内存空间,分别为redisObject和sds分配空间,不连续。
  • embstr好处:创建/删除时少分配/释放一次空间,对象的所有数据连续,查找方便
  • embstr坏处:当需要重新分配内存时,整个redisObject和sds都要重新分配空间,因此redis中的embstr实现为只读

3.3 底层数据结构

String的数据结构为简单动态字符串(Simple Dynamic String,即SDS),是可以修改的字符串,采用预分配冗余空间的方式来减少内存的频繁分配。
当字符串长度小于1M时,扩容是加倍现有空间。超过1M,扩容只会多扩1M空间,字符串最大长度为512M

4. 列表list

4.1 基本操作

# lpush/rpush从左边或右边插入一个或多个值
127.0.0.1:6379> lpush username shenjian domi
(integer) 2
# lpop/rpop从左边或右边抛出一个值
127.0.0.1:6379> rpop username 1
1) "shenjian"
# lrange按照索引下标从左到右获取元素
127.0.0.1:6379> lrange username 0 -1
1) "domi"
# rpoplpush <key1> <key2> 从key1列表右边抛出一个值,插到key2列表左边
127.0.0.1:6379> lpush user shen
(integer) 1
127.0.0.1:6379> rpoplpush user username
"shen"
127.0.0.1:6379> lrange username 0 -1
1) "shen"
2) "domi"
# lindex按照索引下标获取元素
127.0.0.1:6379> lindex username 1
"domi"
# llen获取列表长度
127.0.0.1:6379> llen username
(integer) 2
# linsert <key> before/after <value> <newvalue>在value前/后面插入newvalue
127.0.0.1:6379> linsert username before domi shenjian
(integer) 3
127.0.0.1:6379> lrange username 0 -1
1) "shen"
2) "shenjian"
3) "domi"
127.0.0.1:6379> lpush username shenjian
(integer) 4
# lrem <key> <n> <value>从左边删除n的value
127.0.0.1:6379> lrem username 1 shenjian
(integer) 1
# lset <key> <index> <value>key列表指定下标值为value
127.0.0.1:6379> lset username 0 shenjian
OK

4.2 底层数据结构

127.0.0.1:6379> object encoding username
"quicklist"

2

List的数据结构为快速列表quicklist,由压缩列表ziplist[压缩列表结构本身就是连续的内存块]和普通的双向链表组成。每个双链表节点中保存一个ziplist,然后每个ziplist中存一批list中的数据,这样既可以避免大量链表指针带来的内存消耗,也可以避免ziplist更新导致的大量性能损耗。

5. 集合Set

5.1 基本操作

# sadd集合添加元素
127.0.0.1:6379> sadd username shenjian shenjian domi jing
(integer) 3
# smembers取出集合中所有元素
127.0.0.1:6379> smembers username
1) "shenjian"
2) "domi"
3) "jing"
# sismember查看元素是否在集合中,1是 0否
127.0.0.1:6379> sismember username shenjian
(integer) 1
# scard返回集合大小
127.0.0.1:6379> scard username
(integer) 3
# srem删除集合中指定元素
127.0.0.1:6379> srem username jing
(integer) 1
# spop随机从结合中抛出n个数元素
127.0.0.1:6379> spop username 1
1) "domi"
127.0.0.1:6379> sadd username zhangsan lisi
(integer) 2
# srandmember从集合中随机取出n个值,但不会删除
127.0.0.1:6379> srandmember username 1
1) "shenjian"
127.0.0.1:6379> sadd age 20
(integer) 1
# smove <source> <destination> member把源集合中元素移动到目标集合中
127.0.0.1:6379> smove username age shenjian
(integer) 1
127.0.0.1:6379> smembers age
1) "shenjian"
2) "20"
127.0.0.1:6379> sadd username shenjian
(integer) 1
#  sinter取集合交集
127.0.0.1:6379> sinter username age
1) "shenjian"
# sunion取集合并集
127.0.0.1:6379> sunion username age
1) "shenjian"
2) "zhangsan"
3) "20"
4) "lisi"
# sdiff取集合差集
127.0.0.1:6379> sdiff username age
1) "zhangsan"
2) "lisi"

5.2 数据结构

127.0.0.1:6379> object encoding username
"hashtable"
127.0.0.1:6379> sadd number 1 2 3
(integer) 3
127.0.0.1:6379> object encoding number
"intset"
127.0.0.1:6379> sadd number shen
(integer) 1
127.0.0.1:6379> object encoding number
"hashtable"

由上可知,Set底层数据结构为整数集合intset和字典hashtable,其中intset可以理解为一种特殊的数组,而hashtable就是普通的哈希表

6. 集合ZSet

6.1 基本操作

# zadd <key> <score> <member>将多个member元素及其score值加入有序集合key中
127.0.0.1:6379> zadd top 100 java 99 python 98 vue
(integer) 3
# zrange由小到大返回有序集合指定下标内元素
# zrange <key> <start> <stop>
127.0.0.1:6379> zrange top 0 -1
1) "vue"
2) "python"
3) "java"
# zrevrange由大到小返回有序集合指定下标内元素
127.0.0.1:6379> zrevrange top 0 -1
1) "java"
2) "python"
3) "vue"
# zrange返回有序集合指定下标内元素及评分
127.0.0.1:6379> zrange top 0 -1 WITHSCORES
1) "vue"
2) "98"
3) "python"
4) "99"
5) "java"
6) "100"
# zrangebyscore返回有序集合指定评分范围内元素
127.0.0.1:6379> zrangebyscore top 99 100
1) "python"
2) "java"
# zincrby <key> <increment> <member> 给有序集合中元素评分+增量
127.0.0.1:6379> zincrby top 1 python
"100"
# zrem删除有序集合中元素
127.0.0.1:6379> zrem top vue
(integer) 1
# zcount统计有序集合指定评分范围内数量
127.0.0.1:6379> zcount top 100 100
(integer) 2
# zrank返回有序集合中元素排名
127.0.0.1:6379> zrank top python
(integer) 1

6.2 底层数据结构

127.0.0.1:6379> object encoding top
"listpack"
127.0.0.1:6379> zadd top 96 mysql 95 mongo 94 elasticsearch 93 clickhouse 92 spark 91 k8s2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222
(integer) 1
127.0.0.1:6379> object encoding top
"skiplist"

由上可知,Zset底层数据结构为压缩列表listpack和跳跃表skiplist[结构如下图]

1

7. 哈希Hash

7.1 常用操作

# hset <key> <field> <value> 哈希表赋值
127.0.0.1:6379> hset community city shanghai region jingan
(integer) 2
# hget获取指定field值
127.0.0.1:6379> hget community city
"shanghai"
# hmset批量赋值
127.0.0.1:6379> hmset community city shandong region linyi
OK
# hexists判断哈希表中是否存在指定field
127.0.0.1:6379> hexists community city
(integer) 1
# hkeys获取哈希表所有field
127.0.0.1:6379> hkeys community
1) "city"
2) "region"
# hvals获取哈希表中所有值
127.0.0.1:6379> hvals community
1) "shandong"
2) "linyi"
127.0.0.1:6379> hmset community name binhemingdi households 1000
OK
# hincrby为哈希表指定field加增量
127.0.0.1:6379> hincrby community households 500
(integer) 1500
# hsetnx哈希表指定field不存在则赋值
127.0.0.1:6379> hsetnx community city shanghai
(integer) 0

7.2 底层数据结构

127.0.0.1:6379> object encoding community
"listpack"
127.0.0.1:6379> hsetnx community memo goooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooood
(integer) 1
127.0.0.1:6379> object encoding community
"hashtable"

由上可知,哈希hash底层有压缩列表listpack、字典hashtable两种数据结构

欢迎关注公众号算法小生或沈健的技术博客shenjian.online

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

算法小生Đ

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

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

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

打赏作者

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

抵扣说明:

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

余额充值