Redis第一话 -- Redis介绍以及基于Docker安装Redis

248 阅读7分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

随着缓存技术的发展,Redis已经成为了工作中使用的最多的缓存技术了。 那么对Redis的了解肯定是必不可少的。

1.Redis介绍

Redis是基于C语言开发的纯内存存储KV结构的一个数据库。获取数据的时间复杂度是O(1)。 Redis是基于内存的工作的(亦可持久化),具有很高的性能,普通的String存储TPS能达到10W。

2.Redis基于Docker的安装

预先准备:liunx服务器一台,docker-compose 工具和文件

  • docker-compost.yaml
version: '3.7'
services:
  redis01:
    image: redis:6.0.1
    container_name: redis01
    restart: always
    ports:
    - "6379:6379"
    environment:
    - TZ=Asia/Shanghai
    volumes:
    - /root/local/redis/data:/data
    networks:
    - my-net
 #requirepass 设置密码,不设置可以去掉
 #appendonly yes 表示在容器执行redis-server启动命令,并打开redis持久化配置
    command: redis-server --requirepass a123456 --appendonly yes
networks:
  #新增的网络 内部服务名调用
  my-net:
    external: true 
  • docker-compose启动
[root@m redis]# docker-compose up -d
Creating redis01 ... done
[root@m redis]# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                        PORTS                    NAMES
224c531c62e0        redis:6.0.1         "docker-entrypoint.s…"   7 seconds ago       Up 6 seconds                  0.0.0.0:6379->6379/tcp   redis01

3.在容器内部连接redis

[root@m redis]# docker exec -it redis01 /bin/bash
root@224c531c62e0:/data# redis-cli -h redis01 -p 6379
redis01:6379> auth a123456
OK
redis01:6379> set hello 1234
OK
redis01:6379> get hello
"1234"

可以从上面内容看出Redis是安装成功的了。接下来了解一下Redis的数据结构

4.Redis数据结构

Redis提供了各种类型的数据结构,方便应支持各种数据的存储,从而提高查询的性能。 Redis提供了9种数据结构,由5种最基本的数据结构 (String、Hash、List、Set、ZSet)和HyperLogLog(基数)、Streams(流信息)、Geospatial(地理位置计算)、Bit Arrays(位集合)组成。选择合适的数据结构存储能够大大的提高读取效率。

4.1 String字符串

1.命令

redis01:6379> auth a123456
OK
redis01:6379> set hello 1234
OK
redis01:6379> get hello
"1234"

2.数据结构 内部封装了一个char字节数组,有三种内部编码(int、embstr、raw),最大的长度为512M。int编码是用来保存整数值,raw(长度大于44字节的字符串)是用来保存长字符串的,embstr(长度小于)是用来保存短字符串的。

3.应用 String是Redis中最简单的数据结构,由K-V组成。常见的有分布式锁,计数器,统计在线人数,秒杀,用户的token信息等

4.2 Hash 哈希

1.命令

redis01:6379> hset dict id 10
(integer) 1
redis01:6379> hget dict id
"10"
redis01:6379> hgetall dict
1) "id"
2) "10"

2.数据结构 Hash对象即map对象,在redis中它的实现方式有两种ziplist、hashtable。 ziplist压缩表: 在这里插入图片描述 压缩列表是一组连续内存块组成的顺序的数据结构。压缩列表中使用多个节点来存储数据(hash个数小于512,以及所有的值小于64),超过则使用hashtable hashtable:存储的是一个一个的dictht,即dictEntry数组Map结构,每个数组存储key value,通过链式寻址(存在hash冲突)可以查找到。原理与HashMap的底层原理类似。

3.应用 常用来存储用户信息数据,用户id -> 用户信息Map。可以对字段中的自动做递增递减,可以实现分布式全局唯一ID

4.3 List(有序可重复集合)

1.命令

