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

四川省网站建设最精品网站建设

四川省网站建设,最精品网站建设,常州企业网站建设公司,wordpress教程视频下载1 概念 1.1 关系型数据库与非关系型数据库对比 关系型数据库Mysql、Oralce特点数据之间有关联#xff1b;数据存储在硬盘上效率操作关系型数据库非常耗时 非关系型数据库redis、hbase存储key:value特点数据之间没有关联关系#xff1b;数据存储在内存中缓存思想从缓存中获…1 概念 1.1 关系型数据库与非关系型数据库对比 关系型数据库Mysql、Oralce特点数据之间有关联数据存储在硬盘上效率操作关系型数据库非常耗时 非关系型数据库redis、hbase存储key:value特点数据之间没有关联关系数据存储在内存中缓存思想从缓存中获取数据有数据时直接返回没有数据时从数据库中查询将数据放入到缓存返回数据 总结 与MySQL数据库不同的是Redis的数据是存在内存中的。它的读写速度非常快 每秒可以处理超过10万次读写操作。因此redis被广泛应用于缓存。 另外Redis也经常用来做分布式锁。 除此之外Redis支持事务、持久化、LUA 脚本、LRU 驱动事件、多种集群方案。1.2 五种基本类型 redis存储的是key,value 格式的数据其中Key都是字符串value有5种不同的数据结构。String字符串String是Redis最基础的数据结构类型它是二进制安全的可以存储图片或者序列化的对象值最大存储为512MHash哈希在Redis中哈希类型是指v值本身又是一个键值对k-v结构List列表列表list类型是用来存储多个有序的字符串一个列表最多可以存储2^32-1个元素支持重复元素Set集合集合set类型也是用来保存多个的字符串元素但是不允许重复元素zset有序集合有序集合类型不允许重复元素且元素有顺序每个元素都会关联一个double类型的分数redis正是通过分数来为集合中的成员进行从小到大的排序。 命令举例 字符串类型String存储 set key value获取 get key删除 del key 哈希类型map格式存储 hset key field value获取指定的field对应的值 hget key field获取所有的field和value hgetall key删除 hdel key field列表类型listlinkedlist格式将元素加入列表左表 lpush key value将元素加入列表右边 rpush key value范围获取 lrange key start end删除列表最左边的元素并将元素返回 lpop key删除列表最右边的元素并将元素返回 rpop key集合类型set存储 sadd key value获取所有元素 smembers key删除集合中某个元素 srem key value有序集合类型sortedset存储 zadd key score value获取 zrange key start end删除 zrem key value通用命令查询所有键 key *获取键对应的value类型 tepe key删除指定的Key,value del key1.3 redis事务 redis事务的本质就是一组命令的集合。 一个事务中的所有命令都会被序列化在事务执行过程中会按照顺序执行。 redis事务的特性包含一次性、顺序性、排他性。注意 1、redis事务没有隔离级别的概念。所有的命令在事务中并没有直接执行只有发起执行命令的时候才会执行2、redis单条命令是保证原子性的但是事务不保证原子性。2 Redis为什么这么快 1、基于内存存储实现 内存读写是比在磁盘快很多的Redis基于内存存储实现的数据库相对于数据存在磁盘的MySQL数据库 省去磁盘I/O的消耗。2、高效的数据结构 Mysql索引为了提高效率选择了B树的数据结构。其实合理的数据结构就是让应用/程序更快。3、合理的数据编码 Redis支持多种数据数据类型每种基本类型可能对多种数据结构。什么时候使用什么样数据结构 使用什么样编码是redis设计者总结优化的结果。4、合理的线程模型 Redis是单线程模型的而单线程避免了CPU不必要的上下文切换和竞争锁的消耗。也正因为是单线程 如果某个命令执行过长如hgetall命令会造成阻塞。Redis是面向快速执行场景的数据库。所以要慎用如smembers和lrange、hgetall等命令。 Redis 6.0 引入了多线程提速它的执行命令操作内存的仍然是个单线程。5、虚拟内存机制 Redis直接自己构建了VM机制 不会像一般的系统会调用系统函数处理会浪费一定的时间去移动和请求。 Redis的虚拟内存机制是啥呢 虚拟内存机制就是暂时把不经常访问的数据(冷数据)从内存交换到磁盘中从而腾出宝贵的内存空间用于其它需要访问的数据(热数据)。 通过VM功能可以实现冷热数据分离使热数据仍在内存中、冷数据保存到磁盘。这样就可以避免因为内存不足而造成访问速度下降的问题。3 缓存穿透、缓存雪奔、缓存击穿 常见的缓存使用方式 读请求来了先查下缓存缓存有值命中就直接返回 缓存没命中就去查数据库然后把数据库的值更新到缓存再返回。 3.1 缓存穿透 缓存穿透指查询一个一定不存在的数据由于缓存是不命中时需要从数据库查询查不到数据则不写入缓存 这将导致这个不存在的数据每次请求都要到数据库去查询进而给数据库带来压力。通俗点说读请求访问时缓存和数据库都没有某个值这样就会导致每次对这个值的查询请求都会穿透到数据库 这就是缓存穿透。缓存穿透一般都是这几种情况产生的 1、业务不合理的设计。 2、业务/运维/开发失误的操作比如缓存和数据库的数据都被误删除了。 3、黑客非法请求攻击比如黑客故意捏造大量非法请求以读取不存在的业务数据。如何避免缓存穿透呢 一般有三种方法。 1、如果是非法请求我们在API入口对参数进行校验过滤非法值。 2、如果查询数据库为空我们可以给缓存设置个空值或者默认值。但是如有有写请求进来的话需要更新缓存以保证缓存一致性同时最后给缓存设置适当的过期时间。 3、使用布隆过滤器快速判断数据是否存在。即一个查询请求过来时先通过布隆过滤器判断值是否存在存在才继续往下查。布隆过滤器原理它由初始值为0的位图数组和N个哈希函数组成。一个对一个key进行N个hash算法获取N个值在比特数组中将这N个值散列后设定为1然后查的时候如果特定的这几个位置都为1那么布隆过滤器判断该key存在。3.2 缓存雪奔 缓存雪奔指缓存中数据大批量到过期时间而查询数据量巨大请求都直接访问数据库 引起数据库压力过大甚至down机。1、缓存雪奔一般是由于大量数据同时过期造成的对于这个原因可通过均匀设置过期时间解决即让过期时间相对离散一点。如采用一个较大固定值一个较小的随机值5小时0到1800秒。 2、Redis 故障宕机也可能引起缓存雪奔。这就需要构造Redis高可用集群。3.3 缓存击穿 缓存击穿 指热点key在某个时间点过期的时候而恰好在这个时间点对这个Key有大量的并发请求过来 从而大量的请求打到数据库。解决方案就有两种 1、使用互斥锁方案。缓存失效时不是立即去加载db数据而是先使用某些带成功返回的原子操作命令如(Redis的setnx去操作成功的时候再去加载db数据库数据和设置缓存。否则就去重试获取缓存。 2、“永不过期”是指没有设置过期时间但是热点数据快要过期时异步线程去更新和设置过期时间。缓存击穿和缓存雪奔区别 缓存击穿看着有点像缓存雪奔其实它两区别是缓存雪奔是指数据库压力过大甚至down机缓存击穿只是大量并发请求到了DB数据库层面。 可以认为击穿是缓存雪奔的一个子集吧。 有些文章认为它俩的区别在于击穿针对某一热点key缓存雪奔则是很多key。什么是热Key问题如何解决热key问题 什么是热Key呢在Redis中我们把访问频率高的key称为热点key。 如果某一热点key的请求到服务器主机时由于请求量特别大可能会导致主机资源不足甚至宕机从而影响正常的服务。而热点Key是怎么产生的呢主要原因有两个 1、用户消费的数据远大于生产的数据如秒杀、热点新闻等读多写少的场景。 2、请求分片集中超过单Redis服务器的性能比如固定名称keyHash落入同一台服务器瞬间访问量极大超过机器瓶颈产生热点Key问题。(在日常开发中如何识别到热点key呢) 1、凭经验判断哪些是热Key 2、客户端统计上报 3、服务代理层上报。如何解决热key问题 1、Redis集群扩容增加分片副本均衡读流量 2、将热key分散到不同的服务器中 3、使用二级缓存即JVM本地缓存,减少Redis的读请求。4 Redis 过期策略和内存淘汰策略 4.1 Redis的过期策略 1、定时过期 每个设置过期时间的key都需要创建一个定时器到过期时间就会立即对key进行清除。该策略可以立即清除过期的数据对内存很友好但是会占用大量的CPU资源去处理过期的数据从而影响缓存的响应时间和吞吐量。2、惰性过期 只有当访问一个key时才会判断该key是否已过期过期则清除。该策略可以最大化地节省CPU资源却对内存非常不友好。极端情况可能出现大量的过期key没有再次被访问从而不会被清除占用大量内存。3、定期过期 每隔一定的时间会扫描一定数量的数据库的expires字典中一定数量的key并清除其中已过期的key。 该策略是前两者的一个折中方案。通过调整定时扫描的时间间隔和每次扫描的限定耗时可以在不同情况下使得CPU和内存资源达到最优的平衡效果。 expires字典会保存所有设置了过期时间的key的过期时间数据其中key是指向键空间中的某个键的指针value是该键的毫秒精度的UNIX时间戳表示的过期时间。键空间是指该Redis集群中保存的所有键。4.2 Redis 内存淘汰策略 volatile-lru当内存不足以容纳新写入数据时从设置了过期时间的key中使用LRU最近最少使用算法进行淘汰allkeys-lru当内存不足以容纳新写入数据时从所有key中使用LRU最近最少使用算法进行淘汰。volatile-lfu4.0版本新增当内存不足以容纳新写入数据时在过期的key中使用LFU算法进行删除key。allkeys-lfu4.0版本新增当内存不足以容纳新写入数据时从所有key中使用LFU算法进行淘汰volatile-random当内存不足以容纳新写入数据时从设置了过期时间的key中随机淘汰数据。allkeys-random当内存不足以容纳新写入数据时从所有key中随机淘汰数据。volatile-ttl当内存不足以容纳新写入数据时在设置了过期时间的key中根据过期时间进行淘汰越早过期的优先被淘汰noeviction默认策略当内存不足以容纳新写入数据时新写入操作会报错。5 Redis提供了 RDB 和 AOF 两种持久化机制 Redis是基于内存的非关系型K-V数据库既然它是基于内存的如果Redis服务器挂了数据就会丢失。为了避免数据丢失了Redis提供了持久化即把数据保存到磁盘。 5.1 RDB - 即把内存数据以快照的形式保存到磁盘上 RDB持久化是指在指定的时间间隔内执行指定次数的写操作将内存中的数据集快照写入磁盘中它是Redis默认的持久化方式。 执行完操作后在指定目录下会生成一个dump.rdb文件Redis 重启的时候通过加载dump.rdb文件来恢复数据。RDB 的优点适合大规模的数据恢复场景如备份全量复制等。RDB缺点没办法做到实时持久化/秒级持久化新老版本存在RDB格式兼容问题。【触发机制】 三种情况下会触发RDB规则1.sava的规则满足的情况下会自动触发rdb规则2.执行fushall命令也会触发我们的rdb规则3.退出redis也会产生rdb文件【恢复机制】 只需要将rdb文件放在redis启动目录下即可redis启动的时候回自动检测dump.rdb恢复数据。RDB默认方式不需要进行配置默认就使用这种机制在一定的间隔时间中检测key的变化情况然后持久化数据 5.2 AOFappend only file 持久化 AOFappend only file 持久化采用日志的形式来记录每个写操作 将redis执行过的所有指令记录下来(读操作不记录)追加到文件中且只许追加文件但不可以改写文件 重启时再重新执行AOF文件中的命令来恢复数据。换句话说redis重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作。 它主要解决数据持久化的实时性问题。AOF模式保存的文件名是appendonly.aof。在redis配置中默认是不开启的开发者需要手动配置 只需要将appendonly改为yes即可开启、再进行重启redis就可以生效了。 AOF默认就是文件的无限追加文件会越来越大如果aof文件大于64mredis会fork一个新的进程来将文件进行重写。AOF的优点数据的一致性和完整性更高。 AOF的缺点AOF记录的内容越多文件越大数据恢复变慢。注意 1.redis是一个内存数据库当redis 服务器重启或者电脑重启数据会丢失我们可以将redis 内存中的数据持久化保存到硬盘的文件中。 2.修改后重启redis服务器并制定配置文件的名称。 6 主从模式哨兵模式集群模式 在项目中使用Redis肯定不会是单点部署Redis服务的。因为单点部署一旦宕机就不可用了。为了实现高可用通常的做法是将数据库复制多个副本以部署在不同的服务器上其中一台挂了也可以继续提供服务。 Redis 实现高可用有三种部署模式主从模式哨兵模式集群模式。 6.1 主从模式 主从模式中Redis部署了多台机器有主节点负责读写操作有从节点只负责读操作。 从节点的数据来自主节点实现原理就是主从复制机制。主从复制包括全量复制增量复制两种。 一般当slave第一次启动连接master或者认为是第一次连接就采用全量复制全量复制流程如下1.slave发送sync命令到master。2.master接收到SYNC命令后执行bgsave命令生成RDB全量文件。3.master使用缓冲区记录RDB快照生成期间的所有写命令。4.master执行完bgsave后向所有slave发送RDB快照文件。5.slave收到RDB快照文件后载入、解析收到的快照。6.master使用缓冲区记录RDB同步期间生成的所有写的命令。7.master快照发送完毕后开始向slave发送缓冲区中的写命令;8.salve接受命令请求并执行来自master缓冲区的写命令6.2 哨兵模式 主从模式中一旦主节点由于故障不能提供服务需要人工将从节点晋升为主节点同时还要通知应用方更新主节点地址。显然多数业务场景都不能接受这种故障处理方式。Redis从2.8开始正式提供了Redis Sentinel哨兵架构来解决这个问题。 哨兵模式由一个或多个Sentinel实例组成的Sentinel系统它可以监视所有的Redis主节点和从节点 并在被监视的主节点进入下线状态时自动将下线主服务器属下的某个从节点升级为新的主节点。 但是呢一个哨兵进程对Redis节点进行监控就可能会出现问题单点问题 因此可以使用多个哨兵来进行监控Redis节点并且各个哨兵之间还会进行监控。Sentinel哨兵模式 简单来说哨兵模式就三个作用 1发送命令等待Redis服务器包括主服务器和从服务器返回监控其运行状态 2哨兵监测到主节点宕机会自动将从节点切换成主节点然后通过发布订阅模式通知其他的从节点修改配置文件让它们切换主机 3哨兵之间还会相互监控从而达到高可用。故障切换的过程是怎样的呢 假设主服务器宕机哨兵1先检测到这个结果系统并不会马上进行 failover 过程仅仅是哨兵1主观的认为主服务器不 可用这个现象成为主观下线。当后面的哨兵也检测到主服务器不可用并且数量达到一定值时那么哨兵之间就会进 行一次投票投票的结果由一个哨兵发起进行 failover 操作。切换成功后就会通过发布订阅模式让各个哨兵把自 己监控的从服务器实现切换主机这个过程称为客观下线。这样对于客户端而言一切都是透明的。哨兵的工作模式如下 1、每个Sentinel以每秒钟一次的频率向它所知的MasterSlave以及其他Sentinel实例发送一个 PING命令。 2、如果一个实例instance距离最后一次有效回复 PING 命令的时间超过 down-after-milliseconds 选项所指定的值 则这个实例会被 Sentinel标记为主观下线。 3、如果一个Master被标记为主观下线则正在监视这个Master的所有 Sentinel 要以每秒一次的频率确认Master的确进入了主观下线状态。 4、当有足够数量的 Sentinel大于等于配置文件指定的值在指定的时间范围内确认Master的确进入了主观下线状态 则Master会被标记为客观下线。 5、在一般情况下 每个 Sentinel 会以每10秒一次的频率向它已知的所有MasterSlave发送 INFO 命令。 6、当Master被 Sentinel 标记为客观下线时Sentinel 向下线的 Master 的所有 Slave 发送 INFO 命令的频率会从 10 秒一次改为每秒一次 7、若没有足够数量的 Sentinel同意Master已经下线 Master的客观下线状态就会被移除若Master 重新向 Sentinel 的 PING 命令返回有效回复 Master 的主观下线状态就会被移除。6.3 Cluster集群模式 哨兵模式基于主从模式实现读写分离它还可以自动切换系统可用性更高。但是它每个节点存储的数据是一样的浪费内存并且不好在线扩容。因此Cluster集群应运而生它在Redis3.0加入的实现了Redis的分布式存储。对数据进行分片也就是说每台Redis节点上存储不同的内容来解决在线扩容的问题。并且它也提供复制和故障转移的功能。 Cluster集群节点的通讯 一个Redis集群由多个节点组成各个节点之间是怎么通信的呢通过Gossip协议 Redis Cluster集群通过Gossip协议进行通信节点之前不断交换信息交换的信息内容包括节点出现故障、新节点加入、主从节点变更信息、slot信息等等。常用的Gossip消息分为4种分别是ping、pong、meet、fail。 1meet消息通知新节点加入。消息发送者通知接收者加入到当前集群meet消息通信正常完成后接收节点会加入到集群中并进行周期性的ping、pong消息交换。 2ping消息集群内交换最频繁的消息集群内每个节点每秒向多个其他节点发送ping消息用于检测节点是否在线和交换彼此状态信息。 3pong消息当接收到ping、meet消息时作为响应消息回复给发送方确认消息正常通信。pong消息内部封装了自身状态数据。节点也可以向集群内广播自身的pong消息来通知整个集群对自身状态进行更新。 4fail消息当节点判定集群内另一个节点下线时会向集群内广播一个fail消息其他节点接收到fail消息之后把对应节点更新为下线状态。为了保证高可用Cluster集群引入了主从复制一个主节点对应一个或者多个从节点。 当其它主节点 ping 一个主节点 A 时如果半数以上的主节点与 A 通信超时那么认为主节点 A 宕机了。 如果主节点宕机时就会启用从节点。Redis集群实现了高可用当集群内节点出现故障时通过故障转移以保证集群正常对外提供服务。 redis集群通过ping/pong消息实现故障发现。这个环境包括主观下线和客观下线。 1主观下线 某个节点认为另一个节点不可用即下线状态这个状态并不是最终的故障判定只能代表一个节点的意见可能存在误判情况。 2客观下线 指标记一个节点真正的下线集群内多个节点都认为该节点不可用从而达成共识的结果。如果是持有槽的主节点故障需要为该节点进行故障转移。 流程 1、假如节点A标记节点B为主观下线一段时间后节点A通过消息把节点B的状态发到其它节点当节点C接受到消息 并解析出消息体时如果发现节点B的pfail状态时会触发客观下线流程 2、当下线为主节点时此时Redis Cluster集群为统计持有槽的主节点投票看投票数是否达到一半当下线报告统计数 大于一半时被标记为客观下线状态。故障恢复故障发现后如果下线节点的是主节点则需要在它的从节点中选一个替换它以保证集群的高可用。 流程如下 1资格检查检查从节点是否具备替换故障主节点的条件。 2准备选举时间资格检查通过后更新触发故障选举时间。 3发起选举到了故障选举时间进行选举。 4选举投票只有持有槽的主节点才有票从节点收集到足够的选票大于一半触发替换主节点操作7 MySQL与Redis 如何保证双写一致性 1、缓存延时双删 延时双删流程先删除缓存再更新数据库休眠一会比如1秒再次删除缓存。2、删除缓存重试机制 因为延时双删可能会存在第二步的删除缓存失败导致的数据不一致问题。 可以使用这个方案优化删除失败就多删除几次,保证删除缓存成功就可以。所以可以引入删除缓存重试机制。删除缓存重试流程写请求更新数据库缓存因为某些原因删除失败把删除失败的key放到消息队列 消费消息队列的消息获取要删除的key重试删除缓存操作。3、读取biglog异步删除缓存 通过数据库的binlog来异步淘汰key。 以mysql为例 可以使用阿里的canal将binlog日志采集发送到MQ队列里面 然后通过ACK机制确认处理这条更新消息删除缓存保证数据缓存一致性。为什么Redis 6.0 之后改多线程呢 redis使用多线程并非是完全摒弃单线程redis还是使用单线程模型来处理客户端的请求只是使用多线程来处理数据的读写和协议解析执行命令还是使用单线程。这样做的目的是因为redis的性能瓶颈在于网络IO而非CPU使用多线程能提升IO读写的效率从而整体提高redis的性能。 8 RedisTemplate 8.1 概念 RedisTemplate是一个key和value都是泛型的模板类一般情况下key为String类型如RedisTemplateString,Object。 此外如果没特殊情况切勿定义成RedisTemplateObject, Object否则根据里氏替换原则使用的时候会造成类型错误 ValueOperations简单K-V操作 SetOperationsset类型数据操作 ZSetOperationszset类型数据操作 HashOperations针对map类型的数据操作 ListOperations针对list类型的数据操作RedisTemplate中定义了对5种数据结构操作redisTemplate.opsForValue();//操作字符串redisTemplate.opsForHash();//操作hashredisTemplate.opsForList();//操作listredisTemplate.opsForSet();//操作setredisTemplate.opsForZSet();//操作有序set其实这里的ops相当于options 是RedisTemplate对各种不同的Redis数据类型进行操作。其实还有另外的方法redistempalate.boundValueOpsredistempalate.boundSetOpsredistempalate.boundListOpsredistempalate.boundHashOpsredistempalate.boundZSetOps【opsForXXX和boundXXXOps的区别】 XXX为value的类型前者获取一个operator但是没有指定操作的对象key可以在一个连接事务内操作多个key以及对应的value 后者获取了一个指定操作对象key的operator在一个连接事务内只能操作这个key对应的value。8.2 RedisTemplate操作Redis Autowired private RedisTemplate redisTemplate;// 删除key public void delete(String key){redisTemplate.delete(key); }// 删除多个key public void deleteKey (String ...keys){redisTemplate.delete(keys); }// 指定key的失效时间 public void expire(String key,long time){redisTemplate.expire(key,time,TimeUnit.MINUTES); }// 根据key获取过期时间 public long getExpire(String key){Long expire redisTemplate.getExpire(key);return expire; }// 判断key是否存在 public boolean hasKey(String key){return redisTemplate.hasKey(key); }8.3 封装redisTemplate操作redis 直接用redisTemplate操作redis需要很多行代码因此直接封装好一个RedisUtil 这样写代码更方便点。这个RedisUtil 交给spring容器实例化使用时直接注解注入。 【RedisUtil 使用示例】 Autowiredprivate RedisUtil redisUtil;ListObject strings new ArrayList();strings.add(111);strings.add(222);strings.add(333);redisUtil.lSetList(666, strings);/*** component 把普通pojo实例化到spring容器中相当于配置文件中的泛指各种组件就是说当我们的类不属于各种归类的时候不属于Controller、Services等的时候我们就可以使用Component来标注这个类。1、Service用于标注业务层组件2、Controller用于标注控制层组件(如struts中的action)3、Repository用于标注数据访问组件即DAO组件.4、Component泛指组件当组件不好归类的时候我们可以使用这个注解进行标注。*/ Component public class RedisUtil {/*** Autowired 注释它可以对类成员变量、方法及构造函数进行标注完成自动装配的工作。 通过 Autowired的* 使用来消除 set get方法。在使用Autowired之前我们对一个bean配置起属性时是这用用的* property name属性名 value 属性值/ 通过这种方式来配置比较繁琐而且代码比较多。在Spring 2.5 引* 入了 Autowired 注释*/Autowiredprivate RedisTemplateString, Object redisTemplate;/*** 指定缓存失效时间* param key 键* param time 时间秒* return true / false*/public boolean expire(String key, long time) {try {if (time 0) {redisTemplate.expire(key, time, TimeUnit.SECONDS);}return true;} catch (Exception e) {e.printStackTrace();return false;}}/*** 根据 key 获取过期时间* param key 键* return*/public long getExpire(String key) {return redisTemplate.getExpire(key, TimeUnit.SECONDS);}/*** 判断 key 是否存在* param key 键* return true / false*/public boolean hasKey(String key) {try {return redisTemplate.hasKey(key);} catch (Exception e) {e.printStackTrace();return false;}}/*** 删除缓存* SuppressWarnings(unchecked) 忽略类型转换警告* param key 键一个或者多个*/SuppressWarnings(unchecked)public void del(String... key) {if (key ! null key.length 0) {if (key.length 1) {redisTemplate.delete(key[0]);} else { // 传入一个 CollectionString 集合redisTemplate.delete(CollectionUtils.arrayToList(key));}}}// String /*** 普通缓存获取* param key 键* return 值*/public Object get(String key) {return key null ? null : redisTemplate.opsForValue().get(key);}/*** 普通缓存放入* param key 键* param value 值* return true / false*/public boolean set(String key, Object value) {try {redisTemplate.opsForValue().set(key, value);return true;} catch (Exception e) {e.printStackTrace();return false;}}/*** 普通缓存放入并设置时间* param key 键* param value 值* param time 时间秒如果 time 0 则设置无限时间* return true / false*/public boolean set(String key, Object value, long time) {try {if (time 0) {redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);} else {set(key, value);}return true;} catch (Exception e) {e.printStackTrace();return false;}}/*** 递增* param key 键* param delta 递增大小* return*/public long incr(String key, long delta) {if (delta 0) {throw new RuntimeException(递增因子必须大于 0);}return redisTemplate.opsForValue().increment(key, delta);}/*** 递减* param key 键* param delta 递减大小* return*/public long decr(String key, long delta) {if (delta 0) {throw new RuntimeException(递减因子必须大于 0);}return redisTemplate.opsForValue().increment(key, delta);}// Map /*** HashGet* param key 键no null* param item 项no null* return 值*/public Object hget(String key, String item) {return redisTemplate.opsForHash().get(key, item);}/*** 获取 key 对应的 map* param key 键no null* return 对应的多个键值*/public MapObject, Object hmget(String key) {return redisTemplate.opsForHash().entries(key);}/*** HashSet* param key 键* param map 值* return true / false*/public boolean hmset(String key, MapObject, Object map) {try {redisTemplate.opsForHash().putAll(key, map);return true;} catch (Exception e) {e.printStackTrace();return false;}}/*** HashSet 并设置时间* param key 键* param map 值* param time 时间* return true / false*/public boolean hmset(String key, MapObject, Object map, long time) {try {redisTemplate.opsForHash().putAll(key, map);if (time 0) {expire(key, time);}return true;} catch (Exception e) {e.printStackTrace();return false;}}/*** 向一张 Hash表 中放入数据如不存在则创建* param key 键* param item 项* param value 值* return true / false*/public boolean hset(String key, String item, Object value) {try {redisTemplate.opsForHash().put(key, item, value);return true;} catch (Exception e) {e.printStackTrace();return false;}}/*** 向一张 Hash表 中放入数据并设置时间如不存在则创建* param key 键* param item 项* param value 值* param time 时间如果原来的 Hash表 设置了时间这里会覆盖* return true / false*/public boolean hset(String key, String item, Object value, long time) {try {redisTemplate.opsForHash().put(key, item, value);if (time 0) {expire(key, time);}return true;} catch (Exception e) {e.printStackTrace();return false;}}/*** 删除 Hash表 中的值* param key 键* param item 项可以多个no null*/public void hdel(String key, Object... item) {redisTemplate.opsForHash().delete(key, item);}/*** 判断 Hash表 中是否有该键的值* param key 键no null* param item 值no null* return true / false*/public boolean hHasKey(String key, String item) {return redisTemplate.opsForHash().hasKey(key, item);}/*** Hash递增如果不存在则创建一个并把新增的值返回* param key 键* param item 项* param by 递增大小 0* return*/public Double hincr(String key, String item, Double by) {return redisTemplate.opsForHash().increment(key, item, by);}/*** Hash递减* param key 键* param item 项* param by 递减大小* return*/public Double hdecr(String key, String item, Double by) {return redisTemplate.opsForHash().increment(key, item, -by);}// Set /*** 根据 key 获取 set 中的所有值* param key 键* return 值*/public SetObject sGet(String key) {try {return redisTemplate.opsForSet().members(key);} catch (Exception e) {e.printStackTrace();return null;}}/*** 从键为 key 的 set 中根据 value 查询是否存在* param key 键* param value 值* return true / false*/public boolean sHasKey(String key, Object value) {try {return redisTemplate.opsForSet().isMember(key, value);} catch (Exception e) {e.printStackTrace();return false;}}/*** 将数据放入 set缓存* param key 键值* param values 值可以多个* return 成功个数*/public long sSet(String key, Object... values) {try {return redisTemplate.opsForSet().add(key, values);} catch (Exception e) {e.printStackTrace();return 0;}}/*** 将数据放入 set缓存并设置时间* param key 键* param time 时间* param values 值可以多个* return 成功放入个数*/public long sSet(String key, long time, Object... values) {try {long count redisTemplate.opsForSet().add(key, values);if (time 0) {expire(key, time);}return count;} catch (Exception e) {e.printStackTrace();return 0;}}/*** 获取 set缓存的长度* param key 键* return 长度*/public long sGetSetSize(String key) {try {return redisTemplate.opsForSet().size(key);} catch (Exception e) {e.printStackTrace();return 0;}}/*** 移除 set缓存中值为 value 的* param key 键* param values 值* return 成功移除个数*/public long setRemove(String key, Object... values) {try {return redisTemplate.opsForSet().remove(key, values);} catch (Exception e) {e.printStackTrace();return 0;}}// List /*** 获取 list缓存的内容* param key 键* param start 开始* param end 结束0 到 -1 代表所有值* return*/public ListObject lGet(String key, long start, long end) {try {return redisTemplate.opsForList().range(key, start, end);} catch (Exception e) {e.printStackTrace();return null;}}/*** 获取 list缓存的长度* param key 键* return 长度*/public long lGetListSize(String key) {try {return redisTemplate.opsForList().size(key);} catch (Exception e) {e.printStackTrace();return 0;}}/*** 根据索引 index 获取键为 key 的 list 中的元素* param key 键* param index 索引* 当 index 0 时 {0:表头, 1:第二个元素}* 当 index 0 时 {-1:表尾, -2:倒数第二个元素}* return 值*/public Object lGetIndex(String key, long index) {try {return redisTemplate.opsForList().index(key, index);} catch (Exception e) {e.printStackTrace();return null;}}/*** 将值 value 插入键为 key 的 list 中如果 list 不存在则创建空 list* param key 键* param value 值* return true / false*/public boolean lSet(String key, Object value) {try {redisTemplate.opsForList().rightPush(key, value);return true;} catch (Exception e) {e.printStackTrace();return false;}}/*** 将值 value 插入键为 key 的 list 中并设置时间* param key 键* param value 值* param time 时间* return true / false*/public boolean lSet(String key, Object value, long time) {try {redisTemplate.opsForList().rightPush(key, value);if (time 0) {expire(key, time);}return true;} catch (Exception e) {e.printStackTrace();return false;}}/*** 将 values 插入键为 key 的 list 中* param key 键* param values 值* return true / false*/public boolean lSetList(String key, ListObject values) {try {redisTemplate.opsForList().rightPushAll(key, values);return true;} catch (Exception e) {e.printStackTrace();return false;}}/*** 将 values 插入键为 key 的 list 中并设置时间* param key 键* param values 值* param time 时间* return true / false*/public boolean lSetList(String key, ListObject values, long time) {try {redisTemplate.opsForList().rightPushAll(key, values);if (time 0) {expire(key, time);}return true;} catch (Exception e) {e.printStackTrace();return false;}}/*** 根据索引 index 修改键为 key 的值* param key 键* param index 索引* param value 值* return true / false*/public boolean lUpdateIndex(String key, long index, Object value) {try {redisTemplate.opsForList().set(key, index, value);return true;} catch (Exception e) {e.printStackTrace();return false;}}/*** 在键为 key 的 list 中删除值为 value 的元素* param key 键* param count 如果 count 0 则删除 list 中所有值为 value 的元素* 如果 count 0 则删除 list 中最左边那个值为 value 的元素* 如果 count 0 则删除 list 中最右边那个值为 value 的元素* param value* return*/public long lRemove(String key, long count, Object value) {try {return redisTemplate.opsForList().remove(key, count, value);} catch (Exception e) {e.printStackTrace();return 0;}} }
http://www.dnsts.com.cn/news/15139.html

