首页 / REDIS / 开发学习笔记-Redis
开发学习笔记-Redis
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了开发学习笔记-Redis,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含18751字,纯文字阅读大概需要27分钟。
内容图文
![开发学习笔记-Redis](/upload/InfoBanner/zyjiaocheng/868/6307417c23f542b18919416c5276d78e.jpg)
redis中的操作命令
1.redis中有关key的操作命令
查看数据库中所有的key:keys [pattern]
匹配0次或任意次字符
?匹配1次字符
[]匹配[]中的一个字符
keys * 查看数据库中所有的key
keys k 查看数据库中所有以k开头的key
keys k*s 查看数据库中所有以k开头,s结尾的key
keys k[eds]s 查看数据库中所有以k开头,s结尾,中间为[]中任意一个字符的key
判断key是否在数据库中存在: exists key [key…] 如果存在,返回存在的key的数量,如果不存在,返回0
key k1 判断k1是否存在
移动指定key到指定的数据库实例: move key index
move k1 3 将k1移动到3号数据库
查看指定key的剩余生存时间: ttl key
如果key不存在,返回-2
如果key没有设置生存时间,返回-1
ttl k1 查看k1的剩余生存时间
设置key的最大生存时间: expire key seconds
expire k1 3 给k1设置3秒最大生存时间
查看key的数据类型: type key
type k1 查看k1的数据类型
重命名key: rename key newkey
rename k1 k2 将k1改为k2
删除key: del key [key…] 返回实际删除的key的数量
del k1 删除指定的key
2.redis中有关String类型的操作命令 单key - 单value
将string类型的数据保存到redis中: set key value,如果key已经存在,覆盖之前的value
set k1 v1 保存一条键为k1的数据,值为v1
从redis获取字符串类型的数据: get key
get k1 获取键为k1的值
追加字符串: append key value 返回拼接后的字符串长度,若key不存在,相当于set
append k1 value 在k1后面拼接value
获取字符串数据的长度: strlen key
strlen k1 获取键为k1的字符串的长度
将字符串数值进行加1运算: incr key 返回加1运算之后的数据 如果key不存在,设置一个key,初始化值为0,再加1
要求key表示的value必须是数值,否则报错
set age 11 ----- age : 11
incr age age : 12
将字符串数值进行减1运算: decr key 返回减1运算之后的数据 如果key不存在,设置一个key,初始化值为0,再减1
要求key表示的value必须是数值,否则报错
set age 11 ----- age : 11
decr age age : 10
将字符串数值加offset运算: incrby key offset 返回加offset运算之后的数据 如果key不存在,设置一个key,初始化值为0,再加offset
要求key表示的value必须是数值,否则报错
set age 11 ----- age : 11
incrby age 10 --- age : 21
将字符串数值减offset运算: decrby key offset 返回减offset运算之后的数据 如果key不存在,设置一个key,初始化值为0,再减offset
要求key表示的value必须是数值,否则报错
set age 11 ----- age : 11
decrby age 10 --- age : 1
获取字符串的子字符串: getrange key startIndex endIndex
set str abcdefg ------- abcdefg
getrange str 0 3 ------ abcd
用value覆盖从下标为startIndex开始的字符串: setrange key startIndex value
set str abcdeee ------ abcdeee
setrange str 0 eeee -- eeeeeee
设置字符串数据的同时,设置它的最大生命周期: setex key seconds value
setex k1 3 v1 设置k1,值为v1, 生命周期3秒
只有在key不存在的时候,才设置字符串类型的数据: setnx k1 v1
setnx k1 v1
批量设置string类型的数据到数据库中: mset k1 v1 k2 v2 k3 v3 .....
mset k1 v1 k2 v2 k3 v3 设置k1 k2 k3到数据库中
批量获取string类型的数据: mget k1 k2 k3 k4 ....
mget k1 k2 k3 获取k1 k2 k3的数据
批量设置string类型的数据到数据库中,只有当所有key都存在才设置成功: msetnx k1 v1 k2 v2 ....
msetnx k1 v1 k2 v2 设置k1 k2到数据库中,只要有一个key已经存在,则所有的都不设置
3.redis中有关list类型数据的操作命令 单key - 多有序value [插入顺序]
将一个或者多个值依次插入到列表的表头: lpush listName v1 v2 v3 v4..
lpush list1 v1 v2 v3 --- v3 v2 v1
将一个或者多个值依次插入到列表的表尾: rpush listName v1 v2 v3 v4..
lpush list1 v1 v2 v3 --- v3 v2 v1
rpush list1 v4 v5 v6 --- v3 v2 v1 v4 v5 v6
获取指定列表中的元素: lrange lsitName startIndex endIndex
lpush list1 v1 v2 v3 --- v3 v2 v1
rpush list1 v4 v5 v6 --- v3 v2 v1 v4 v5 v6
lrange list1 0 2 --- v3 v2 v1
从指定列表中移除并返回表头元素: lpop listName
lpush list1 v1 v2 v3 --- v3 v2 v1
lpop list1 --- v3
lrange list1 0 -1 --- v2 v1
从指定列表中移除并返回表尾元素: rpop listName
lpush list1 v1 v2 v3 --- v3 v2 v1
rpop list1 --- v1
lrange list1 0 -1 --- v3 v2
获取指令列表中指定下标的元素(不移除): lindex listName index
lpush list1 v1 v2 v3 --- v3 v2 v1
lindex list1 2 --- v1
获取指定列表的长度: llen listName
lpush list1 v1 v2 v3 --- v3 v2 v1
llen list1 --- 3
从指定列表中移除与value相同的数据: lram listName count value
count > 0 : 从左侧移除count个
count < 0 : 从右侧移除-count个
count = 0 : 移除所有
lpush list1 v1 v1 v1 v2 v0 v2 v3 v3 v3 v3
lram list1 2 v1 --- v1 v2 v0 v2 v3 v3 v3 v3
lram list1 -2 v3 --- v1 v2 v0 v2 v3 v3
lram list1 -1 v2 --- v1 v2 v0 v3 v3
截取指定列表中指定区间内的元素组成新的列表,并赋值给key : ltrim key startIndex endIndex
lpush list1 v1 v2 v3 --- v3 v2 v1 [list1]
ltrim list2 0 1 --- v3 v2 [list2]
将指定列表中指定下标的元素设置为指定值: lset listName index value
lpush list1 v1 v2 v3 --- v3 v2 v1
lset list1 1 v0 --- v3 v0 v1
将value插入到指定列表中某元素之前/之后的位置: linsert listName before/after pivot value
lpush list1 v1 v2 v3 --- v3 v2 v1
linsert list1 before v2 v0 --- v3 v0 v2 v1
linsert list1 after v2 v4 --- v3 v0 v2 v4 v1
redis中有关set类型数据的操作命令 单key - 多无序value value不能重复
将一个或多个数据添加到指定的集合中: sadd key v1 v2 v3 ... 如果元素已经存在,忽略元素,返回成功加入的元素的个数
sadd set1 a b c a --- a b c(不一定是这个顺序)
获取指定集合中的所有元素: smembers key
sadd set1 a b c a --- a b c(不一定是这个顺序)
smembers set1 --- b a c
判断指定元素在指定集合中是否存在: sismember key value
sismember key v1 判断key中是否有v1元素
获取指定集合的长度: scard key
sadd set1 a b c a --- a b c(不一定是这个顺序)
scard set1 --- 3
移除指定集合中一个或者多个元素: srem key member [member ...] 返回成功移除的个数
sadd set1 a b c a --- a b c(不一定是这个顺序)
srem set1 b c --- 2
随机获取指定集合中的count个元素(默认为1): srandmember key[count]
count > 0 : 获取不重复的count个
count < 0 : 获取可能重复的count个
sadd set1 a b c a --- a b c(不一定是这个顺序)
srandmember set1 --- a / b / c
随机移除指定集合中count个元素(默认为1) : spop key [count]
sadd set1 a b c a --- a b c(不一定是这个顺序)
spop set1 2 --- a / b / c
将指定集合中的指定元素移动到另一集合: smove source dest member
sadd set1 a b c a --- a b c(不一定是这个顺序)
sadd set2 d e --- d e
smove set1 set2 a --- a d e
求差集 获取第一个集合有,但是其他集合都没有的元素: sdiff key [key key ...]
sadd set1 1 2 3 4 5
sadd set2 2 3 4
sadd set3 4 5
sdiff set1 set2 set3 ----- 1
求交集 获取所有指定集合都有的元素: sinter key [key key ...]
sadd set1 1 2 3 4 5
sadd set2 2 3 4
sadd set3 4 5
sinter set1 set2 set3 ----- 4
求并集 获取所有指定集合中所有元素组: sunion key [key key ...]
sadd set1 1 2 3 4 5
sadd set2 2 3 4
sadd set3 4 5 6
sunion set1 set2 set3 --- 1 2 3 4 5 6
redis中有关hash类型数据的操作命令 单key - field:value
将一个field:value对存到hash表中: hset key filed value 如果已存在,则覆盖
hset stu1 stuName zhangsan
将一个field:value对存到hash表中: hsetnx key field value 如果已存在,放弃添加操作
获取指定hash表中的指定field的值: hget key field
hget stu1 stuName
将一个或多个field:value对存到hash表中: hmset key field value [filed value ...]
hmset stu1 stuName zhangsan stuId 1
获取指定hash表中指定的多个field的值: hmget field [field ...]
hmget stu1 stuName stuId
获取指定hash表中所有的field和value: hgetall key
hgetall stu1
获取指定hash表中所有的field: hkeys key
hkeys stu1
获取指定hash表中所有的value: hvals key
hvals stu1
从指定hash表中删除一个或多个field: hdel key field [field ...]
hdel stu1 stuName
获取指定hash表中所有field的个数: hlen key
hlen stu1
判断指定hash表中是否存在指定的field: hexists key field 存在返回1 不存在返回0
hexists stu1 stuName
对指定hash表中指定的field值进行整数加法运算: hincrby key field int
hincrby stu1 stuId 5 对stu1中stuId加5
对指定hash表中指定的field值进行浮点数加法运算: hincrbyfloat key field float
hincrbyfloat stu1 score 0.5 对stu1中score加0.5
redis中有关zset类型数据的操作命令: 有序集合 给每个元素关联一个分数,按分数决定顺序,每个元素都有下标,如果元素存在,覆盖score
将一个或者多个member及其score加入有序集合: zadd key score member [score member ...]
zadd zset1 10 z1 20 z2 12 z3
获取指定有序集合中指定下标区间的元素: zrange key startIndex endIndex [withscores]
zrange zset1 0 -1 withscores
获取指定有序集合中指定分数区间的元素: zrangebyscore key min max [withscores]
zrangebyscore zset1 10 15 withscores
获取指定有序集合中指定分数区间内的元素个数: zcount key min max
zcount zset1 10 15
删除指定有序集合一个或多个元素: zrem key member [member ...]
zrem zset1 z1 z2
获取指定有序集合中所有元素的个数: zcard key
zcard zset1
获取指定有序集合中指定元素的排名: zrank key member 从0开始
zrank zset1 z3
获取指定有序集合中指定元素的分数: zscore key member
zscore zset1 z3
获取指定有序集合中指定元素的排名(反向): zrevrank key member
zrevrank zset1 z1
redis的配置文件: 在redis根目录下提供redis.conf配置分拣
可以配置一些redis服务端运行时的一些参数
如果不适用配置文件,redis按照默认参数运行
如果使用配置文件,在启动redis服务时必须指定所使用的配置文件
redis配置文件中关于网络的配置:
port: 指定redis服务所使用的端口,默认使用6379
bind: 指定客户端连接redis服务时使用的ip地址,默认可以使用redis所在主机上的任何一个ip都可以
一般情况下,都会配置一个ip,而且通常是一个真实ip
如果配置了port和bind,则客户端连接redis服务时,必须指定端口和ip:
redis-cli -h ip -p port
redis-cli -h ip -p port shutdown
tcp-keepalive: 连接保活策略。
redis常规配置:
loglevel: 配置日志级别
logfile: 指定日志文件,redis在运行过程中会输出一些日志信息,默认情况下,这些日志信息会输出到控制台,
我们可以使用logfile配置日志文件,使redis把日志信息输出到指定文件。
databases: 配置数据库的数量
resid安全配置:
requirepass: 设置访问redis服务时所使用的密码,默认不使用
此参数必须在protected-mode=yes时才起作用
一旦设置了密码验证,客户端连接redis服务时,必须使用密码连接 redis-cli -h ip -p port -a pwd
redis的持久化: redis提供持久化策略,在适当的时机采用适当手段把内存中的数据持久化到磁盘中,每次redis服务启动时
都可以把磁盘上的数据再次加载到内存中使用。
1. RDB策略: 在指定时间间隔内,redis服务执行指定次数的写操作会自动触发一次持久化操作
RDB策略是redis默认的持久化策略,redis服务开启时这种持久化策略就默认开启了
save : 配置持久化策略
dbfilename: redis RDB持久化存储的文件
dir: redis持久化文件所在的目录
2. AOF策略: 采用操作日志来记录进行每一次写操作,每次redis服务启动时,都会重新执行一遍操作日志中的指令。
效率低,redis默认不开启AOF功能
小结:根据数据的特点来决定开启哪种持久化策略,一般情况下开启RDB策略足够了。
redis的事务:
事务: 把一组数据库操作放在一起执行,保证操作的原子性,要么同时成功,要么同时失败
redis的事务: 允许把一组redis命令放在一起执行,把命令进行序列化(依次执行),然后一起执行,保证部分原子性
multi: 用来标记一个事务的开始
exec: 执行事务队列中所有的命令
discard: 清除所有已经压入队列中的命令并结束整个事务
watch: 监控某一个键,当事务在执行过程中,此键代码的值发生变化,则本事务放弃执行,否则正常
unwatch: 放弃监控所有键
redis的事务只能保证部分原子性:
如果一组命令中,有在压入事务队列过程中发生错误的命令,则本事务中所有的命令都不执行,保证事务的原子性
如果一组命令中,在压入队列过程中正常,但是在执行事务队列命令时发生了错误,则只会影响发生错误的命令,
不会影响其他命令的执行,不能保证事务的原子性
redis消息的发布与订阅:
redis客户端订阅频道,消息的发布者往频道上发布消息,所有订阅此频道的客户端都能接收到消息
subscribe: 订阅一个或者多个频道的消息
subscribe ch1 ch2 ch3…
publish: 将消息发布到指定频道
publish ch1 message
psubscribe: 订阅一个或者多个频道的消息,频道名支持通配符
psubscribe ch*
redis的主从复制: 主库-从库 : 主少从多,主写从读,读写分离,主写同步复制到从,从机也可以有从机
主从复制缺点: 增加延迟时间,从机数量越多,越延迟
搭建一主二从的redis集群:
搭建三台redis服务: 使用一个redis模拟三台redis服务
提供三分redis配置文件 redis6379.conf redis6380.conf redis6381.conf
修改三分配置文件,以6379为例:
bind 127.0.0.1
port 6379
pidfile /var/run/redis_6379.pid
logfile “6379.log”
dbfilename dump6379.rdb
分别使用三个配置文件,启动三台redis服务
查看三台redis服务在集群中的主从角色:
info replication : master-主机 slave-从机
设置主从关系: 主机不用设置,默认就是主机
在6380 6381上执行: slaveof 127.0.0.1 6379
全量复制: 一旦主从关系确定,会自动把主机上已有的数据同步复制到从库
增量复制: 主库修改数据,会自动同步到从库
主机宕机: 从机原地待命,依然可以读
主机恢复: 一切恢复正常
从机宕机: 主机少一个从机,其他从机不变
从机恢复: 从机变成主机,需要重新设置主从关系
从机上位: 主机宕机且短时间无法恢复, 选一个从机变为主机
1.从机断开原来的主从关系
slaveof no one
2.重新设置主从关系
3.之前的主机恢复后,不再拥有从机,需要重新设置主从关系
redis的哨兵模式: 主机宕机后自动挑选从机上位
提供哨兵配置文件: 在redis安装目录下创建配置文件 redis_sentinel.conf
配置文件中: sentinel monitor dc-redis ip port num (num: 根据某规则对从机进行投票,一旦达到num票,则上位)
启动哨兵服务: redis-sentinel redis_sentinel.conf
之前主机恢复: 自动从属于新的主机
Jedis: 通过java访问redis,进行操作
连接redis: Jedis jedis = new Jedis(ip, port);
jedis相当于一个客户端,通过jedis的方法进行操作
缓存雪崩:
原有缓存大量失效,新缓存未到,原本应该访问缓存的请求都去查询数据库,对数据库和cpu造成巨大压力,严重的会造成数据库
宕机,形成一系列连锁反应,造成系统崩溃。
解决方法: 给缓存中数据设置不同的过期时间,避免再某一时刻大量数据同时过期
缓存穿透:
用户查询的数据在数据库中没有,缓存中显然也没有,但是这种查询需要查一遍缓存再查一遍数据库,缓存命中率低,造成资源浪费
解决方法:布隆过滤器:采用bitmap和多个hash函数来判断请求的某个数据是否存在,将所有可能存在的数据存到一个足够大的
bitmap中,将所有一定不存在的数据过滤掉,只有通过了所有的hash函数的判断,才能判断该数据可能存在
缓存击穿:
某个热点数据在缓存中不断的被大量并发访问,在这个数据失效的瞬间,会有许多并发的访问转而请求数据库,造成cpu压力
解决方法:设置一个短期key来锁住对当前数据的访问,访问结束再删除 / 设置热点数据不过期
缓存预热:
系统上线后,将相关缓存数据加载到缓存系统
缓存更新:
过期缓存清理:
定时清理过期缓存
定时删除+懒惰删除 :定时随机抽查是否过期,在访问时如果发现过期,则删除
缓存更新:
1.volatile-lru 从已设置过期时间的数据中挑选最近最少使用的数据淘汰
2.volatile-ttl 从已设置过期时间的数据中挑选将要过期的淘汰
3.volatile-random 从已设置过期时间的数据中随机挑选一个淘汰
4.allkeys-lru 从所有数据中挑选最近最少使用的数据淘汰
5.allkeys-random 从所有数据中随机挑选一个淘汰
6.no-enviction 不主动淘汰数据,当缓存满时进行写操作会报错
缓存降级:
不理解!
redis和memcache的区别:
redis支持五种数据结构:string set zset hash list, 而memcache只支持string
redis能存放512M的value,memcache只能存放1M
redis提供持久化策略,memcache不能持久化
redis支持主从模式
redis速度快于memcache
redis速度快的原因:
1.单线程,避免上下文切换
2.采用IO多路复用机制(处理大量客户端的访问请求, IO多路复用:select epoll等)
3.纯内存操作(内存访问速度不是限制redis效率的瓶颈,因此可以使用单线程)
redis为什么是单线程的
redis是基于内存的操作,cpu不是redis的瓶颈, 单线程不会影响redis的速度
采用单线程,避免了不必要的上下文切换和竞争条件
redis的瓶颈在于内存大小、网络带宽
redis利用队列技术将并发访问变为串行访问
Redis rdbsave
SAVE:
SAVE是同步RDB持久化方式,在进行SAVE的时候Redis不能接收客户端请求
BGSAVE:
BGSAVE是异步RDB持久化方式,在进行BGSAVE的时候Redis可以接收客户端请求,一边持久化,一遍提供读写服务
BGSAVE的原理是fork()+copy on write
fork()即创建一个子 进程,该子进程共享父进程的数据,且子进程和父进程对共享数据的修改互相不可见,互不影响,子进程做持久化工作,父进程对外提供读写服务
但要做到互相不可见,不可能是将数据复制了一份,否则需要Redis给RDB专门留出一半的空间才行,Redis使用copy on write来解决这个问题
copy on write:子进程和父进程共享同一块内存区域,如果父进程没有执行写操作,则子进程正常执行持久化工作,如果父进程修改了共享内存中的数据,则Redis在
修改前将更改数据的数据页拷贝一份,修改数据,主进程指向新的数据页,子进程指向原有数据页进行持久化工作。
BGSAVE执行前先判断是否由子进程已经存在,如果存在则放弃本次持久化操作,如果不存在则fork子进程进行持久化操作
Redis五种数据类型及底层实现
五种数据类型即五种数据对象,redis数据对象的基本格式中,type字段来表示对象的类型,encoding字段来表示底层使用那种数据结构实现,prt指向底层的数据结构
1.String
1.如果字符串保存的是整数值,并且可以用long类型来表示,则直接保存在redisObject的ptr中,即ptr直接指向这个long类型的数值
2.如果字符串保存小于32字节的字符串值,则采用embstr编码,使用简单动态字符串(SDS)结构,ptr指向sdshdr,即SDS所在的位置,在embstr编码下,内存分配一次,分配一块连续的内存空间。
3.如果字符串保存大于32字节的字符串值,则采用raw编码,使用简单动态字符串(SDS)结构,ptr指向sdshdr,与embstr不同的是,raw编码下的内存分配两次,sdshdr的位置和redisObject位置不连续。
总结:
1.redis中,浮点数类型是转换为字符串在进行存储的(long类型范围内的整数直接用long类型存储)
2.raw和embstr编码效果相同,只有内存的分配与释放不同,raw两次,embstr一次
3.embstr内存块连续,能更好的使用缓存带来的优势
4.int编码和embstr编码如果做追加字符串等操作,满足条件下会被转换为raw编码
5.embstr编码是只读的,不能修改,如果要修改需要先转换为raw编码
2.list
1.ziplist
ziplist编码底层实现是压缩列表,压缩列表里每个节点保存一个元素
2.linkedlist
linkedlist编码底层实现是双端列表,每个节点保存一个字符串对象,每个字符串对象内保存一个列表元素
总结:
1.使用ziplist需要满足两个条件:所有字符串长度都小于64字节,元素数量小于512,否则使用linkedlist编码
3.hash
1.ziplist
ziplist编码的hash对象底层实现是压缩列表,在ziplist编码的hash对象中,key-value键值对是紧密相连的放入压缩链表的,先放key,再放value,总是向表尾添加键值对。
2.hashtable
hashtable编码的hash对象底层实现是字典,hash对象中的每个键值对都用一个字典键值对来保存
字典的键和值都是字符串对象
总结:
1.hash对象使用ziplist编码需要满足两个条件,所有键和值的字符串长度小于64字节,键值对数量小于512,否则使用hashtable编码
4.set
1.intset
intset编码的底层实现是整数集合,所有元素保存在整数集合中
2.hashtable
hashtable编码的底层实现对象是字典,字典的每个键是一个字符串对象,保存一个集合元素,值为null
总结:
1.集合对象使用inset编码需要满足两个条件:所有元素都是整数值,元素个数小于512个
5.zset
1.ziplist
ziplist编码的有序集合对象的底层实现是压缩列表,与hash中的类似,key的位置保存集合元素,value的位置保存元素的分值,分值小的靠近表头,分值大的靠近表尾
2.skiplist
skiplist编码的有序集合对象的底层实现是跳跃表/字典
跳表每个节点都保存一个元素集合,并按从小到大排列,节点object属性存放集合元素,score属性存放分值
字典每个键值对保存一个集合元素,字典的键保存元素的成员,值保存分值
总结:
1.有序集合对象使用ziplist编码需要满足两个条件,所有元素长度不超过64,元素个数小于128个
2.为何skiplist要同时使用跳跃表和字典?
跳跃表的优点是有序,但查询分值复杂度为O(logn),字典虽然无序,但查询分值复杂度是O(1)
虽然同时采用两个结构,但通过指针指向同一块内存地址,所以不会浪费内存
跳表用于查询一个区间内的值,可以在O(logn)时间内快速查找
字典用于查询某个值,O(1)时间内快速查找
3.跳表的优点:比起AVL,实现简单
内存占用的大小可由用户控制
可以更方便的支持对某个范围数据的查找
跳表查找时间复杂度O(logn), 插入时间复杂度O(logn)
(跳表有点像多级索引)
压缩列表ziplist
压缩列表类似数组,但又比数组更加节省内存,因为数组中的每一个元素占用的内存空间都是固定的,而压缩列表不固定,元素只占用所需要的内存空间
压缩列表格式
zlbytes zltail zllen [entry1 entry2 entry3…] zlend
zlbytes 记录压缩列表占用的内存字节数:在对压缩列表重新分配内或计算zlend位置时使用
zltail 记录压缩列表表尾节点距离压缩列表起始位置的字节数,无需遍历整个压缩列表就可找到表尾节点
zllen 记录压缩列表包含的节点数量
zlend 标记压缩列表的末端
entry的格式
previous_entry_length encoding content
previous_entry_length 记录上一个节点的长度
encoding 记录当前节点所保存的数据类型和长度
content 当前节点保存的数据
内容总结
以上是互联网集市为您收集整理的开发学习笔记-Redis全部内容,希望文章能够帮你解决开发学习笔记-Redis所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。