redis01:6379> rpush list hello
(integer) 1
redis01:6379> rpush list word
(integer) 2
redis01:6379> rpush list hello
(integer) 3
redis01:6379> lrange list 0 -1
1) "hello"
2) "word"
3) "hello"
redis01:6379> llen list
(integer) 3

2.数据结构 List在3.2版本后使用的是Quicklist结构。 quicklist的底层是采用链表进行实现的,这个链表是Redis自己实现的。 在这里插入图片描述 链表具有以下特性:

  • 每一个节点都有指向前一个节点和后一个节点的指针,链表头尾不相连是无环的
  • 链表会保存自己的长度等基本信息,所以获取长度的时间复杂度是O(1)
  • 每个Node节点的数据是基于Ziplist(压缩表)
  • rpush时添加数据会找到最后一个Ziplist(Node)节点,没满就插入,如果满了就新加一个Ziplist Node。

3.应用 有序消息队列(阻塞队列), 秒杀订单排队,抢红包金额预设。

4.4 Set 无序不可重复集合

1.命令

redis01:6379> sadd setlist hello
(integer) 1
redis01:6379> sadd setlist world
(integer) 1
redis01:6379> sadd setlist hello
(integer) 0
redis01:6379> smembers setlist
1) "world"
2) "hello"
redis01:6379> srandmember setlist
"hello"
redis01:6379> scard setlist
(integer) 2

与list相比,Set是不可重复的,但是又是无序的。

2.数据结构 Set的底层实现是Intset(数组)和dictht数组Map结构. 集合对象保存的全是整数,数量不超过512,用intset(数组) 否则用字典类型dictht 除交集查询以外,其他时间复杂度都是常量级别

3.应用 鉴于不可重复的特性,可以做数据去重,抽奖奖品控制。交集并集特性,共同好友,可能认识的好友等等。

4.5 ZSet 有序不可重复集合(sorted set)

1.命令

redis01:6379> zadd zlist 1 hello
(integer) 1
redis01:6379> zadd zlist 2 world
(integer) 1
redis01:6379> zadd zlist 3 world
(integer) 0
redis01:6379> zadd zlist 4 hello
(integer) 0
redis01:6379> zrange zlist 0 10 withscores
1) "world"
2) "3"
3) "hello"
4) "4"

有序,根据score排序

2.数据结构 每个元素会关联一个double类型的分数,从而实现对集合中的成员进行排序。集合中的成员是唯一的,分数可以重复出现。集合是通过Hash表实现的,添加删除查询的时间复杂度都是O(1)。 zset的底层实现是dictht和skiplist实现(内容大于64)。内容小于64的时候采用的是ZipList的设计。 skiplist跳跃表,是一种有序的数据结构。通过一个节点维持多个指向其他节点的指针,结构中指向前进指针和后退指针,可能根据分数快速实现定位。 dictht数组Map中的key指向skiplist的值value为分数,可用作跳表查询。

3.应用 热门数据,排行榜,成绩前十呀,都可以用该数据结构来实现。

上述结构基本上能满足工作中的需求,其他的需要了解的自行去菜鸟教程了解。

5.总结

数据结构选择问题:基于数据的存取时,要选择最合适、最快速、最方便取值的结构 数据大小问题:因为Redis是单线程安全的,存储大数据又需要一次性取值的情况下一定要选择合适的数据结构。 PS: 之前业务中遇到的一个问题,使用的是list数据结构(因为需要按顺序刷库)大数据的存入后,需要比较数据的重复性(uuid->map{浏览量,点赞量等}),在某个数据非常热门的时候这个数据会非常的大,取出的时候严重卡Redis线程,导致取出的时候插入数据一直是报错。后续修改为ZSet结构以时间戳为分数才解决这个问题。

所以,使用redis最重要的是用对数据结构 以上就是本章的全部内容了。

上一篇:通信框架之Netty第五话 - 一文了解RPC通信原理并使用Netty实现一个PRC 下一篇:Redis第二话 -- Java中使用Redis以及常用API汇总

问渠那得清如许,为有源头活水来