相关文章:

  • 英文网站制作注意点营口 微网站建设
  • 曲阜市古建设计院网站苏州发布最新消息
  • 企业服务类网站支付宝手机网站
  • 做网站加推广多少钱盐津铺子网络营销推广方法
  • 我想做卖鱼苗网站怎样做厦门企业建站模板
  • mysql 注册网站淘宝运营培训有必要吗
  • 沈阳行业网站十大免费网站推广平台
  • 营销型网站制作培训多少钱html5新特性
  • 设计网站页面要怎么切图用wordpress 安装自己喜欢的主题 主题图片显示不对
  • 企业网站建设排名价格深圳宝安网站建设
  • 网赌网站国外空间国外做各种趣味实验的网站
  • 无极任务平台网站进入wordpress来源
  • intitlt 山西大同网站建设网站文件命名规则
  • 空间网站大全中企动力做网站好吗
  • 高端人才做兼职的招聘网站有哪些全球网
  • seo网站建设价格html编写新闻页面
  • 如何设置网站根目录在电商网站上做推广的技巧
  • 如何用word做网站地图成品网站nike源码免费
  • 网站免备案空间商务网站内容维护和管理的范围
  • 个人网站icp备案号微盟商城
  • 做移动网站网站如何做问卷调查报告
  • 云霄县建设局网站投诉wordpress 破解账号
  • 做logo去哪个网站商务定制网站
  • 如何建设商城网站山西网站建设营销qq
  • 深圳电器网站建设设计网站推荐ps
  • 建设网站都要什么黄一级a做爰片免费网站
  • iOS开发 隐私政策网站怎么做秦皇岛网站制作公司哪家好
  • 网站开发先前台和后台twenty ten wordpress
  • 网站做半透明度的优势建设银行信用卡网站首页
  • 做图片推广的网站招聘网最新招聘信息网