1redis基础
Redis基础
Redis和Memchched
- 数据类型:Memcached 仅支持字符串类型,而 Redis 支持五种不同的数据类型,可以更灵活地解决问题。
- 数据持久化:Redis 支持两种持久化策略:RDB 快照和 AOF 日志,而 Memcached 不支持持久化。
- 分布式:Memcached 不支持分布式,只能通过在客户端使用一致性哈希来实现分布式存储,这种方式在存储和查询时都需要先在客户端计算一次数据所在的节点。
- 内存管理机制
- 在 Redis 中,并不是所有数据都一直存储在内存中,可以将一些很久没用的 value 交换到磁盘,而 Memcached 的数据则会一直在内存中。
- Memcached 将内存分割成特定长度的块来存储数据,以完全解决内存碎片的问题。但是这种方式会使得内存的利用率不高,例如块的大小为 128 bytes,只存储 100 bytes 的数据,那么剩下的 28 bytes 就浪费掉了
性能
- Redis默认有六个数据库,从0-5,每个数据库单例能处理key:2.5亿个,一个key或是value大小最大是512M;Redis性能还是极高的,读的速度是110000次/s,写的速度是81000次/s 。
通用命令
- 仅当不存在时赋值,两种写法
- set key value nx
- SETNX
- SETXX : 只有键已经存在时,才对键进行色赋值操作
- setex key timeout value
- 为指定的 key 设置值及其过期时间。如果 key 已经存在, SETEX 命令将会替换旧的值。
- setpx 设置键的过期时间为毫秒
- keys * 获取所有的key * 号可以匹配正则
- type key 获取该key的数据类型
- del key 删除指定的key value
- exists key 确认一个key是否存在
- expire key seconds 设置一个key的生存时间 ttl key : 返回一个key的剩余过期事件。
- rename oldkeyname newkeyname 重命名key
- SCAN
- SACN 命令每次被调用之后, 都会向用户返回一个新的游标, 用户在下次迭代时需要使用这个新游标作为 SCAN 命令的游标参数, 以此来延续之前的迭代过程。当 SCAN命令的游标参数被设置为
0
时, 服务器将开始一次新的迭代, 而当服务器向用户返回值为0
的游标时, 表示迭代已结束。
- SACN 命令每次被调用之后, 都会向用户返回一个新的游标, 用户在下次迭代时需要使用这个新游标作为 SCAN 命令的游标参数, 以此来延续之前的迭代过程。当 SCAN命令的游标参数被设置为
数据类型
String
- 包含三种字符串、数值、bitmap
- 存储:set key value
- 获取:get key
- 删除:del key
- 追加:APPEND
- 用指定的字符串覆盖给定 key 所储存的字符串值,覆盖的位置从偏移量 offset 开始
- setrange k1 6 v2
- 获取存储在指定 key 中字符串的子字符串。字符串的截取范围由 start 和 end 两个偏移量决定(包括 start 和 end 在内)。
- getrange k1 start end (支持反向索引)
- 重新赋值并返回原值: getset k1 v2
- 获取字符串长度: STRLEN key
- 同时赋值或获取: mset mget
二进制安全
- 空字符’\0‘,C语言是判断空字符去判断一个字符的长度的,但是有很多数据结构经常会穿插空字符在中间,比如图片,音频,视频,压缩文件的二进制数据。
- Redis的String使用长度去校验是否到了字符的结尾
数值增减
- 整数才能进行数值增减
- 原子性操作
- 自增命令 incr
- 制定步长自增 incrby key increment(步长)
- 递减 decr decrby
Hash
- 存储: hset key filed1 value1 filed2 value2
- 获取: hget key filed1
- 全部获取:hgetall key
- 删除: hdel key filed1
- 判断字段是否存在:HEXISTS key filed
- 只获取字段名或字段数量: hkeys key 、hvalues key
- 获取字段数量 : HLEN key
- 哈希表中的字段值加上指定增量值: Hincrby key filed1 INCR_BY_NUMBER
- 应用场景
- 哈希支持单独修改字段,存储那些对象数据,特别是对象属性经常发生增删改操作的数据
List
- 双向链表实现,有序重复,按照出入顺序排序,可以添加元素到头部和尾部
- 赋值:lpush key value1 | rpush key value1
- 取值和赋值使用相同方向的命令可以模拟队列,使用方向相反的命令可以模拟栈
- 获取元素个数:llen key
- 获取
- 范围获取:lrange key start end (0 -1):取出全部
- 获取或设置指定索引的元素值
- LINDEX key index LSET key index value
- 只保留区间指定的元素
- LTRIM key start stop
- 向列表中插入元素
- LINSERT key BEFORE|AFTER pivot value
- 该命令首先会在列表中从左到右查找值为pivot的元素,然后根据第二个参数是BEFORE还是AFTER来决定将value插入到该元素的前面还是后面。
- LINSERT key BEFORE|AFTER pivot value
- 将元素从一个列表转移到另一个列表
- RPOPLPUSH source destination
- 删除
- lpop key : 删除一个元素并返回 rpop key
- 删除类表中指定个数的指定值
- LREM key count value
- 当count>0时, LREM会从列表左边开始删除。
- 当count<0时, LREM会从列表后边开始删除。
- 当count=0时, LREM删除所有值为value的元素。
- LREM key count value
- 阻塞查找
- blpop
- 应用场景
- 消息队列
- 时间线
- 文章列表或者数据分页展示的应用。
- 比如,我们常用的博客网站的文章列表,当用户量越来越多时,而且每一个用户都有自己的文章列表,而且当文章多时,都需要分页展示,这时可以考虑使用Redis的列表,列表不但有序同时还支持按照范围内获取元素,可以完美解决分页查询功能。大大提高查询效率。
Set
- 无序,不允许重复元素,内部是hash实现,支持交集操作
- 添加
- sadd key value
- 获取
- smembers key : 获取所有元素
- 删除
- srem key value : 删除集合中的某个元素
- 判断元素是否在集合中
- SISMEMBER key member
- 获取集合中的元素个数
- SCARD key
- 从集合中弹出某个元素
- SPOP key
- SRANDMEMBER key count
- 用于返回集合中的一个随机元素
- 如果countcount 为正数,且小于集合基数,那么命令返回一个包含 count 个元素的数组,数组中的元素各不相同。如果 count 大于等于集合基数,那么返回整个集合。
- 如果count 为负数,那么命令返回一个数组,数组中的元素可能会重复出现多次,而数组的长度为 count 的绝对值。
- SPOP key count
- 用于移除集合中的指定 key 的count个随机元素,移除后会返回移除的元素。
运算指令
- 差集运算
- SDIFF key1 [key …]
- 获得key1与其他集合的差集
- SDIFF key1 [key …]
- 交集运算
- SINTER key [key …]
- 并集运算
- SUNION key [key …]
Sortedset
- 有序,不允许重复元素,通过哈希表实现,排序后的集合中的每个元素都与一个称为得分的浮点值相关联,按照分数进行排序
- 存储
- zadd key score value
- 获取
- zrange key start end (0 -1):取出全部 withsores(获取全部分数)
- zrevrange 从大到小
- 获取元素的分数
- ZSCORE key member
- 获得集合中元素的数量
- ZCARD key
- 获得指定分数范围的元素
- ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]
- 增加某个元素的分数
- ZINCRBY key increment member
- 删除
- zrem key value
- 获得指定范围内的元素个数
- ZCOUNT key min max
- 按照排名范围删除元素
- ZREMRANGEBYRANK key start stop
- 按照分数范围删除元素
- ZREMRANGEBYSCORE key min max
- 获取元素的排名
- ZRANK | ZREVRANK key member
- 取交集
- ZUNIONSTORE destination numkeys key [key …] [WEIGHTS weight [weight …]] [AGGREGATE SUM|MIN|MAX]
- numkeys 为key的数量 WEIGHTS 为各个key的权重,合并时会按照权重计算分数 AGGREGATE 为当value值相同,对于相同的value值的source的处理
排序的数据结构
- 元素唯一且按分数(score)排序,结合哈希表(快速查找)和跳跃表(范围查询)。
- skip list,类似于数据库的B+树,区别是skip list是随机选层
应用场景
- 排行榜:有序集合经典使用场景。例如视频网站需要对用户上传的视频做排行榜,榜单维护可能是多方面:按照时间、按照播放量、按照获得的赞数等
- 用Sorted Sets来做带权重的队列,比如普通消息的score为1,重要消息的score为2,然后工作线程可以选择按score的倒序来获取工作任务。让重要的任务优先执行。
bitMap
- 基于 String 的位操作,每个 bit 表示 0/1。
- setbit k1 1 1 :将第一个字节的第二位变为1,默认为0, 0000 0000 -> 0100 0000
- bitcount k start end: 统计start end中1出现的次数
- bitpos k bit start end : 返回位图中第一个值为bit的位置
- bitop operation destkey key1 key2…:对一个或多个保存二进制位的字符串key进行位元操作,并将结果保存到destksy上
- operation可以是AND、OR、NOT、XOR
HyperLogLog
- 基数统计(估算集合中不重复元素数量),误差率约 **0.81%**。
- 在 Redis 中实现的 HyperLoglog 也只需要 12 K 内存,在 标准误差 0.81% 的前提下,能够统计 2的64 次方数据!
- 应用场景
- 统计独立 IP 访问量。
- 大型数据集的去重计数(如搜索关键词去重)。
Geospatial
- 基于 Sorted Set 存储经纬度,使用 GeoHash 编码。
- 应用场景
- 配送距离计算
- 附近的人/地点
Stream
- Redis 5.0 引入,用于消息队列,支持多消费者组和消息持久化。
- 应用场景
- 异步通信系统(类似 Kafka)
- 日志收集(支持回溯消费)
数据结构
SDS
- String键的底层实现 还被用作缓冲区
- 原生C语言字符串采用遍历拿到字符串长度,效率太低,SDS自己维护了长度信息
- 底层是char数组
- 还减少了修改字符串时带来的内存重新分配次数
- 空间预分配:当我们对SDS进行扩展操作的时候,Redis会为SDS分配好内存,并且根据特定的公式,分配多余的free空间,还有多余的1byte空间(这1byte也是为了存空字符)
- 惰性空间释放:当我们执行完一个字符串缩减的操作,redis并不会马上收回我们的空间,因为可以预防你继续添加的操作,这样可以减少分配空间带来的消耗,但是当你再次操作还是没用到多余空间的时候,Redis也还是会收回对于的空间,防止内存的浪费的。
dict(字典)
- 是哈希键的底层实现
- 字典内部包含两个hashtable
渐进式rehash
- 渐进式 rehash 会在 rehash 的同时,保留新旧两个 hash 结构,查询时会同时查询两个 hash 结构,然后在后续的定时任务以及 hash 操作指令中,循序渐进的把旧字典的内容迁移到新字典中。当搬迁完成了,就会使用新的 hash 结构取而代之。
扩缩容的阈值
- hash 表中 元素的个数等于第一维数组的长度时,就会开始扩容,扩容的新数组是 原数组大小的 2 倍,如果在进行持久化则尽量不去扩容,如果达到了数组长度的五倍,会强制扩容
- **元素个数低于数组长度的 10%**,缩容不会考虑 Redis 是否在做
bgsave
。
跳跃表
- 有序集合的底层实现
发布订阅模式(Pub/Sub)
- PUBLISH channel message
- 推送message到channel
- SUBSCRIBE channel
- 订阅某个channel
redis事务
- Redis的事务是通过MULTI,EXEC,DISCARD和WATCH这四个命令来完成的。
- Redis的单个命令都是原子性的,所以这里确保事务性的对象是命令集合。
- Redis将命令集合序列化并确保处于同一事务的命令集合连续且不被打断的执行
- Redis不支持回滚操作
- 大多数事务失败都是因为语法错误或者类型错误,这两种错误都是开发过程中可以预见的。
- 性能问题
相关语句
- MULIT
- 用于标记事务块的开始,将后续的命令压入FIFO队列中,最终使用EXEC来执行这个队列
- EXEC
- 在一个事务中执行所有先前放入队列的命令,然后恢复正常的连接状态
- DISCARD
- 清除所有先前在一个事务中放入队列的命令,然后恢复正常的连接状态。
- WATCH
- 当某个事务需要按条件执行时,就要使用这个命令将给定的键设置为受监控的状态。
- 通过CAS的乐观锁,当监控数据发生变化,事务不执行
- UNWATCH
- 清除所有先前为一个事务监控的键。
事务失败处理
- redis语法错误(编译器错误)
- 语法错误,所有的执行均不提交
- redis类型错误(运行起错误)
- 不回滚,执行错误语句前的所有语句并提交
key的过期策略
- 定时策略:在设置key的过期时间的同时,为该key创建一个定时器,让定时器在key的过期时间来临时,对key进行删除。
- 优点:保证内存被尽快释放,减少无效的缓存暂用内存。
- 缺点:若过期key很多,删除这些key会占用很多的CPU时间,在CPU时间紧张的情况下,CPU不能把所有的时间用来做要紧的事儿,还需要去花时间删除这些key。定时器的创建耗时,若为每一个设置过期时间的key创建一个定时器(将会有大量的定时器产生),性能影响严重。一般来说,是不会选择该策略模式。
- 惰性策略:key过期的时候不删除,每次从数据库获取key的时候去检查是否过期,若过期,则删除,返回null。
- 优点:删除操作只发生在从数据库取出key的时候发生,而且只删除当前key,所以对CPU时间的占用是比较少的,而且此时的删除是已经到了非做不可的地步
- 缺点:若大量的key在超出超时时间后,很久一段时间内,都没有被获取过,此时的无效缓存是永久暂用在内存中的,那么可能发生内存泄露(无用的垃圾占用了大量的内存)
- 定期策略:每隔一段时间对设置了缓存时间的key进行检测,如果可以已经失效,则从内存中删除,如果未失效,则不作任何处理。
- 优点:通过限制删除操作的时长和频率,来减少删除操作对CPU时间的占用–处理”定时删除”的缺点 定期删除过期key–处理”惰性删除”的缺点。
- 缺点:在内存友好方面,不如”定时删除”,因为是随机遍历一些key,因此存在部分key过期,但遍历key时,没有被遍历到,过期的key仍在内存中。在CPU时间友好方面,不如”惰性删除”,定期删除也会暂用CPU性能消耗。
数据淘汰策略
- 可以设置内存最大使用量,当内存使用量超出时,会实行数据淘汰策略。
- 6 种淘汰策略
策略 描述 volatile-lru 从已设置过期时间的数据集中挑选最近最少使用的数据淘汰 volatile-ttl 从已设置过期时间的数据集中挑选将要过期的数据淘汰 volatile-random 从已设置过期时间的数据集中任意选择数据淘汰 allkeys-lru 从所有数据集中挑选最近最少使用的数据淘汰 allkeys-random 从所有数据集中任意选择数据进行淘汰 noeviction 禁止驱逐数 - 作为内存数据库,出于对性能和内存消耗的考虑,Redis 的淘汰算法实际实现上并非针对所有 key,而是抽样一小部分并且从中选出被淘汰的 key。
- 使用 Redis 缓存数据时,为了提高缓存命中率,需要保证缓存数据都是热点数据。可以将内存最大使用量设置为热点数据占用的内存量,然后启用 allkeys-lru 淘汰策略,将最近最少使用的数据淘汰。
- Redis 4.0 引入了 volatile-lfu 和 allkeys-lfu 淘汰策略,LFU 策略通过统计访问频率,将访问频率最少的键值对淘汰
安装
Linux
- 下载&解压https://redis.io/download
- make
- make PREFIX=/usr/local/redis install 指定路径安装
- 安装失败,安装gcc, yum install gcc ,安装后,要先make disclean
- 安装后,将实例的配置文件移动到启动文件夹
- redis配置文件
- daemonize 后台运行
- maxmemory 设置最大内存
- 使用服务启动
- vim /etc/profile
- export REDIS_PATH=redisLocal
- export PATH=$PATH:$REDIS_PATH/bin
- cd utils
- ./install_server.sh
- 启动:service redis_6379 start
- vim /etc/profile
- /启动 redis-server ./etc/redis.config 指定配置文件启动
- 关闭 redis-cli shutdown
WIN
- win下运行的下载地址:
https://github.com/microsoftarchive/redis/releases/tag/win-3.2.100 - 配置文件:redis.windows.conf
1redis基础
https://x-leonidas.github.io/2024/02/21/05数据库/05-2非关系型数据库/redis/1redis基础/