当前位置: 首页 > news >正文

Redis-string

String字符串

字符串类型是redis最基础的数据类型,redis中所有的键的类型都是字符类型,而且其它几种数据结构都是在字符类型基础上,redis字符类型可以存储普通字符串,数字,JSON,XML格式字符串,二进制流数据,redis字符串最大值不能超过512MB。

redis内部存储字符是按照二进制流形式保存的,则redis就不用处理字符集编码问题,从客服端传入的命令是使用扫描的字符集编码,那么就存储扫描字符集编码。

常见命令

set命令

将string类型的value设置到key中,key之前存在就会覆盖掉,时间复杂度为O(1)。

SET key value [expiration EX seconds|PX milliseconds] [NX|XX]

EX后面是设置key的过期时间,单位是秒,PX则单位是毫秒,NX则是key不存在时允许设置,存在就不允许设置,XX则相反,存在才可以设置,不存在就不执行。

示例

redis> EXISTS mykey
(integer) 0
redis> SET mykey "Hello"
OK
redis> GET mykey
"Hello"
redis> SET mykey "World" NX
(nil)
redis> DEL mykey
(integer) 1
redis> EXISTS mykey
(integer) 0
redis> SET mykey "World" XX
(nil)
redis> GET mykey
(nil)
redis> SET mykey "World" NX
OK
redis> GET mykey
"World"
redis> SET mykey "Will expire in 10s" EX 10
OK
redis> GET mykey
"Will expire in 10s"
redis> GET mykey # 10秒之后
(nil)

清楚redis上的所有数据

FLUSHALL

GET命令

获取key对应的value,如果key不存在就返回nil。value类型不是string也会报错,仅支持字符串类型。

示例

127.0.0.1:6379> lpush key3 11 22 33 
(integer) 3
127.0.0.1:6379> get key3
(error) WRONGTYPE Operation against a key holding the wrong kind of value
127.0.0.1:6379> type key3
list

MGET命令

一次性获取多个key值,如果key不存在或者对应的数据类型不是string,也会后返回nil。

示例

127.0.0.1:6379> mset key1 111 key2 222 key3 333
OK
127.0.0.1:6379> mget key1 key2 key3
1) "111"
2) "222"
3) "333"
127.0.0.1:6379> mget key1 key2 key4
1) "111"
2) "222"
3) (nil)
127.0.0.1:6379> 

MSET命令

一次性设置多个key值,时间复杂度是O(N),这里的N是命令行中key的数量。

示例

127.0.0.1:6379> mset key1 111 key2 222 key3 333
OK
127.0.0.1:6379> mget key1 key2 key3
1) "111"
2) "222"
3) "333"
127.0.0.1:6379> mget key1 key2 key4
1) "111"
2) "222"
3) (nil)
127.0.0.1:6379> 

使用mget比get高效,get需要多次进行网络传输,而mget只用一次就可以。批量操作对于业务来说是有好处的,但也不能盲目,每次批量存在的数量也不能太多,不然,大体积的批量操作可能被记录为慢查询(默认超过10ms),redis就会阻塞住。

SETNX/SETEX/PSETEX命令

setnx:key不存在可以设置,存在就会失败

setex:设置key时,可以增加过期时间,单位为秒

psetex:设置key,可以增加过期时间,单位为毫秒

与前面的set,这里就像是set和NX,EX和为一体。

127.0.0.1:6379> setnx key1 111
(integer) 1
127.0.0.1:6379> get key1
"111"
127.0.0.1:6379> setnx key1 121
(integer) 0
127.0.0.1:6379> get key1
"111"

127.0.0.1:6379> setex key2 10 222
OK
127.0.0.1:6379> ttl key2
(integer) 5
127.0.0.1:6379> ttl key2
(integer) -2
127.0.0.1:6379> get key2
(nil)
127.0.0.1:6379> 

127.0.0.1:6379> psetex key3 5000 333
OK
127.0.0.1:6379> pttl key3
(integer) 1829
127.0.0.1:6379> pttl key3
(integer) -2
127.0.0.1:6379> get key3
(nil)
127.0.0.1:6379> 

