csx 发表于 2024-3-10 21:59

Redis的简单使用分享

emm 上次帮水友排查了一个redis 的问题。有水友留言想了解一下redis。我对redis的了解也不是很多一点点浅见分享给水友。希望水友能有收获。

Redis 是什么?
官方解释(https://redis.io/docs/about/): Redis是一个开源(BSD许可)的内存数据结构存储,用作数据库、缓存、消息代{过}{滤}理和流引擎。Redis提供了数据结构,如字符串、哈希、列表、集合、排序集合、范围查询、位图、超日志、地理空间索引和流。Redis具有内置复制、Lua脚本、LRU驱逐、事务和不同级别的磁盘持久性,并通过Redis Sentinel和Redis Cluster提供高可用性和自动分区。


通俗解释(个人认为),Redis 是一款基于C语言开发的开源的内存数据库。它提供了丰富的数据(结构)类型 包括字符串(strings)、哈希(hashes)、列表(lists)、集合(sets)和有序集合(sorted sets)、位图(bitmap)、地理空间索引(GEO)、流(stream) 等, 可以基于这些属于上述的数据(结构)类型,高效的满足我们的业务需求。


Redis 官网: https://redis.io/ (注意这里是.io域名)


版本差异
Redis 社区比较活跃,版本更新迭代非常快。截止到目前发文之前的版本是 Stable (7.2) 这里我们只拿出 5、6、7 三个版本简略说下差异,这里只说最核心的部分。详细对比差异请参考官网或网络。


redis 5新的stream数据类型
redis 6增加了多线程Thread I/O(工作线程还是单线程)和 ACL细粒度的权限控制
redis 7 Redis Functions
Redis怎么使用? 可以用来做什么?
Redis 通常需要搭配一种开发语言来配合业务使用。如常见的开发语言都会有SDK 客户端。https://redis.io/docs/connect/clients/(官方clients)也可以使用常见的桌面端开源图形客户端。
Redis 根据不同的业务需求,所能做的东西也不同 App后台服务端端业务、场景不同需求不同。下面我会举一些常见的业务需求场景 和 经典实现。
为什么要使用redis ?
Redis 基于内存操作数据,且是单线程原子操作(单个命令),因为单线程读写,避免了多线程并发冲突。早起redis 官方号称 单机redis qps为10w/s(和机器配置相关)
Redis桌面客户端
这种开源的桌面客户端连接工具非常的多,大家可以根据自己的喜好选择。我这里只介绍两款 两款都支持 支持Mac、Windows和Linux。
Tiny RDM
官网: https://redis.tinycraft.cc/zh/ (https://github.com/wailsapp/wails "https://redis.tinycraft.cc/zh/")
github: https://github.com/tiny-craft/tiny-rdm/releases (https://github.com/wailsapp/wails "https://github.com/tiny-craft/tiny-rdm/releases")
https://pic.imgdb.cn/item/65e32c539f345e8d03faaf1f.png
AnotherRedisDesktopManager
github:https://github.com/qishibo/AnotherRedisDesktopManager/releases
https://pic.imgdb.cn/item/65e32be19f345e8d03f8d14b.png
redis 安装
这里提供两种安装方式。
基于 Rethat Linux 发行版本的操作系统安装(yum)
yum install -y gcc tcl gcc-c++ make
yum install -y epel-release
yum install redis -y
上述命令执行完就已经安装好了。
打开配置文件:vim /etc/redis.conf
修改默认密码:查找 requirepass,默认密码为 foobared。需要修改
https://pic.imgdb.cn/item/65e32cc49f345e8d03fc9d35.png
找到 bind 127.0.0.1 将其注释,否则redis只允许本机连接
https://pic.imgdb.cn/item/65e32cee9f345e8d03fd5ff0.png
找到 protected-mode yes 将其改为:protected-mode no
https://pic.imgdb.cn/item/65e32da79f345e8d0300784c.png
找到 port 6379 建议修改默认端口号
https://pic.imgdb.cn/item/65e32d289f345e8d03fe684f.png
添加iptables 规则:
iptables -I INPUT -p tcp --dport 6379 -j ACCEPT
https://pic.imgdb.cn/item/65e32dc19f345e8d0300eb08.png

Centos7 防火墙规则 :
firewall-cmd --zone=public --add-port=6379/tcp --permanent
firewall-cmd --reload
启动 : systemctl start redis
https://pic.imgdb.cn/item/65e32e809f345e8d03044545.png

基于docker的方式安装,全平台通用前提是要装个docker。
1、docker pull redis:6.2.7
https://pic.imgdb.cn/item/65e32ede9f345e8d0305d3f7.png
2、创建需要挂载的配置目录和文件
mkdir -p /data/redis6/conf
touch /data/redis6/redis.conf(这一步也可以先启动容器 从容器中copy出来一个。或者去dockerHub wget下来一个)
3、启动 docker run -p 6379:6379 --privileged=true --name redis6 -v /data/redis6/data:/data -v /data/redis6/conf/redis.conf:/etc/redis/redis.conf -d redis:6.2.7redis-server /etc/redis/redis.conf
https://pic.imgdb.cn/item/65e32eb79f345e8d03053168.png
Redis 命令:
https://redis.io/commands/(官网)
https://pic.imgdb.cn/item/65e32f379f345e8d030749a6.png
每个命令都有示例 。可以根据数据类型筛选,过滤 首字母索引等。
以前有个中文版的现在找不到了

redis 常见的数据类型 和 经典实现
String:
      描述: 最基本的数据类型,二进制安全。不仅限于 存储 String。最大存储512M.
      ops: set 会覆盖数据 get incre自增 setnx 如果存在则返回,不存在则返回0。
      经典实现: 自增数实现分布式全局ID 各种访问数量,如 用户访问量,点赞。字符串用来存储 token , 短信验证码之类。
Hash(字典):
      描述: 存储类型类似于对象。hmset创建对象。 通过hget hset 获取对象。
      ops: hmset key ,,. hget obj.filed. hset obj.filed
      经典实现: json序列化的对象存储,购物车实现。
List(列表):
      desc:按照插入的String元素排序,后进先出 (stack)的数据结构。可以存储40亿成员。O(1) 复杂度
      ops: lpush 。 lrange 取数据
      经典实现: 最新消息排行榜。
Set(集合):
      desc: 集合,类似于java List 无序,通过hash表实现。不允许重复。
      ops: sadd 添加集合元素, smembers 获取集合。
      SRANDMEMBER KEY :随机弹出集合中的一个元素
      SPOP KEY :随机删除弹出集合中的一个元素
      SCARD KEY : 集合中的元素个数
      经典实现:
      把关注人存在set中.可以 求交集、并集、差集。操作 计算共同关注。
      SPOP 、SRANDMEMBER 随机弹出元素可用于立即参与(微信)抽奖。(把用户id放入)
      SCARD 可用于显示多少人进行参加抽奖活动
      SCARD 点赞数量
StoreSet(Zset有序集合):
      desc:会记录一个double类型的 score ,按照从小到达排序。score可以重复,Value不允许重复 分数小靠前。
      升序排列,分值越大越靠后,分值相同,则按照value的字典顺序排序
      ops:
      zadd key score member
      nx: member 必须不存在,才可以设置成功,用于添加
      xx: member 必须存在,才可以设置成功,用于更新
      ch: 返回此次操作后,有序集合元素和分数发生变化的个数
      incr: 对 score 做增加,相当于后面介绍的 zincrby
      zadd key score value [添加key]
      ZCARD key [获取一个排序的集合中的成员数量]
      zrange key 0,n(-1) [遍历集合 从小到大]
      zrevrange key 0,n(-1)[遍历集合 从大到小]
      zrangebyscore key 0,n(-1) limit x x[根据分数值查询,可选分页参数]
      zremrangebyscore key x x 删除有序set。
      经典实现:热搜排行榜(根据浏览点赞)、存储班级学生成绩排序。程序根据重要的任务排序,score 高的任务优先执行。
pub/sub(发布订阅)
      底层实现:
      Redis有两种发布/订阅模式:
      基于频道(Channel)的发布/订阅
      基于模式(pattern)的发布/订阅
      命令:
      #订阅 处于监听消息的状态
      SUBSCRIBE channels
      subscreibe user-topic
      #发布消息
      PUBLISH channels message
      publish user-topic hello
      # 查看当前订阅列表
      pubsub channels
BitMap
ops :   setbit key 1 1 ,getbit key 1, bitcount key
      经典实现: 统计打卡 、在线人数 、10亿手机号中判断重复
redis 具体使用场景(Redis 通常需要配合开发语言来完成业务。)
String 类型
存储 AccessToken和 RefreshToken。
现在主流的web 或者app 与后端交互 登陆鉴权 的方式基本是 accessToken的形式。
用户登陆 服务端会 生成两个随机字符串"access_token:a6f1efca84705b7041193f96f265ac768d35" 作为Key,
把用户的id 作为value 。设置过期时间为30min 后过期。
生成"refresh_token:e4e44f08754dadbfeec2927ee706cb01fa6b" 作为key ,把用户id 设置成value
设置过期时间为 1个月。
这样每次客户端发起请求携带access_token,后端从redis拿到并且校验,如果过期。则前端重新使用refresh_token换取 access_token。
set access_token:a6f1efca84705b7041193f96f265ac768d35 1ex 1800
https://pic.imgdb.cn/item/65e330779f345e8d030ce12b.png
set refresh_token:e4e44f08754dadbfeec2927ee706cb01fa6b 1ex 2626560
https://pic.imgdb.cn/item/65e330969f345e8d030d70d2.png
设置商品详情页,从程序中写入redis 中。
https://pic.imgdb.cn/item/65e331199f345e8d03105792.png

分布式自增ID (在分布式环境下保证id不重复)
set increment_id 1
INCR increment_id
https://pic.imgdb.cn/item/65e331a19f345e8d0312f118.png

Set 数据类型
公司年会简单的抽奖 把 公司所有人的姓名添加到 set 集合中。总共 有 3 等奖。 从
set 集合中随机弹出 3 个 做为 1 2 3 等奖。
sadd prize_user tom
sadd prize_user eric
sadd prize_user jack
sadd prize_user bob
https://pic.imgdb.cn/item/65e331fc9f345e8d031476f0.png
SPOP prize_user
SPOP prize_user
SPOP prize_user
https://pic.imgdb.cn/item/65e3326d9f345e8d0316206c.png
bitMap
有序大数据 去重 统计
假如 需要对一个亿的手机号判断是否有重复。在通常情况下我们会通过hash 来判断。这样不仅占用内存而且效率也不是特别高。我们可以把号码放到redis bitmap中。号码通常是11位第一位都是1 可以去调。这样还剩下 8位数字。bitmap 是一个数组具体存储的是bit位 0 和 1 。那么我们的号码就可以作为数组下标最大为 99999999 的下标。下面我们就以131 开头的号码演示
setbit mobile_coll 3162587639 1
setbit mobile_coll 3162587611 1
setbit mobile_coll 3162587612 1
setbit mobile_coll 3162587613 1
setbit mobile_coll 3162587614 1
setbit mobile_coll 3162587615 1
setbit mobile_coll 3162587615 1
https://pic.imgdb.cn/item/65e332e39f345e8d0317da41.png
当我们第一次 放进去 13162587615 号码的时候返回0。我们再次放进去的时候就返回 1 说明该号码已经存在。时间复杂度为O(1) 且不占用内存。
bitMap 在线用户统计把一些用户添加到 user_onlins 中 1表示在线 0表示下线 (online 单词好像拼错了undefined)setbit user_onlins 132637 1
setbit user_onlins 132638 1
setbit user_onlins 132639 0
setbit user_onlins 132640 1
setbit user_onlins 132641 1
setbit user_onlins 132642 1
https://pic.imgdb.cn/item/65e3359b9f345e8d03231d5a.png
BITCOUNT user_onlins 统计 user_onlins 下的在线人数https://pic.imgdb.cn/item/65e3366e9f345e8d03267941.png


分布式锁
如果我们的系统是分布式服务架构,调用操作系统内核加锁。已经不能保证并发安全。
举例子 52论坛中的签到功能,在0点的时候一个用户模拟发送了10个签到请求,如果该系统是分布式的情况下 10个请求 会被nginx 分发3台服务器。单个服务器中跑的代码加锁已经不能保证数据一致性。这个时候可以借助一个中间件来完成分布式锁的功能。保证在分布式集群环境下并发安全。
分布式锁的实现方式很多。借助的中间件也不限于Redis 主要是一种思想。在java生产环境中一般会使用 redisson 提供的分布式锁。或者zookeeper 来实现。

redis 内存8种淘汰策略(内存超过 maxmemory):
maxmemory-policy 可以指定配置使用下面哪一种淘汰策略。
   默认是no-eviction。内存满了写入OOM。
      1. volatile-lru:从已设置过期时间的数据集中挑选最近最少使⽤的数据淘汰。
      2. volatile-random:从已设置过期时间的数据集中任意选择数据淘汰。
      3. allkeys-lru:当内存不⾜以容纳新写⼊数据时,在键空间中,移除最近最少使⽤的 key(常用)
      4. allkeys-random:从数据集(server.db.dict)中任意选择数据淘汰。
      5. volatile-ttl:从已设置过期时间的数据集中挑选将要过期的数据淘汰。
      6. no-eviction:禁⽌驱逐数据,也就是说当内存不⾜以容纳新写⼊数据时,新写⼊操作会报错OOM。
      7. volatile-lfu:从已设置过期时间的数据集中挑选最不经常使⽤的数据淘汰。
      8. allkeys-lfu:当内存不⾜以容纳新写⼊数据时,在键空间中,移除最不经常使⽤的 key。


redis 删除策略(key过期删):
1、定时删除(时间换空间)
       节约内存,无占用,不分时段占用CPU资源,频度高
2、惰性删除(空间换时间)
       内存占用严重 延时执行,CPU利用率高
3、定期删除(折中)两种方式混合 Redis默认采用的就是该模式
       内存定期随机清理 每秒花费固定的CPU资源维护内存 随机抽查,重点抽查


ok~ 写的比较乱。。 凑合看吧。有问题可以在讨论哈 。
页: [1]
查看完整版本: Redis的简单使用分享