标签:second 哈希表 对象类型 倒序 活跃 @param 一个用户 dom 系统
Redis 命令用于在 Redis 服务上执行操作。要在 Redis 服务上执行命令需要一个 Redis 客户端。Redis 客户端在我们之前下载的的 Redis 的安装包中。
Redis 主要支持五种数据类型:string
(字符串),hash
(哈希),list
(列表),set
(集合)及 zset
(sorted set:有序集合)
# 返回满足的所有键,可以模糊匹配比如 keys abc* 代表 abc 开头的 key
keys *
# 返回 key 所储存的值的类型
type key
# 是否存在指定的 key,存在返回 1,不存在返回 0
exists key
# 删除某个 key
del key
# 设置某个 key 的过期时间 单位为秒
expire key second
# 查看剩余时间
## ttl:time to live
## 当 key 不存在时,返回 -2
## 存在但没有设置剩余生存时间时,返回-1
## 否则,以秒为单位,返回 key 的剩余时间
ttl key
# 查看剩余时间,以毫秒为单位
pttl key
# 移除 key 的过期时间
persist key
# 修改key的过期时间,单位为毫秒
pexpire key mi11seconds
# 选择数据库
## 数据库为 0-15(默认一共 16 个数据库)设计成多个数据库实际上是为了数据库安全和备份
select index
# 将当前数据中的 key 转移到其他数据库
move key dbindex
# 随机返回一个 key
randomkey
# 重命名 key
rename key key2
# 打印命令
echo
# 查看数据库的 key 数量
dbsize
# 查看数据库信息
info
# 实时传储收到的请求,返回相关的配置
config get *
# 清空当前数据库
flushdb
# 清空所有数据库
flusha11
EXPIRE key seconds
exists key
Redis 单个 key 允许存入 512M 大小
非关系型数据库:数据与数据之间没有关联关系,需要通过 key 的名称风格来归类数据。
Redis 提供多种数据类型:
string 类型是 Redis 最基本的数据类型,一个键最大能存储 512MB。
string 数据结构是简单的 key-value类型,value 不仅可以是 string,也可以是数字,是包含很多种类型的特殊类型。
string 类型是二进制安全的。意思是 Redis 的 string 可以包含任何数据,比如序列化的对象进行存储,比如一张图片进行二进制存储,比如一个简单的字符串、数值等等
################### 赋值语法 ##########################
# SET
## 多次设置name会覆盖
## Redis SET 命令用于设置给定 key 的值。如果 key 已经存储值,SET 就覆写旧值,且无视类型
SET KEY VALUE
# SETNX
## 如果 key 不存在,则设值并返回1,如果 key 存在,则不设值并返回0;
## 解决分布式锁方案之一,只有在 key 不存在时设置 key 的值。
## setnx(SET if Not exists)命令在指定的key不存在时,为key设置指定的值
SETNX key value
# SETEX
## 设置 key 的值,并设置过期时间,单位为秒,过期时间后 key 被清除
SETEX key seconds value
# SETRANGE
## 替换字符串
SETRANGE string range value
################### 取值语法 ##########################
# GET
## Redis GET 命令用于获取指定 key 的值
## 如果 key 不存在,返回 ni1。如果 key 储存的值不是字符串类型,返回一个错误。
GET KEY
# GETRANGE
## 用于获取存储在指定 key 中字符串的子字符串。字符串的截取范围由 start 和 end 两个偏移量决定(包括 start 和 end 在内)
GETRANGE key start end
# GETBIT
## 对 key 所储存的字符串值,获取指定偏移量上的位(bit)
GETBIT key offset
# GETSET
## Getset 命合用于设置指定 key 的值,并返回 key 的旧值,当key不存在时,返回ni1
GETSET KEY VALUE
# STRLEN
## 返回 key 所储存的字符串值的长度值
STRLEN key
################### 其他语法 ##########################
# DELKEY
## 删除指定的 KEY,如果存在,返回值数字类型。
DELKEY key
# MSET
## 批量写
## 一次性写入多个值
MSET k1 v1 k2 v2 ...
# MGET
## 批量读
MGET k1 k2 k3 ...
# INCR
## 自增
## 将 key 中存储的数字值增 1。如果 key 保存在,那么 key 的值被初始化为 0,然后执行 INCR 操作。
## key 对应的 value 必须是数字
INCR KEY
## 指定增量
INCRBY KEY INCREMENT
# DECR
## 自减
## 将 key 中存储的数字减 1
## key 对应的 value 必须是数字
DECR KEY
## 指定减量
DECRBY KEY DECREMENT
# APPEND
## 字符串拼接
## 为指定的 key 追加至末尾,如果不存在,为其赋值
APPEND KEY VALUE
string 通常用于保存单个字符串或 JSON 字符串数据
因 string 是二进制安全的,所以你完全可以把一个图片文件的内容作为字符串来存储
计数器(常规 key-value 缓存应用。常规计数:微博数,粉丝数)
INCR 等指令本身就具有原子操作的特性,所以我们完全可以利用 Redis 的 INCR、 INCRBY、DECR、 DECRBY 等指令来实现原子计数的效果。假如,在某种场景下有 3 个客户端同时读取了 mynum 的值(值为2),然后对其同时进行了加 1 的操作,那么,最后 mynum 的值一定是 5。
不少网站都利用 Redis 的这个特性来实现业务上的统计计数需求。
hash 类型是 string 类型的 field 和 value 的映射表,或者说是一个 string 集合。hash 特别适合用于存储对象,相比较而言,将一个对象类型存储在 hash 类型要存储在 string 类型里占用更少的内存空间,并对整个对象的存取可以看成具有 KEY 和 VALUE 的 MAP 容器,该类型非常适合于存储值对象的信息,如:uname,upass,age等。该类型的数据仅占用很少的磁盘空间(相比于 JSON)。
Redis 中每个 hash 可以存储(2 的 32 次方减 1)个键值对(40多亿)
################### 赋值语法 ####################
# HSET
## 为指定的KEY,设定 FIELD/VALUE
HSET KEY FIELD VALUE
# HMSET
## 同时将多个 field-value(域-值)对设置到哈希表 key 中
HMSET KEY FIELD VALUE[ FIELD1, VALUE1] ...
################### 取值语法 ####################
# HGET
## 获取存储在 HASH 中的值,根据 FIELD 得到 VALUE
HGET KEY FIELD
# HMGET
## 获取 key 所有给定字段的值
HMGET KEY field[field1]
# HGETALL
## 返回 HASH 表中所有的字段和值
HGETALL KEY
# HKEYS
## 获取所有哈希表中的字段
HKEYS KEY
# HLEN
## 获取哈希表中字段的数量
HLEN KEY
################### 其他语法 ####################
# HDEL
## 删除一个或多个 HASH 表字段
HDEL KEY field1[field2]...
# HSETNX
## 只有在字段 field 不存在时,设置哈希表字段的值
HSETNX key field value
# HINCRBY
## 为哈希表 key 中的指定字段的差数值加上增量 increment
HINCRBY key field increment
# HINCRBYFLOAT
## 为哈希表key中的指定字段的浮点数值加上増量 increment
HINCRBYFLOAT key field increment
# HEXISTS
## 查看哈希表 key 中,指定的字段是否存在
HEXISTS key field
Hash的应用场景:(存储一个用户信息对象数据)
常用于存储一个对象
为什么不用 string 存储一个对象?
hash 是最接近关系数据库结构的数据类型,可以将数据库一条记录或程序中一个对象转换成 hashmap 存放在 Redis 中。
用户 ID 为查找的key,存储的 value 用户对象包含姓名,年龄,生日等信息,如果用普通的 key/value 结构来存储,主要有以下2种存储方式:
将用户 ID 作为查找 key,把其他信息封装成一个对象以序列化的方式存储,这种方式的缺点是,增加了序列化/反序列化的开销,并且在需要修改其中一项信息时,需要把整个对象取回,并且修改操作需要对并发进行保护,引入CAS等复杂问题
这个用户信息对象有多少成员就存成多少个 key-value 对,用【用户 ID + 对应属性的名称】作为唯一标识来取得对应属性的值,虽然省去了序列化开销和并发问题,但是用户ID为重复存储,如果存在大量这样的数据,内存浪费还是非常可观的
总结:Redis 提供的 Hash 很好的解决了这个问题,Redis 的 Hash 实际是内部存储的 Value 为一个 HashMap,
List 类型是一个链表结构的集合,其主要功能有 push、pop、获取元素等。更详细的说,List 类型是一个双端链表的集合,我们可以通过相关的操作在集合的头部或者尾部添加和删除元素, List 的设计非常简单精巧,即可以作为栈,又可以作为队列,满足绝大多数的需求。
按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)一个列表最多可以包含 2的32次方减一个元素(4294967295,每个列表超过 40 亿个元素)
类似 JAVA 中的 LinkedList
############## 赋值语法 ####################
# LPUSH
## 将一个或多个值插入到列表头部(从左侧添加)
LPUSH key value1[value2]
# RPUSH
## 在列表中添加一个或多个值(从右侧添加)
RPUSH key value1[value2]
# LPUSHX
## 将一个值插入到已存在的列表头部。如果列表不在,操作无效
LPUSHX key value
# RPUSHX
## 一个值插入已存在的列表尾部(最右边)。如果列表不在,操作无效。
RPUSHX key value
############## 取值语法 ####################
# LLEN
## 获取列表长度
LLEN key
# LINDEX
## 通过索引获取列表中的元素
LINDEX key index
# LRANGE
## 获取列表指定范围内的元素
LRANGE key start stop
#######
# 描述:返回列表中指定区间内的元素,区间以偏移量 START 和 END 指定。
# 其中 0 表示列表的第一个元素,1 表示列表的第二个元素,以此类推。
# 也可以使用负数下标,以- 1 表示列表的最后一个元素,- 2 表示列表的倒数第二个元素,以此类推。
#
# 用于分页时:
# start :页大小 *(页数 - 1) stop :(页大小 * 页数)- 1
#######
############## 删除语法 ####################
# LPOP
## 移出并获取列表的第一个元素(从左侧删除)
LPOP key
# RPOP
## 移除列表的最后一个元燾,返回值为移除的元素(从右侧删除)
RPOP key
# BLPOP
## 移出并获取列表的第一个元素,如果列表没有元素会阻塞列表直到等待超时后返回 nil 或发现可弹出元素为止。
### timeout 单位为秒
BLPOP key1 [key2] timeout
# BRPOP
## 移出并获取列表的最后一个元素,如果列表没有元素会阻塞列表直到等待超时后返回 nil 或发现可弹出元素为止
### timeout 单位为秒
BRPOP key1 [key2] timeout
# LTRIM
## 对一个列表进行修剪(trim),就是说,让列表只保留指定区间内的元素,不在指定区间之内的元素都将被删除。
### 左右边界都包含在结果内
LTRIM key start stop
############## 修改语法 ####################
## 通过索引设置列表元素的值
LSET key index value
## 在列表的元素前或者后插入元素
## 将值 value 插入到列表 key 当中,位于值 pivot 之前或之后。
### 有多个相同元素时,只插入一次,以第一个元素为基准
LINSERT key BEFORE|AFTER pivot value
############## 高级命令 ####################
# RPOPLPUSH
## 移除列表的最后一个元素,并将该元素添加到另一个列表并返回
RPOPLPUSH source destination
# BRPOPLPUSH
## 从列表中弹出一个值,将弹出的元素插入到另外一个列表中并返回它
## 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。
BRPOPLPUSH source destination timeout
List 常应用于:
对数据量大的集合数据删减
列表数据显示、关注列表、粉丝列表、留言评价等
分页、热点新闻(Top5)等
利用 LRANGE 还可以很方便的实现分页的功能,在博客系统中,每片博文的评论也可以存入一个单独的 List 中。
任务队列
(List 通常用来实现一个消息队列,而且可以确保先后顺序,不必像 MYSQL 那样还需要通过 ORDER BY 来进行排序)
任务队列介绍(生产者和消费者模式)
在处理 web 客户端发送的命令请求时,某些操作的执行时间可能会比我们预期的更长一些,通过将待执行任务的相关信息放入队列里面,并在之后对队列进行处理,用户可以推迟执行那些需要一段时间才能能完成的操作,这种将工作交给任务处理器来执行的做法被称为任务队列(task queue)。
当用户完成付款后:
会生成一个物流队列(发货地址 --》 收货地址)
生成物流队列(发货地址:北京海淀、收货地址:南京建邺)
1、商家发货(北京海淀)
2、快递小哥取货
3、北京首都机场 —— 南京禄口机场
4、南京禄口机场 —— 建邺区
5、建邺区 —— 居民小区
6、收货
业务类
@Service
@Slf4j
public class ListQueueCacheService {
@Resource(name = "redisTemplate")
private ListOperations<String, String> opsForList;
/**
* 生成物流队列(发货地址:北京海淀、收货地址:南京建邺)
* 1、商家发货(北京海淀)
* 2、快递小哥取货
* 3、北京首都机场 —— 南京禄口机场
* 4、南京禄口机场 —— 建邺区
* 5、建邺区 —— 居民小区
* 6、收货
*
* @param orderId
*/
public void orderQueue(String orderId) {
// 待执行任务的队列 key
String key = "queue:" + orderId;
opsForList.leftPush(key, "1、商家发货(北京海淀)");
opsForList.leftPush(key, "2、快递小哥取货");
opsForList.leftPush(key, "3、北京首都机场 —— 南京禄口机场");
opsForList.leftPush(key, "4、南京禄口机场 —— 建邺区");
opsForList.leftPush(key, "5、建邺区 —— 居民小区");
opsForList.leftPush(key, "6、收货");
}
/**
* 快递小哥触发 队列事件
* 消费一个任务
*/
public String orderTouch(String orderId) {
// 待执行任务的队列 key
String key = "queue:" + orderId;
// 执行成功的队列的 key
String keySucc = "queue:" + orderId + ":succ";
return opsForList.rightPopAndLeftPush(key, keySucc);
}
/**
* 快递公司
* 关注点:快递任务还有几项完成
*
* @param orderId
* @return
*/
public List<String> orderSelect(String orderId) {
// 待执行任务的队列 key
String key = "queue:" + orderId;
return opsForList.range(key, 0, -1);
}
/**
* 用户
* 关注点:快递到哪了
*
* @param orderId
* @return
*/
public List<String> orderSelectSucc(String orderId) {
// 执行成功的队列的 key
String keySucc = "queue:" + orderId + ":succ";
return opsForList.range(keySucc, 0, -1);
}
}
测试类
@RunWith(SpringRunner.class)
@SpringBootTest
public class ListQueueCacheServiceTest {
@Autowired
private ListQueueCacheService service;
private String orderId;
@Before
public void init() {
orderId = "0001";
}
@Test
public void testOrderQueue() {
System.out.println("============> 生成物流任务列表");
service.orderQueue(orderId);
}
@Test
public void testOrderSelect() {
System.out.println("============> 需要执行的物流任务列表");
List<String> list = service.orderSelect(orderId);
System.out.println(list);
}
@Test
public void testOrderTouch() {
System.out.println("============> 物流小哥消费一个任务");
String s = service.orderTouch(orderId);
System.out.println("============> 被消费的任务是:" + s);
testOrderSelect();
}
@Test
public void testOrderSelectSucc() {
System.out.println("============> 用户查询物流进度");
List<String> list = service.orderSelectSucc(orderId);
System.out.println(list);
testOrderSelect();
}
}
Redis 的 Set 是 String 类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据。
Redis 中集合是通过哈希表实现的,Set 是通过 hashtable 实现的
集合中最大的成员数为 2的32次方减一(4294967295 ,每个集合可存储 40 多亿个成员)
类似于 Java 中的 Hashtable
集合
################ 赋值语法 ############################
# SADD
## 向集合添加一个或多个成员
SADD key member1[member2]
################ 取值语法 ############################
## 获取集合的成员数
SCARD key
## 返回集合中的所有成员
SMEMBERS key
## 判断 member 元素是否是集合key的成员
SISMEMBER key member
## 返回集合中一个或多个随机数
SRANDMEMBER key [count]
################ 删除语法 ############################
## 移除集合中一个或多个成员
SREM key member1 [member2]
## 移除并返回集合中的一个随机元素
SPOP key [count]
## 将 member 元素从 source集合移动到 destination 集合
SMOVE source destination member
################ 差集语法 ############################
## 返回给定所有集台的差集(左侧)
SDIFF key1 [key2]
## 返回给定所有集合的差集并存储在 destination 中
SDIFFSTORE destination keyl [key2]
################ 交集语法 ############################
## 返回给定所有集合的交集(共有数据)
SINTER key1 [key2]
## 返回给定所有集合的交集并存储在 destination 中
SINTERSTORE destination key1 [key2]
################ 并集语法 ############################
## 返回所有给定集合的并集
SUNION key1 [key2]
## 所有给定集合的并集存储在 destination 集合中
SUNIONSTORE destination key1 [key2]
常应用于:对两个集合间的数据【计算】进行交集、并集、差集运算
有序集合(sorted set )
Redis 有序集合和集合一样也是 string 类型元素的集合,且不允许重复的成员。
不同的是每个元素都会关联一个 double 类型的分数。 redis 正是通过分数来为集合中的成员进行从小到大的排序
有序集合的成员是唯一的但分数(score)法可以重复
集合是通过哈希表实现的。集合中最大的成员数为 2的32次方减1 (4294967295,每个集合可存储 40 多亿个成员)。 Redis 的 ZSet 是有序、且不重复
很多时候,我们都将 Redis 中的有序集合叫 zsets,这是因为在 Redis 中,有序集合相关的操作指令都是以 z 开头的)
################### 赋值语法 ##############################
## 向有序集合添加一个或多个成员,或者更新已存在成员的分数
ZADD key scorel member1 [score2 member2]
################### 取值语法 ##############################
## 获取有序集台的成员数
ZCARD key
## 计算在有序集台中指定区间分致的成员数
ZCOUNT key min max
## 返回有序集合中指定成员的索引
ZRANK key member
## 通过索引区间返回有序集合指定区间内的成员(低到高)
ZRANGE key start stop[WITHSCORES]
## 通过分数返回有序集合指定区间内的成员
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT]
## 倒序返回有序集中指定区间内的成员,通过索引,分数从高到低
ZREVRANGE key start stop [WITHSCORES]
## 返回有序集中指定分数区间内的成员,分数从高到低排序
ZREVRANGEBYSCORE key max min [WITHSCORES]
################### 删除语法 ##############################
## 移除集合
DEL key
## 移除有序集合中的一个或多个成员
ZREM key member [member...]
## 移除有序集合中给定的排名区间的所有成员(第一名是 0)(从低到高排序)
ZREMRANGEBYRANK key start stop
## 移除有序集合中给定的分数区间的所有成员
ZREMRANGEBYSCORE key min max
## 増加 memeber 元素的分数 increment,返回值是更改后的分数
ZINCRBY key increment member
常应用于:排行榜,销量排名,积分排名等
Redis 在 2.8.9 版本添加了 HyperLogLog 结构。
Redis HyperLogLog 是用来做基数统计的算法,HyperLogLog 的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定的、并且是很小的。
在 Redis里面,每个 HyperLogLog 键只需要花表 12 KB 内存,就可以计算接近 2^64 个不同元素的基数。这和计算基数时,元素越多耗费内存就越多的集合形成鲜明对比。
但是,因为 HyperLogLog 只会根据输入元素来计算基数,而不会储存输入元素本身,所以 HyperLogLog 不能像集合那样,返回输入的各个元素。
什么是基数?比如数据集 { 1, 3, 5, 7, 5, 7, 8 },那么这个数据集的基数集为{ 1, 3, 5, 7, 8 },基数(不重复元素)为 5。
基数估计就是在误差可接受的范围内,快速计算基数。
如果要统计 1 亿个数据的基数值,大约需要内存 100000000/8/1024/1024 ≈ 12M,内存减少占用的效果显著。
然而统计一个对象的基数值需要 12M,如果统计 10000 个对象,就需要将近 120G,同样不能广泛用于大数据场景。
## 添加指定元素到 HyperLogLog 中
PFADD key element [element ...]
## 返回给定 HyperLogLog 的基数估算值
PFCOUNT key [key ...]
## 将多个 HyperLogLog 合并为一个 HyperLogLog
PFMERGE destkey sourcekey [sourcekey ...]
基数不大,数据量不大就用不上,会有点大材小用浪费空间
有局限性,就是只能统计基数数量,而没办法去知道具体的内容是什么
具体用途:
HyperLogLog 是一种算法,并非 Redis 独有
目的是做基数统计,故不是集合,不会保存元数据,只记录数量而不是数值。
耗空间极小,支持输入非常大体积的数据量
核心是基数估算算法,主要表现为计算时内存的使用和数据合并的处理。最终数值存在一定误差
Redis 中每个 HyperLogLog key 占用了 12K 的内存用于标记基数(官方文档)
pfadd 命令并不会一次性分配 12k 内存,而是随着基数的增加而逐渐增加内存分配;而 pfmerge 操作则会将 sourcekey 合并后存储在 12k 大小的 key 中,这由 HyperLogLog 合并操作的原理(两个 HyperLogLog 合并时需要单独比较每个桶的值)可以很容易理解。
误差说明:基数估计的结果是一个带有 0.81% 标准错误(standard error)的近似值。是可接受的范围
Redis 对 HyperLogLog 的存储进行了优化,在计数比较小时,它的存储空间采用稀疏矩阵存储,空间占用很小,仅仅在计数慢慢变大,稀疏矩阵占用空间渐渐超过了阈值时才会一次性转变成稠密矩阵,才会占用 12k 的空间
20200610 千锋教育 Redis 2. Redis 命令、数据类型
标签:second 哈希表 对象类型 倒序 活跃 @param 一个用户 dom 系统
原文地址:https://www.cnblogs.com/huangwenjie/p/13088693.html