计数指令

INCR命令

将key对应的string值进行加1,key要是不存在,就会默认为0并加1,如果超过64位有符号整型就报错,对应的不是整数也报错。

示例

127.0.0.1:6379> set key 10
OK
127.0.0.1:6379> incr key
(integer) 11
127.0.0.1:6379> get key
"11"
127.0.0.1:6379> set key2 hello
OK
127.0.0.1:6379> incr key2
(error) ERR value is not an integer or out of range
127.0.0.1:6379> set key2 1.5
OK
127.0.0.1:6379> incr key2
(error) ERR value is not an integer or out of range
127.0.0.1:6379> set key2 22222222222222222222222222222222222222222222222222222222222222222222
OK
127.0.0.1:6379> incr key2
(error) ERR value is not an integer or out of range

127.0.0.1:6379> get key3
(nil)
127.0.0.1:6379> incr key3
(integer) 1

INCRBY命令

将key对应的string表示的数字加上设置的值,值可以为负数,key不存在就默认为0,key的值需要是整数,加上值不能超过64位有符号整数。

示例

redis> EXISTS mykey
(integer) 0
redis> INCRBY mykey 3
(integer) 3
redis> SET mykey "10"
"OK"
redis> INCRBY mykey 3
(integer) 13
redis> INCRBY mykey "not a number"
(error) ERR value is not an integer or out of range
redis> SET mykey "234293482390480948029348230948"
"OK"
redis> INCRBY mykey 3
(error) value is not an integer or out of range
redis> SET mykey 'not a number'
"OK"
redis> INCRBY mykey 3
(error) value is not an integer or out of range

DECR指令

将key对应的string值减少1,限制与之前一样。

redis> EXISTS mykey
(integer) 0
redis> DECR mykey
(integer) -1
redis> SET mykey "10"
"OK"
redis> DECR mykey
(integer) 9
redis> SET mykey "234293482390480948029348230948"
"OK"
redis> DECR mykey
(error) value is not an integer or out of range
redis> SET mykey 'not a number'
"OK"
redis> DECR mykey
(error) value is not an integer or out of range

DECRBY命令

key对应的value减去一个设置的值,限制与之前一样。

redis> EXISTS mykey
(integer) 0
redis> DECRBY mykey 3
(integer) -3
redis> SET mykey "10"
"OK"
redis> DECRBY mykey 3
(integer) 7
redis> DECRBY mykey "not a number"
(error) ERR value is not an integer or out of range
redis> SET mykey "234293482390480948029348230948"
"OK"
redis> DECRBY mykey 3
(error) value is not an integer or out of range
redis> SET mykey 'not a number'
"OK"
redis> DECRBY mykey 3
(error) value is not an integer or out of range

INCRBYFLOAT命令

将key对应的string加上一个浮点数的值,值为负数就是减去。

示例

redis> SET mykey 10.50
"OK"
redis> INCRBYFLOAT mykey 0.1
"10.6"
redis> INCRBYFLOAT mykey -5
"5.6"
redis> SET mykey 5.0e3
"OK"
redis> INCRBYFLOAT mykey 2.0e2
"5200"

很多存储线和编程语言内部都使用CAS机制实现计数功能,redis则不需要,因为是单线程。

def cas_counter(shared_value, expected, new_value):
if shared_value == expected:  # 比较
shared_value = new_value  # 交换
return True
return False

多线程还是会有先后顺序只不过不知道谁快

