先说说redis怎么做缓存,作为redis新手的我很迷茫怎么做,一无所措,然后就找度娘。最后度娘告诉我你学习了redis的五大数据类型就会了。是不是想吐槽 哈哈哈(先说明我是先学习看了数据类型才思考如何做缓存的)
redis缓存:说白了就是在你dao层操作数据库的时候同时优先操作redis数据库如果redis数据库中有则返回没有则操作DB数据库,例如:查询先插redis数据库如果有则返回没有就在查DB数据库,最后把DB数据库结果返回并存入热度是数据库即可
进入正题开始码redis数据类型:
一、String字符串类型
1、简介
string 类型是 Redis 中最基本的数据类型,最常用的数据类型,甚至被很多玩家当成 redis 唯一的数据类型去使用。
string 类型在 redis 中是二进制安全(binary safe)的,这意味着 string 值关心二进制的字符串,不关心具体格式,
你可以用它存储 json 格式或 JPEG 图片格式的字符串。
字符串类型实际上可以是字符串(简单的字符串、复杂的字符串(xml、json)、数字(整数、浮点数)、二进制(图片、音频、视频)), 但最大不能超过512M。
2、使用场景
缓存功能:字符串最经典的使用场景,redis最为缓存层,Mysql作为储存层,绝大部分请求数据都是
redis中获取,由于redis具有支撑高并发特性,所以缓存通常能起到加速读写和降低 后端压力的作用。
计数器:许多运用都会使用redis作为计数的基础工具,他可以实现快速计数、查询缓存的功能,
同时数据可以一步落地到其他的数据源。如:视频播放数系统就是使用redis作为视频播放数计数的基础组件。
共享session:出于负载均衡的考虑,分布式服务会将用户信息的访问均衡到不同服务器上,
用户刷新一次访问可能会需要重新登录,为避免这个问题可以用redis将用户session集中管理,
在这种模式下只要保证redis的高可用和扩展性的,每次获取用户更新或查询登录信息都直接从redis中集中获取。
限速:处于安全考虑,每次进行登录时让用户输入手机验证码,为了短信接口不被频繁访问,
会限制用户每分钟获取验证码的频率。
3、基本方法
static Jedis jedis = null;
static {
//初始化redisPool连接池
RedisPoolUtil.initalPool();
//获得连接实例
jedis = RedisPoolUtil.getConnect();
}
public static void main(String[] args) {
//String类型基本操作方法
//1、设置键 获取键
jedis.set("key","hello jedis");
String str = jedis.get("key");
System.out.println("设置后值:"+str);
//2、追加键
jedis.append("key", " i very heppy");
str = jedis.get("key");
System.out.println("追加后值:"+str);
//3、删除操作
jedis.del("key");
str = jedis.get("key");
System.out.println("删除后值:"+str);
//4、不存在就保存(指定的 key 不存在时,为 key 设置指定的值。)
jedis.setnx("key","world");
str = jedis.get("key");
System.out.println("设置后值:"+str);
System.out.println("再次设置没有被覆盖"+jedis.setnx("key","hello"));
//5、截取字符串
System.out.println("截取后值:"+jedis.substr("key",0,2));
//6、设置多个键值对
jedis.mset(new String[]{"kay","111111","kcy","22"});
System.out.println("多次设置后值:"+jedis.mget("kay","kcy"));
System.out.println("设置后值:"+jedis.get("kay"));
//7、递增递减
jedis.incr("kay");
jedis.decr("kcy");
System.out.println("递增递减后值:"+jedis.mget("kay","kcy"));
jedis.incrBy("kay",3);
jedis.decrBy("kcy",2);
System.out.println("递增递减后值:"+jedis.mget("kay","kcy"));
//8、返回 key 所储存的字符串值的长度。
System.out.println("储存的字符串值的长度:"+jedis.strlen("key"));
//9、覆盖给定 key 所储存的字符串值,覆盖的位置从偏移量 offset 开始。
jedis.setrange("key", 6, "redis");
System.out.println("覆盖给定 key后的值"+jedis.get("key"));
//键ket的基本操作
//1、检查给定 key 是否存在
System.out.println("键是否存在:"+jedis.exists("key"));
//2、返回 key 所储存的值的类型。
System.out.println("key储存值的类型:"+jedis.type("key"));
//3、修改 key 的名称
jedis.rename("key", "newKey");
System.out.println("设置后值:"+jedis.get("key"));
System.out.println("设置后值:"+jedis.get("newKey"));
}
二、List列表类型
1、简介
列表类型是用来储存多个有序的字符串,列表中的每个字符串成为元素(element),一个列表最多可以储存
2的32次方-1个元素,在redis中,可以队列表两端插入(pubsh)和弹出(pop),还可以获取指定范围的元素
列表、获取指定索引下表的元素等,列表是一种比较灵活的数据结构,它可以充当栈和队列的角色,
优点:
1.列表的元素是有序的,这就意味着可以通过索引下标获取某个或某个范围内的元素列表。
2.列表内的元素是可以重复的。
2、使用场景
消息队列: redis的lpush+brpop命令组合即可实现阻塞队列,生产者客户端是用lupsh从列表左侧插入元素,
多个消费者客户端使用brpop命令阻塞时的“抢”列表尾部的元素,多个客户端保证了消费的负载均衡
和高可用性
文章列表:每个用户都有属于自己的文章列表,现在需要分页展示文章列表,此时可以考虑使用列表,列表不但有序
同时支持按照索引范围获取元素。
使用列表技巧:
lpush+lpop=Stack(栈)
lpush+rpop=Queue(队列)
lpush+ltrim=Capped Collection(有限集合)
lpush+brpop=Message Queue(消息队列)
3、基本方法
static Jedis jedis = null;
static {
//初始化redisPool连接池
RedisPoolUtil.initalPool();
//获得连接实例
jedis = RedisPoolUtil.getConnect();
}
public static void main(String[] args) {
//1、将一个或多个值插入到列表头部。 如果 key 不存在,一个空列表会被创建并执行 LPUSH 操作。
//当 key 存在但不是列表类型时,返回一个错误。返回值是列表的长度。
jedis.lpush("books", "java","js","html","nodes","css");
//2、将一个或多个值插入到列表的尾部(最右边)。如果列表不存在,一个空列表会被创建并执行 RPUSH 操作。
//当列表存在但不是列表类型时,返回一个错误。返回值是列表的长度。
jedis.rpush("language", "java","c++","html","python","php");
//3、返回列表中指定区间内的元素,区间以偏移量 START 和 END 指定。 其中 0 表示列表的第一个元素, 1 表示列表的第二个元素,
//以此类推。 你也可以使用负数下标,以 -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素,以此类推。
System.out.println("头添加后books值:"+jedis.lrange("books",0,-1));
System.out.println("尾添加后language值:"+jedis.lrange("language",0,-1));
//4、移除并返回列表的第一个元素。
System.out.println("删除的值为:"+jedis.lpop("books"));
//5、移除列表的最后一个元素,返回值为移除的元素。
System.out.println("删除的值为:"+jedis.rpop("language"));
System.out.println("头部删除后books值:"+jedis.lrange("books",0,-1));
System.out.println("尾部删除后language值:"+jedis.lrange("language",0,-1));
//6、移除列表的最后一个元素,并将该元素添加到另一个列表并返回。
jedis.rpoplpush("books", "language");
System.out.println("尾部删除并头添加后books值:"+jedis.lrange("books",0,-1));
System.out.println("尾部删除并头添加后language值:"+jedis.lrange("language",0,-1));
//7、将一个值插入到已存在的列表头部,列表不存在时操作无效。
jedis.lpushx("books","php");
jedis.lpushx("book","php");
System.out.println("头添加后books值:"+jedis.lrange("books",0,-1));
System.out.println("头添加后book值:"+jedis.lrange("book",0,-1));
//8、返回列表的长度。 如果列表 key 不存在,则 key 被解释为一个空列表,返回 0 。 如果 key 不是列表类型,返回一个错误
System.out.println("books集合长度:"+jedis.llen("books"));
//9、通过索引获取列表中的元素。你也可以使用负数下标,以 -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素,以此类推。
System.out.println("books集合第二个数值:"+jedis.lindex("books",1));
//10、 对一个列表进行修剪(trim),就是说,让列表只保留指定区间内的元素,不在指定区间之内的元素都将被删除。
//下标 0 表示列表的第一个元素,以 1 表示列表的第二个元素,以此类推。 你也可以使用负数下标,以 -1 表示列表的最后一个元素,
//-2 表示列表的倒数第二个元素,以此类推。 命令执行成功时,返回 ok 。
jedis.ltrim("books",0,2);
System.out.println("截取后books值:"+jedis.lrange("books",0,-1));
//11、列表的元素前或者后插入元素。当指定元素不存在于列表中时,不执行任何操作。
//当列表不存在时,被视为空列表,不执行任何操作。如果 key 不是列表类型,返回一个错误。
jedis.linsert("books", LIST_POSITION.BEFORE, "html", "vue");
System.out.println("插入元素后的列表:"+jedis.lrange("books", 0, -1));
//12、通过索引来设置元素的值。当索引参数超出范围,或对一个空列表进行 LSET 时,返回一个错误。
jedis.lset("books", 0, "layui");
System.out.println("设置元素后的列表:"+jedis.lrange("books", 0, -1));
//13、根据参数 COUNT 的值,移除列表中与参数 VALUE 相等的元素。
// COUNT 的值可以是以下几种:
// count > 0 : 从表头开始向表尾搜索,移除与 VALUE 相等的元素,数量为 COUNT 。
// count < 0 : 从表尾开始向表头搜索,移除与 VALUE 相等的元素,数量为 COUNT 的绝对值。
// count = 0 : 移除表中所有与 VALUE 相等的值。
jedis.lrem("books", -2, "html");
System.out.println("移除列表中与参数 VALUE 相等的元素后的列表:"+jedis.lrange("books", 0, -1));
}
三、Hash哈希类型
1、简介
hash 类型很像一个关系型数据库的数据表,hash 的 Key 是一个唯一值,Value 部分是一个 hashmap 的结构。
是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象。
哈希结构相对于字符串序列化缓存信息更加直观,并且在更新操作上更加便捷、灵活。使用 string 类型存储,必然需要转换和解析 json 格式的字符串,即便不需要转换,在内存开销方面,还是 hash 占优势。
哈希类型和关系型数据库有所不同,哈希类型是稀疏的, 而关系型数据库是完全结构化的,关系型数据库可以做复杂的关系查询,而redis去模拟关系型复杂查询 开发困难,维护成本高。
2、使用场景
存储部分变更数据,如用户信息等。
3、基本方法
static Jedis jedis = null;
static {
//初始化redisPool连接池
RedisPoolUtil.initalPool();
//获得连接实例
jedis = RedisPoolUtil.getConnect();
}
public static void main(String[] args) {
//1、设置或者获取存储在哈希表中指定字段的值
jedis.hset("studen", "name", "zhangsan");
String str = jedis.hget("studen", "name");
System.out.println("student中name的值为:"+str);
HashMap<String, String> map = new HashMap<String,String>();
map.put("name", "张三");
map.put("sex", "男");
map.put("age","20");
//2、同时将多个 field-value (字段-值)对设置到哈希表中。此命令会覆盖哈希表中已存在的字段。
//如果哈希表不存在,会创建一个空哈希表,并执行 HMSET 操作。
jedis.hmset("teacher",map);
System.out.println("teacher中name、age的值为:"+jedis.hmget("teacher","name","age"));
//3、查看哈希表 key 中,指定的字段是否存在。
Boolean flag = jedis.hexists("teacher", "sex");
System.out.println("哈希表指定 key中的字段是否存在:"+flag);
//4、为哈希表 key 中的指定字段的整数值加上增量 number
jedis.hincrBy("teacher", "age", 3);
System.out.println("teacher中age的值为:"+jedis.hmget("teacher","age"));
//5、获取哈希表中字段的数量
System.out.println("哈希表中字段的数量:"+jedis.hlen("teacher"));
//6、获取所有哈希表中的字段
System.out.println("哈希表中所有的字段:"+jedis.hkeys("teacher"));
//7、获取所有给定字段的值
System.out.println("所有给定字段的值:"+jedis.hvals("teacher"));
//8、获取在哈希表中指定 key 的所有字段和值
System.out.println("哈希表中指定 key 的所有字段和值:"+jedis.hgetAll("teacher"));
//9、删除一个或多个哈希表字段
jedis.hdel("teacher", "sex");
System.out.println("哈希表中指定 key 的所有字段和值:"+jedis.hgetAll("teacher"));
}
四、Set集合类型
1、简介
Redis 的 Set 是 String 类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据。
Redis 中集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。
集合类型也是用来保存多个字符串的元素,但和列表不同的是集合中不允许有重复的元素,并且集合中的元素是
无序的,不能通过索引下标获取元素,redis除了支持集合内的增删改查,
set 类型提供了多个 set 之间的聚合运算,如求交集、并集、补集,这些操作在 redis 内部完成,效率很高。
2、使用场景
set 类型的特点是——不重复且无序的一组数据,并且具有丰富的计算功能,在一些特定的场景中可以高效的解决一般关系型数据库不方便做的工作。
1. 共同好友列表:社交类应用中,获取两个人或多个人的共同好友,两个人或多个人共同关注的微博这样类似的功能,用 MySQL 的话操作很复杂,可以把每个人的好友 id 存到集合中,获取共同好友的操作就可以简单到一个取交集的命令就搞定。
2、标签(tag):集合类型比较典型的使用场景,取不同兴趣圈子的交集,如一个用户对娱乐、体育比较感兴趣,另一个可能对新闻感兴 趣,这些兴趣就是标签,有了这些数据就可以得到同一标签的人,以及用户的共同爱好的标签,这些数据对于用户体验以及曾强用户粘度比较重要。(用户和标签的关系维护应该放在一个事物内执行,防止部分命令失败造成数据不一致)
sadd=tagging(标签)
spop/srandmember=random item(生成随机数,比如抽奖)
sadd+sinter=social Graph(社交需求)
3、基本方法
static Jedis jedis = null;
static {
//初始化redisPool连接池
RedisPoolUtil.initalPool();
//获得连接实例
jedis = RedisPoolUtil.getConnect();
}
public static void main(String[] args) {
//1、将一个或多个成员元素加入到集合中,已经存在于集合的成员元素将被忽略。
//假如集合 key 不存在,则创建一个只包含添加的元素作成员的集合。当集合 key 不是集合类型时,返回一个错误。
jedis.sadd("bory", "jan","john","Anna","jack");
jedis.sadd("girls", "jeane","jack","Anna","peka");
//2、返回集合中的所有的成员。 不存在的集合 key 被视为空集合。
System.out.println("集合中的所有的成员:"+jedis.smembers("bory"));
System.out.println("集合中的所有的成员:"+jedis.smembers("girls"));
//3、返回集合中元素的数量。
System.out.println("集合中元素的数量:"+jedis.scard("bory"));
//4、判断成员元素是否是集合的成员。
System.out.println("元素是否是集合的成员:"+jedis.sismember("bory", "jack"));
//5、移除集合中的一个或多个成员元素,不存在的成员元素会被忽略。当 key 不是集合类型,返回一个错误。
System.out.println("移除集合中的一个或多个成员元素:"+jedis.srem("girls","peka"));
System.out.println("集合中的所有的成员:"+jedis.smembers("girls"));
//6、移除集合中的指定 key 的一个或多个随机元素,移除后会返回移除的元素
System.out.println("移除集合中的一个或多个成员元素:"+jedis.spop("girls"));
//7、返回给定所有给定集合的交集。 不存在的集合 key 被视为空集。 当给定集合当中有一个空集时,结果也为空集(根据集合运算定律)。
System.out.println("给定集合的交集:"+jedis.sinter("bory","girls"));
//8、返回给定集合的并集。不存在的集合 key 被视为空集。
System.out.println("给定集合的并集:"+jedis.sunion("bory","girls"));
//9、返回给定集合之间的差集。不存在的集合 key 将视为空集。差集的结果来自前面的 FIRST_KEY ,
//而不是后面的 OTHER_KEY1,也不是整个 FIRST_KEY OTHER_KEY1..OTHER_KEYN 的差集。
System.out.println("bory对girls的差集:"+jedis.sdiff("bory","girls"));
System.out.println("girls对bory的差集:"+jedis.sdiff("girls","bory"));
//10、将给定集合之间的交集存储在指定的集合中。如果指定的集合已经存在,则将其覆盖。
jedis.sinterstore("jiaoji","bory","girls");
System.out.println("交集:"+jedis.smembers("jiaoji"));
//11、将给定集合的并集存储在指定的集合 destination 中。如果 destination 已经存在,则将其覆盖。
jedis.sunionstore("bingji","bory","girls");
System.out.println("并集:"+jedis.smembers("bingji"));
//12、将给定集合之间的差集存储在指定的集合中。如果指定的集合 key 已存在,则会被覆盖。
jedis.sdiffstore("chaji","bory","girls");
System.out.println("student对girls的差集:"+jedis.smembers("chaji"));
}
五、 sorted set有序集合类型
1、简介
Redis 有序集合和集合一样也是string类型元素的集合,且不允许重复的成员。不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。有序集合的成员是唯一的,但分数(score)却可以重复。集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。 集合中最大的成员数为 232 - 1 (4294967295, 每个集合可存储40多亿个成员)。
2、使用场景
比好友的“亲密度”排序显示好友列表。
排行榜:有序集合经典使用场景。例如视频网站需要对用户上传的视频做排行榜,榜单维护可能是多方面:
按照时间、按照播放量、按照获得的赞数等。
3、基本方法
static Jedis jedis = null;
static {
//初始化redisPool连接池
RedisPoolUtil.initalPool();
//获得连接实例
jedis = RedisPoolUtil.getConnect();
}
public static void main(String[] args) {
//1、将一个或多个成员元素及其分数值加入到有序集当中。如果某个成员已经是有序集的成员,那么更新这个成员的分数值,
//并通过重新插入这个成员元素,来保证该成员在正确的位置上。分数值可以是整数值或双精度浮点数。如果有序集合 key 不存在,
//则创建一个空的有序集并执行 ZADD 操作。当 key 存在但不是有序集类型时,返回一个错误。
jedis.zadd("math",75,"Jim");
jedis.zadd("math",86,"Lina");
jedis.zadd("math",52,"Dive");
jedis.zadd("math",91,"Bobber");
jedis.zadd("math", 99, "bana");
jedis.zadd("meth",63,"Jime");
jedis.zadd("meth",86,"Lina");
jedis.zadd("meth",52,"Dive");
jedis.zadd("meth",91,"Bobber");
jedis.zadd("meth", 99, "bana");
//2、 返回有序集中,指定区间内的成员。其中成员的位置按分数值递增(从小到大)来排序。
//具有相同分数值的成员按字典序(lexicographical order )来排列。如果你需要成员按值递减(从大到小)来排列,
//请使用 ZREVRANGE 命令。下标参数 start 和 stop 都以 0 为底,也就是说,以 0 表示有序集第一个成员,
//以 1 表示有序集第二个成员,以此类推。你也可以使用负数下标,以 -1 表示最后一个成员, -2 表示倒数第二个成员,以此类推。
Set<String> set = jedis.zrange("math", 0, -1);
System.out.println("指定区间内的成员(从小到大):"+set);
System.out.println("指定区间内的成员(从大到小)):"+jedis.zrevrange("math", 0,-1));
//3、计算集合中元素的数量。
System.out.println("有序集合的成员数量:"+jedis.zcard("math"));
//4、计算在有序集合中指定区间分数的成员数量
System.out.println("指定区间分数的成员数量:"+jedis.zcount("math", 80, 95));
//5、对有序集合中指定成员的分数加上增量 increment可以通过传递一个负数值 increment ,让分数减去相应的值,
System.out.println("指定成员的分数加上增量:"+jedis.zincrby("math", 5, "Dive"));
//8、在计算有序集合中指定字典区间内成员数量。
System.out.println("字典区间内成员数量:"+jedis.zlexcount("jiaoji", "-", "+"));
//18、计算给定的一个或多个有序集的并集,其中给定 key 的数量必须以 numkeys 参数指定,并将该并集(结果集)储存到 destination 。
System.out.println("给定的一个或多个有序集的并集:"+jedis.zunionstore("bingji", "math","meth"));
System.out.println("多个有序集的交集:"+jedis.zrange("bingji", 0, -1));
//7、计算给定的一个或多个有序集的交集,其中给定 key 的数量必须以 numkeys 参数指定,
//并将该交集(结果集)储存到 destination 。默认情况下,结果集中某个成员的分数值是所有给定集下该成员分数值之和。
jedis.zinterstore("jiaoji", "math","meth");
System.out.println("多个有序集的交集:"+jedis.zrange("jiaoji", 0, -1));
//6、返回有序集合中指定分数区间的成员列表。有序集合成员按分数值递增(从小到大)次序排列。
//具有相同分数值的成员按字典序来排列(该属性是有序集提供的,不需要额外的计算)。
//默认情况下,区间的取值使用闭区间 (小于等于或大于等于),你也可以通过给参数前增加 ( 符号来使用可选的开区间 (小于或大于)。
System.out.println("返回有序集合中指定分数区间的成员列表:"+jedis.zrangeByScore("math",0, 100));
//9、返回有序集合中指定分数区间的成员列表。有序集成员按分数值递增(从小到大)次序排列。
//具有相同分数值的成员按字典序来排列(该属性是有序集提供的,不需要额外的计算)。
//默认情况下,区间的取值使用闭区间 (小于等于或大于等于),你也可以通过给参数前增加 ( 符号来使用可选的开区间 (小于或大于)。
System.out.println("返回有序集合中指定分数区间的成员列表:"+jedis.zrangeByScore("math", 60, 90));
//15、返回有序集中,指定区间内的成员。其中成员的位置按分数值递减(从大到小)来排列。
//具有相同分数值的成员按字典序的逆序(reverse lexicographical order)排列。
//除了成员按分数值递减的次序排列这一点外, ZREVRANGE 命令的其他方面和 ZRANGE 命令一样。
System.out.println("有序集合的成员:"+jedis.zrevrangeByScore("math",0,100));
//10、返回有序集中指定成员的排名。其中有序集成员按分数值递增(从小到大)顺序排列。
System.out.println("有序集中指定成员的排名,按分数值递增(从小到大):"+jedis.zrank("math", "Lina"));
//16、返回有序集中成员的排名。其中有序集成员按分数值递减(从大到小)排序。排名以 0 为底,也就是说, 分数值最大的成员排名为 0 。
//使用 ZRANK 命令可以获得成员按分数值递增(从小到大)排列的排名。
System.out.println("有序集中指定成员的排名,按分数值递减(从大到小):"+jedis.zrank("math", "Lina"));
//11、移除有序集中的一个或多个成员,不存在的成员将被忽略。当 key 存在但不是有序集类型时,返回一个错误。
System.out.println("移除有序集中的一个或多个成员:"+jedis.zrem("math", "Lina","Jim"));
System.out.println("指定区间内的成员(从大到小)):"+jedis.zrevrange("math", 0,-1));
//12、移除有序集合中给定的字典区间的所有成员。
System.out.println("移除给定的字典区间内的所有成员:"+jedis.zremrangeByLex("jiaoji", "-","+"));
System.out.println("指定给定的字典区间内的所有成员:"+jedis.zrevrange("jiaoji", 0,-1));
//13、移除有序集中,指定排名(rank)区间内的所有成员。
System.out.println("移除指定排名(rank)区间内的所有成员:"+jedis.zremrangeByRank("meth", 1,2));
System.out.println("指定排名(rank)区间内的所有成员:"+jedis.zrevrange("meth", 0,-1));
//14、移除有序集中,指定分数(score)区间内的所有成员。
System.out.println("移除指定分数(score)区间内的所有成员:"+jedis.zremrangeByScore("meth", 80, 90));
System.out.println("指定分数(score)区间内的所有成员:"+jedis.zrevrange("meth", 0,-1));
//17、返回有序集中,成员的分数值。 如果成员元素不是有序集 key 的成员,或 key 不存在,返回 nil 。
System.out.println("返回有序集中,成员的分数值:"+jedis.zrank("math", "Lina"));
}
以上就是redis的数据类型介绍及简答的使用,最后来一个数据库事务正确执行的四个基本要素数据库事务
一、原子性(Atomicity)
整个程序中的所有操作,要么全部完成,要么全部不完成,不可能停滞在中间某个环节。
二、一致性(Consistency)
一个事务可以封装状态改变(除非它是一个只读的)。事务必须始终保持系统处于一致的状态,不管在任何给定的时间并发事务有多少。
三、隔离性(Isolation)
隔离状态执行事务,使它们好像是系统在给定时间内执行的唯一操作。
四、持久性(Durability)
在事务完成以后,该事务对数据库所作的更改便持久的保存在数据库之中,并不会被回滚。
参考链接:https://blog.csdn.net/qq_41654985/article/details/82390875