假设你和室友共用冰箱里的最后一瓶可乐:

  1. ​你查看冰箱​​,看到还有1瓶(此时shared_value = 1

  2. ​你的预期​​:拿饮料前冰箱应该仍有1瓶(expected = 1

  3. ​你的操作​​:如果确实是1瓶,你拿走它(设为new_value = 0

  • ​宏观上(用户感知)​​:多个线程"同时"在运行(如音乐播放+下载文件)

  • ​微观上(CPU实际执行)​​:单核CPU在任何时刻​​只能执行一个线程的指令​

其它命令

针对字符串的命令,如拼接,修改,获取字符串长度等。

APPEND命令

如果key存在且为字符串,将value追加到字符串的尾巴,不存加就是set命令,创建一个键值对。

redis> EXISTS mykey
(integer) 0
redis> APPEND mykey "Hello"
(integer) 5
redis> GET mykey
"Hello"
redis> APPEND mykey " World"
(integer) 11
redis> GET mykey
"Hello World"

GETRANGE命令

跟C++中的std::string的substr一样作用。根据start和end的值来框选一个范围,这个范围是左闭右闭区间,就会把value的在这个区间的字符返回。这里可以为负数,负数就是倒数的意思,下标从0开始。如果是汉字进行切分可能有问题,因为汉字的在utf8上面不知道是什么。

redis> SET mykey "This is a string"
"OK"
redis> GETRANGE mykey 0 3
"This"
redis> GETRANGE mykey -3 -1
"ing"
redis> GETRANGE mykey 0 -1
"This is a string"
redis> GETRANGE mykey 10 100
"string"

SETRANGE命令

指定偏移量,从这个偏移量开始进行覆盖用value,返回值是替换后字符串的长度,长度的单位是字节,不是字符。

redis> SET key1 "Hello World"
"OK"
redis> SETRANGE key1 6 "Redis"
(integer) 11
redis> GET key1
"Hello Redis"

STRLEN命令

获取字符串长度,key不存在返回0。

redis> SET mykey "Hello world"
"OK"
redis> STRLEN mykey
(integer) 11
redis> STRLEN nonexisting
(integer) 0

补充:MySQL 中的varchar(N),此处的N单位是字符。

内部编码

字符串类型有三种内部编码,可以使用OBJECT encoding key查看

1.int(八字节长整型)

2.embstr(<=39字节字符串)

3.raw(>39字节的字符串)

上面的39是现在的,不一定以后也是,具体的值要看业务是什么,这里的值可以在配置文件修改的。

典型使用场景

缓存功能:redis作为缓冲层,MySQL作为存储层,绝大部分请求的数据都是从redis中获取。

示例

1.业务通过uid获取用户信息

UserInfo getUserInfo(long uid) {

}

2.BAM获取用户信息,将用户信息保存到user:info:<uid>对应的键中

// 根据 uid 得到 Redis HR
String key = "user:info:" + uid;

RWNE

// 尝试从 Redis 中获取对应的值
String value = Redis 执行命令: get key;


// 如果缓存命中 (hit)
if (value != null) {
// 假设我们的用户信息按照 JSON 格式存储
UserInfo userInfo = JSON 反序列化(value);
return userInfo;
}

3.没用从redis获取到用户信息,就是缓存miss,就会从MySQL中获取对应的信息

// 如果缓存未命中 (miss)
if (value == null) {
// 从数据库中,根据 uid 获取用户信息
UserInfo userInfo = MySQL 执行 SQL: select * from user_info where uid = <uid>

// 如果表中没有 uid 对应的用户信息
if (userInfo == null) {
响应 404
return null;
}
// 将用户信息序列化成 JSON 格式
String value = JSON 序列化(userInfo);

// 写入缓存,为了防止数据腐烂 (rot) ,设置过期时间为 1 小时 (3600s)
Redis 执行命令; set key value ex 3600

// 返回用户信息
return userInfo;
}

需要注意,随着时间推移,有越来越多的key在redis访问不到,就会从MySQL中读取写入到redis中,redis的数据会越来越多吗?

这里是不会的,因为写入redis同时会设置过期时间。

计数功能

许多应用都是u使用redis作为计数的基础工具,可以实现快速计数,查询缓存功能,同时数据可以异步处理给其它数据源。

记录视频播放次数

在视频网站中,用户播放视频,系统就会执行redis命令如INCR来异步增加视频的播放计数,这里异步处理的好吃有几个。

第一,允许网站快速响应用户操作,不需要等待数据库更新,第二,减轻了数据库的即使写入压力,播放计数可以在redis中累计,接着在批量同步到数据库,就可以提高系统的性能和稳定性。

// 在 Redis 中统计某视频的播放次数
long incrVideoCounter(long vid) {
key = "video:" + vid;
long count = Redis 执行命令: incr key
return counter;
}

共享会话(Session)

一个Web服务将用户的Session信息如登录信息保存到各自的服务器上,分布式服务会把用户请求均衡到不同的服务器上,但是不能保证用户每一次都到之前的服务器上,用户刷新一次就要重新登录,就降低了用户体验感。

每一个服务器都要维护自己的会话数据,但是相互之间不共享,用户请求访问到不同的服务器上就还是不行。所以使用redis将用户的session信息集中管理,这样用户被分配到哪一个服务器上都可以到redis中获取用户的数据。

Cookie是属于浏览器存储数据的机制,session是服务器存储数据的机制,一般是按照键值对方式存储数据。

1

2

手机验证码

手机验证码可以在一些方面提高安全性,但是也不可以一直申请短信,会对服务器有开销,如果大量的重复申请。实习中理解业务是重要的,业务清楚再到技术

示例

String 发送验证码(phoneNumber) {
key = "shortMsg:Limit:" + phoneNumber;
// 设置过期时间为 1 分钟 (60s)
// 使用 NX,只在不存在 key 时才能设置成功
bool r = Redis 执行命令; set key 1 ex 60 nx
if (r == false) {
// 说明之前设置过该手机的验证码了
long c = Redis 执行命令: incr key
if (c>5) {
// 说明超过了一分钟 5 次的限制了
// 限制发送
return null;
}
}// 说明要么之前没有设置过手机的验证码; 要么次数没有超过 5 次
String validationCode = 生成随机的 6 位数的验证码() ;
validationKey = "validation:" + phoneNumber;
// 验证码 5 分钟 (300 秒) 内有效
Redis 执行命令; set validationKey validationCode ex 300;// 返回验证码,随后通过手机短信发送给用户
return validationCode ;
}// 验证用户输入的验证码是否正确
bool 验证验证码 (phoneNumber,validationCode) {
validationKey = "validation:" + phoneNumber;String value = Redis 执行命令: get validationkey;
if (value == null) {
// 说明没有这个手机的验证码记录,验证失败
return false;
}if (value == validationCode) {
return true;
} else {
return false;
}
}

http://www.dtcms.com/a/467212.html

相关文章:

  • 网站网页的收录数量赤峰建设厅官方网站
  • 做灯箱的网站wordpress nginx apache
  • (7)100天python从入门到拿捏《迭代器和生成器》
  • 花卉网站建设策划书核酸二维码
  • 00--VSCode配置
  • 光明区建设局网站抖音代运营成功案例
  • 宁波论坛建站模板珠海市建设工程信息网
  • 温州做网站价格外贸推广软件
  • 自己建的网站也要注册域名吗电子商务网站建设与维护试卷答案
  • Java项目:基于SSM框架实现的连锁干洗店管理系统(ssm+B/S架构+源码+数据库+毕业论文)
  • 国外装饰公司网站郑州网站seo厂家
  • 如何建立免费个人网站盘龙区网站建设外包
  • 供热设施网站搭建教程品牌推广名词解释
  • 算法社Python基础入门面试题库(新手版·含答案)
  • 网站建设与管理 自考wordpress邮箱社交
  • Day59 SPI驱动与ADXL345传感器应用及Linux系统移植基础
  • 做网站有限公司外贸企业有哪些公司
  • 设计师接私活的网站深圳装修设计培训
  • 数据密度与视觉层次:让信息既丰富又不乱
  • 银川市网站制作公司邢台网站建设基本流程
  • 浏览器解析HTML完整教程
  • dns加网站家具网站建设策划
  • 备案网站制作汽车租赁网站设计
  • 网站服务器设置地点elision豪华级创意企业wordpress
  • 济南网站建设(力推聚搜网络)海外网络推广
  • 合肥网站建设佳蓝网络网站建设培训深圳
  • 建设网站的申请信用卡吗网站头部导航样式
  • 网站建设及优化 赣icp公司网站建设合同电子版
  • 做阿里巴巴类似的网站天津西青区怎么样
  • 个人网站建设赚取流量费wordpress网站多层循环调用文章