diff --git a/Snipaste_2023-02-20_14-56-37 1.png b/Snipaste_2023-02-20_14-56-37 1.png new file mode 100644 index 0000000..b64962e Binary files /dev/null and b/Snipaste_2023-02-20_14-56-37 1.png differ diff --git a/Snipaste_2023-02-20_14-56-37 2.png b/Snipaste_2023-02-20_14-56-37 2.png new file mode 100644 index 0000000..5b06d94 Binary files /dev/null and b/Snipaste_2023-02-20_14-56-37 2.png differ diff --git a/Snipaste_2023-02-20_14-56-37 3.png b/Snipaste_2023-02-20_14-56-37 3.png new file mode 100644 index 0000000..efe2aaf Binary files /dev/null and b/Snipaste_2023-02-20_14-56-37 3.png differ diff --git a/Snipaste_2023-02-20_14-56-37 4.png b/Snipaste_2023-02-20_14-56-37 4.png new file mode 100644 index 0000000..f5fbdfb Binary files /dev/null and b/Snipaste_2023-02-20_14-56-37 4.png differ diff --git a/Snipaste_2023-02-20_14-56-37.png b/Snipaste_2023-02-20_14-56-37.png new file mode 100644 index 0000000..c452ea2 Binary files /dev/null and b/Snipaste_2023-02-20_14-56-37.png differ diff --git a/Snipaste_2023-02-20_15-16-16.png b/Snipaste_2023-02-20_15-16-16.png new file mode 100644 index 0000000..e69c2bb Binary files /dev/null and b/Snipaste_2023-02-20_15-16-16.png differ diff --git a/Snipaste_2023-02-20_15-21-10 1.png b/Snipaste_2023-02-20_15-21-10 1.png new file mode 100644 index 0000000..2c9a9f1 Binary files /dev/null and b/Snipaste_2023-02-20_15-21-10 1.png differ diff --git a/Snipaste_2023-02-20_15-21-10 2.png b/Snipaste_2023-02-20_15-21-10 2.png new file mode 100644 index 0000000..462de6c Binary files /dev/null and b/Snipaste_2023-02-20_15-21-10 2.png differ diff --git a/Snipaste_2023-02-20_15-21-10 3.png b/Snipaste_2023-02-20_15-21-10 3.png new file mode 100644 index 0000000..b9771ee Binary files /dev/null and b/Snipaste_2023-02-20_15-21-10 3.png differ diff --git a/Snipaste_2023-02-20_15-21-10 4.png b/Snipaste_2023-02-20_15-21-10 4.png new file mode 100644 index 0000000..185fedf Binary files /dev/null and b/Snipaste_2023-02-20_15-21-10 4.png differ diff --git a/Snipaste_2023-02-20_15-21-10 5.png b/Snipaste_2023-02-20_15-21-10 5.png new file mode 100644 index 0000000..eb1dcbd Binary files /dev/null and b/Snipaste_2023-02-20_15-21-10 5.png differ diff --git a/Snipaste_2023-02-20_15-21-10 6.png b/Snipaste_2023-02-20_15-21-10 6.png new file mode 100644 index 0000000..2e96828 Binary files /dev/null and b/Snipaste_2023-02-20_15-21-10 6.png differ diff --git a/Snipaste_2023-02-20_15-21-10 7.png b/Snipaste_2023-02-20_15-21-10 7.png new file mode 100644 index 0000000..84f1aab Binary files /dev/null and b/Snipaste_2023-02-20_15-21-10 7.png differ diff --git a/Snipaste_2023-02-20_15-21-10 8.png b/Snipaste_2023-02-20_15-21-10 8.png new file mode 100644 index 0000000..cc704be Binary files /dev/null and b/Snipaste_2023-02-20_15-21-10 8.png differ diff --git a/Snipaste_2023-02-20_15-21-10 9.png b/Snipaste_2023-02-20_15-21-10 9.png new file mode 100644 index 0000000..8fab06c Binary files /dev/null and b/Snipaste_2023-02-20_15-21-10 9.png differ diff --git a/Snipaste_2023-02-20_15-21-10.png b/Snipaste_2023-02-20_15-21-10.png new file mode 100644 index 0000000..e5f99d6 Binary files /dev/null and b/Snipaste_2023-02-20_15-21-10.png differ diff --git a/Snipaste_2023-02-21_09-33-02 1.png b/Snipaste_2023-02-21_09-33-02 1.png new file mode 100644 index 0000000..76a4a62 Binary files /dev/null and b/Snipaste_2023-02-21_09-33-02 1.png differ diff --git a/Snipaste_2023-02-21_09-33-02.png b/Snipaste_2023-02-21_09-33-02.png new file mode 100644 index 0000000..c1528e9 Binary files /dev/null and b/Snipaste_2023-02-21_09-33-02.png differ diff --git a/Snipaste_2023-02-22_14-56-05 1.png b/Snipaste_2023-02-22_14-56-05 1.png new file mode 100644 index 0000000..0dc6839 Binary files /dev/null and b/Snipaste_2023-02-22_14-56-05 1.png differ diff --git a/Snipaste_2023-02-22_14-56-05 10.png b/Snipaste_2023-02-22_14-56-05 10.png new file mode 100644 index 0000000..94114bc Binary files /dev/null and b/Snipaste_2023-02-22_14-56-05 10.png differ diff --git a/Snipaste_2023-02-22_14-56-05 2.png b/Snipaste_2023-02-22_14-56-05 2.png new file mode 100644 index 0000000..3376d57 Binary files /dev/null and b/Snipaste_2023-02-22_14-56-05 2.png differ diff --git a/Snipaste_2023-02-22_14-56-05 3.png b/Snipaste_2023-02-22_14-56-05 3.png new file mode 100644 index 0000000..b50acbe Binary files /dev/null and b/Snipaste_2023-02-22_14-56-05 3.png differ diff --git a/Snipaste_2023-02-22_14-56-05 4.png b/Snipaste_2023-02-22_14-56-05 4.png new file mode 100644 index 0000000..ba99008 Binary files /dev/null and b/Snipaste_2023-02-22_14-56-05 4.png differ diff --git a/Snipaste_2023-02-22_14-56-05 5.png b/Snipaste_2023-02-22_14-56-05 5.png new file mode 100644 index 0000000..2bbdbe4 Binary files /dev/null and b/Snipaste_2023-02-22_14-56-05 5.png differ diff --git a/Snipaste_2023-02-22_14-56-05 6.png b/Snipaste_2023-02-22_14-56-05 6.png new file mode 100644 index 0000000..a3f50e4 Binary files /dev/null and b/Snipaste_2023-02-22_14-56-05 6.png differ diff --git a/Snipaste_2023-02-22_14-56-05 7.png b/Snipaste_2023-02-22_14-56-05 7.png new file mode 100644 index 0000000..b34c5b7 Binary files /dev/null and b/Snipaste_2023-02-22_14-56-05 7.png differ diff --git a/Snipaste_2023-02-22_14-56-05 8.png b/Snipaste_2023-02-22_14-56-05 8.png new file mode 100644 index 0000000..37a1ceb Binary files /dev/null and b/Snipaste_2023-02-22_14-56-05 8.png differ diff --git a/Snipaste_2023-02-22_14-56-05 9.png b/Snipaste_2023-02-22_14-56-05 9.png new file mode 100644 index 0000000..87e1c68 Binary files /dev/null and b/Snipaste_2023-02-22_14-56-05 9.png differ diff --git a/Snipaste_2023-02-22_14-56-05.png b/Snipaste_2023-02-22_14-56-05.png new file mode 100644 index 0000000..78de1f4 Binary files /dev/null and b/Snipaste_2023-02-22_14-56-05.png differ diff --git a/Snipaste_2023-02-22_16-10-55 1.png b/Snipaste_2023-02-22_16-10-55 1.png new file mode 100644 index 0000000..af2b0ba Binary files /dev/null and b/Snipaste_2023-02-22_16-10-55 1.png differ diff --git a/Snipaste_2023-02-22_16-10-55 10.png b/Snipaste_2023-02-22_16-10-55 10.png new file mode 100644 index 0000000..8e24164 Binary files /dev/null and b/Snipaste_2023-02-22_16-10-55 10.png differ diff --git a/Snipaste_2023-02-22_16-10-55 2.png b/Snipaste_2023-02-22_16-10-55 2.png new file mode 100644 index 0000000..ca0157c Binary files /dev/null and b/Snipaste_2023-02-22_16-10-55 2.png differ diff --git a/Snipaste_2023-02-22_16-10-55 3.png b/Snipaste_2023-02-22_16-10-55 3.png new file mode 100644 index 0000000..bcf1538 Binary files /dev/null and b/Snipaste_2023-02-22_16-10-55 3.png differ diff --git a/Snipaste_2023-02-22_16-10-55 4.png b/Snipaste_2023-02-22_16-10-55 4.png new file mode 100644 index 0000000..c4dbcb0 Binary files /dev/null and b/Snipaste_2023-02-22_16-10-55 4.png differ diff --git a/Snipaste_2023-02-22_16-10-55 5.png b/Snipaste_2023-02-22_16-10-55 5.png new file mode 100644 index 0000000..e72cb73 Binary files /dev/null and b/Snipaste_2023-02-22_16-10-55 5.png differ diff --git a/Snipaste_2023-02-22_16-10-55 6.png b/Snipaste_2023-02-22_16-10-55 6.png new file mode 100644 index 0000000..f32d491 Binary files /dev/null and b/Snipaste_2023-02-22_16-10-55 6.png differ diff --git a/Snipaste_2023-02-22_16-10-55 7.png b/Snipaste_2023-02-22_16-10-55 7.png new file mode 100644 index 0000000..55fe106 Binary files /dev/null and b/Snipaste_2023-02-22_16-10-55 7.png differ diff --git a/Snipaste_2023-02-22_16-10-55 8.png b/Snipaste_2023-02-22_16-10-55 8.png new file mode 100644 index 0000000..f0a6906 Binary files /dev/null and b/Snipaste_2023-02-22_16-10-55 8.png differ diff --git a/Snipaste_2023-02-22_16-10-55 9.png b/Snipaste_2023-02-22_16-10-55 9.png new file mode 100644 index 0000000..3972ca6 Binary files /dev/null and b/Snipaste_2023-02-22_16-10-55 9.png differ diff --git a/Snipaste_2023-02-22_16-10-55.png b/Snipaste_2023-02-22_16-10-55.png new file mode 100644 index 0000000..41b834b Binary files /dev/null and b/Snipaste_2023-02-22_16-10-55.png differ diff --git a/Snipaste_2023-02-23_10-00-41 1.png b/Snipaste_2023-02-23_10-00-41 1.png new file mode 100644 index 0000000..33015ec Binary files /dev/null and b/Snipaste_2023-02-23_10-00-41 1.png differ diff --git a/Snipaste_2023-02-23_10-00-41 10.png b/Snipaste_2023-02-23_10-00-41 10.png new file mode 100644 index 0000000..5a80170 Binary files /dev/null and b/Snipaste_2023-02-23_10-00-41 10.png differ diff --git a/Snipaste_2023-02-23_10-00-41 11.png b/Snipaste_2023-02-23_10-00-41 11.png new file mode 100644 index 0000000..0d1e663 Binary files /dev/null and b/Snipaste_2023-02-23_10-00-41 11.png differ diff --git a/Snipaste_2023-02-23_10-00-41 12.png b/Snipaste_2023-02-23_10-00-41 12.png new file mode 100644 index 0000000..263f059 Binary files /dev/null and b/Snipaste_2023-02-23_10-00-41 12.png differ diff --git a/Snipaste_2023-02-23_10-00-41 13.png b/Snipaste_2023-02-23_10-00-41 13.png new file mode 100644 index 0000000..e7f3339 Binary files /dev/null and b/Snipaste_2023-02-23_10-00-41 13.png differ diff --git a/Snipaste_2023-02-23_10-00-41 14.png b/Snipaste_2023-02-23_10-00-41 14.png new file mode 100644 index 0000000..6c3d8d2 Binary files /dev/null and b/Snipaste_2023-02-23_10-00-41 14.png differ diff --git a/Snipaste_2023-02-23_10-00-41 15.png b/Snipaste_2023-02-23_10-00-41 15.png new file mode 100644 index 0000000..50ff85c Binary files /dev/null and b/Snipaste_2023-02-23_10-00-41 15.png differ diff --git a/Snipaste_2023-02-23_10-00-41 16.png b/Snipaste_2023-02-23_10-00-41 16.png new file mode 100644 index 0000000..4f0b999 Binary files /dev/null and b/Snipaste_2023-02-23_10-00-41 16.png differ diff --git a/Snipaste_2023-02-23_10-00-41 17.png b/Snipaste_2023-02-23_10-00-41 17.png new file mode 100644 index 0000000..9ac246f Binary files /dev/null and b/Snipaste_2023-02-23_10-00-41 17.png differ diff --git a/Snipaste_2023-02-23_10-00-41 18.png b/Snipaste_2023-02-23_10-00-41 18.png new file mode 100644 index 0000000..4a4228e Binary files /dev/null and b/Snipaste_2023-02-23_10-00-41 18.png differ diff --git a/Snipaste_2023-02-23_10-00-41 19.png b/Snipaste_2023-02-23_10-00-41 19.png new file mode 100644 index 0000000..eaa0c5e Binary files /dev/null and b/Snipaste_2023-02-23_10-00-41 19.png differ diff --git a/Snipaste_2023-02-23_10-00-41 2.png b/Snipaste_2023-02-23_10-00-41 2.png new file mode 100644 index 0000000..1fe4664 Binary files /dev/null and b/Snipaste_2023-02-23_10-00-41 2.png differ diff --git a/Snipaste_2023-02-23_10-00-41 20.png b/Snipaste_2023-02-23_10-00-41 20.png new file mode 100644 index 0000000..2e290f9 Binary files /dev/null and b/Snipaste_2023-02-23_10-00-41 20.png differ diff --git a/Snipaste_2023-02-23_10-00-41 21.png b/Snipaste_2023-02-23_10-00-41 21.png new file mode 100644 index 0000000..42b2f3d Binary files /dev/null and b/Snipaste_2023-02-23_10-00-41 21.png differ diff --git a/Snipaste_2023-02-23_10-00-41 3.png b/Snipaste_2023-02-23_10-00-41 3.png new file mode 100644 index 0000000..5d44254 Binary files /dev/null and b/Snipaste_2023-02-23_10-00-41 3.png differ diff --git a/Snipaste_2023-02-23_10-00-41 4.png b/Snipaste_2023-02-23_10-00-41 4.png new file mode 100644 index 0000000..28bbc05 Binary files /dev/null and b/Snipaste_2023-02-23_10-00-41 4.png differ diff --git a/Snipaste_2023-02-23_10-00-41 5.png b/Snipaste_2023-02-23_10-00-41 5.png new file mode 100644 index 0000000..3ea6175 Binary files /dev/null and b/Snipaste_2023-02-23_10-00-41 5.png differ diff --git a/Snipaste_2023-02-23_10-00-41 6.png b/Snipaste_2023-02-23_10-00-41 6.png new file mode 100644 index 0000000..514c6ed Binary files /dev/null and b/Snipaste_2023-02-23_10-00-41 6.png differ diff --git a/Snipaste_2023-02-23_10-00-41 7.png b/Snipaste_2023-02-23_10-00-41 7.png new file mode 100644 index 0000000..3d5a55c Binary files /dev/null and b/Snipaste_2023-02-23_10-00-41 7.png differ diff --git a/Snipaste_2023-02-23_10-00-41 8.png b/Snipaste_2023-02-23_10-00-41 8.png new file mode 100644 index 0000000..0a08d69 Binary files /dev/null and b/Snipaste_2023-02-23_10-00-41 8.png differ diff --git a/Snipaste_2023-02-23_10-00-41 9.png b/Snipaste_2023-02-23_10-00-41 9.png new file mode 100644 index 0000000..7b02a10 Binary files /dev/null and b/Snipaste_2023-02-23_10-00-41 9.png differ diff --git a/Snipaste_2023-02-23_10-00-41.png b/Snipaste_2023-02-23_10-00-41.png new file mode 100644 index 0000000..0a0695f Binary files /dev/null and b/Snipaste_2023-02-23_10-00-41.png differ diff --git a/Snipaste_2023-02-23_17-24-34 1.png b/Snipaste_2023-02-23_17-24-34 1.png new file mode 100644 index 0000000..0e784c2 Binary files /dev/null and b/Snipaste_2023-02-23_17-24-34 1.png differ diff --git a/Snipaste_2023-02-23_17-24-34 10.png b/Snipaste_2023-02-23_17-24-34 10.png new file mode 100644 index 0000000..1607451 Binary files /dev/null and b/Snipaste_2023-02-23_17-24-34 10.png differ diff --git a/Snipaste_2023-02-23_17-24-34 11.png b/Snipaste_2023-02-23_17-24-34 11.png new file mode 100644 index 0000000..64447e8 Binary files /dev/null and b/Snipaste_2023-02-23_17-24-34 11.png differ diff --git a/Snipaste_2023-02-23_17-24-34 12.png b/Snipaste_2023-02-23_17-24-34 12.png new file mode 100644 index 0000000..d3447a5 Binary files /dev/null and b/Snipaste_2023-02-23_17-24-34 12.png differ diff --git a/Snipaste_2023-02-23_17-24-34 13.png b/Snipaste_2023-02-23_17-24-34 13.png new file mode 100644 index 0000000..c473b15 Binary files /dev/null and b/Snipaste_2023-02-23_17-24-34 13.png differ diff --git a/Snipaste_2023-02-23_17-24-34 2.png b/Snipaste_2023-02-23_17-24-34 2.png new file mode 100644 index 0000000..0e73b93 Binary files /dev/null and b/Snipaste_2023-02-23_17-24-34 2.png differ diff --git a/Snipaste_2023-02-23_17-24-34 3.png b/Snipaste_2023-02-23_17-24-34 3.png new file mode 100644 index 0000000..9371e4d Binary files /dev/null and b/Snipaste_2023-02-23_17-24-34 3.png differ diff --git a/Snipaste_2023-02-23_17-24-34 4.png b/Snipaste_2023-02-23_17-24-34 4.png new file mode 100644 index 0000000..bbee3e0 Binary files /dev/null and b/Snipaste_2023-02-23_17-24-34 4.png differ diff --git a/Snipaste_2023-02-23_17-24-34 5.png b/Snipaste_2023-02-23_17-24-34 5.png new file mode 100644 index 0000000..361b297 Binary files /dev/null and b/Snipaste_2023-02-23_17-24-34 5.png differ diff --git a/Snipaste_2023-02-23_17-24-34 6.png b/Snipaste_2023-02-23_17-24-34 6.png new file mode 100644 index 0000000..a5cebc0 Binary files /dev/null and b/Snipaste_2023-02-23_17-24-34 6.png differ diff --git a/Snipaste_2023-02-23_17-24-34 7.png b/Snipaste_2023-02-23_17-24-34 7.png new file mode 100644 index 0000000..1e6508d Binary files /dev/null and b/Snipaste_2023-02-23_17-24-34 7.png differ diff --git a/Snipaste_2023-02-23_17-24-34 8.png b/Snipaste_2023-02-23_17-24-34 8.png new file mode 100644 index 0000000..b62a4d5 Binary files /dev/null and b/Snipaste_2023-02-23_17-24-34 8.png differ diff --git a/Snipaste_2023-02-23_17-24-34 9.png b/Snipaste_2023-02-23_17-24-34 9.png new file mode 100644 index 0000000..f1e7676 Binary files /dev/null and b/Snipaste_2023-02-23_17-24-34 9.png differ diff --git a/Snipaste_2023-02-23_17-24-34.png b/Snipaste_2023-02-23_17-24-34.png new file mode 100644 index 0000000..dbc46c9 Binary files /dev/null and b/Snipaste_2023-02-23_17-24-34.png differ diff --git a/Snipaste_2023-02-24_09-52-40 1.png b/Snipaste_2023-02-24_09-52-40 1.png new file mode 100644 index 0000000..b457bcb Binary files /dev/null and b/Snipaste_2023-02-24_09-52-40 1.png differ diff --git a/Snipaste_2023-02-24_09-52-40 2.png b/Snipaste_2023-02-24_09-52-40 2.png new file mode 100644 index 0000000..d801d10 Binary files /dev/null and b/Snipaste_2023-02-24_09-52-40 2.png differ diff --git a/Snipaste_2023-02-24_09-52-40.png b/Snipaste_2023-02-24_09-52-40.png new file mode 100644 index 0000000..e66d9ff Binary files /dev/null and b/Snipaste_2023-02-24_09-52-40.png differ diff --git a/Snipaste_2023-02-24_14-42-21 1.png b/Snipaste_2023-02-24_14-42-21 1.png new file mode 100644 index 0000000..068b80a Binary files /dev/null and b/Snipaste_2023-02-24_14-42-21 1.png differ diff --git a/Snipaste_2023-02-24_14-42-21.png b/Snipaste_2023-02-24_14-42-21.png new file mode 100644 index 0000000..4b61d13 Binary files /dev/null and b/Snipaste_2023-02-24_14-42-21.png differ diff --git a/日常学习/中间件/redis/5种基础数据结构详解.md b/日常学习/中间件/redis/5种基础数据结构详解.md new file mode 100644 index 0000000..51cde45 --- /dev/null +++ b/日常学习/中间件/redis/5种基础数据结构详解.md @@ -0,0 +1,102 @@ ++ String ++ hash ++ list ++ set ++ zset + +# 一、数据结构 +## 1. string +字符串由多个字节组成,每个字节由8个bit组成,可以将一个字符串看成很多bit的组合,这就是bitmap数据结构。 +redis提供的字符串是动态字符串,是可以修改的字符串,内部使用数组结构实现,采用**预分配**冗余空间的方式来减少内存的频繁分配,如图所示预分配的空间capacity要高于实际字符串长度len。 +![[Snipaste_2023-02-22_14-56-05.png]] +当字符串长度小于1MB时,扩容都是加倍现有空间。如果字符串长度超过1MB,扩容时一次只会多扩1MB空间,并且字符串最大长度为512MB。 + +### 1.1常用命令 +#### 1.1.1 键值对 +![[Snipaste_2023-02-22_14-56-05 1.png]] +#### 1.1.2 批量键值对 +对多字符串进行批量读写 +![[Snipaste_2023-02-22_14-56-05 2.png]] +#### 1.1.3 过期和set命令扩展 +对key设置过期时间,到期自动删除 +![[Snipaste_2023-02-22_14-56-05 3.png]] +等价命令 setex name 3 zr 等价于set + expire +![[Snipaste_2023-02-22_14-56-05 4.png]] +setnx name zr 如果name不存在则创建 +![[Snipaste_2023-02-22_14-56-05 5.png]] +#### 1.1.4 计数 +如果value值是一个整数,可以对它进行自增操作,自增范围在long的最大值和最小值之间 +![[Snipaste_2023-02-22_14-56-05 6.png]] +## 2.list +Redis的list相当于Java的LinkedList,是链表不是数组。插入和删除很快,时间复杂度为O(1)。索引定位慢,时间复杂度为O(n)。list的每个元素都使用了双向指针,可以支持前向后向遍历,因此可以作为队列或栈使用。 +![[Snipaste_2023-02-22_14-56-05 7.png]] +### 2.1 常用命令 +#### 2.1.1 队列 +队列是先进先出的数据结构,用于消息排队和异步逻辑处理。支持左进右出、右进左出,会确保元素的访问顺序性。 +![[Snipaste_2023-02-22_14-56-05 8.png]] +注:使用pop命令后元素会删除 +#### 2.1.2栈 +栈是后进先出的数据结构 +![[Snipaste_2023-02-22_14-56-05 9.png]] +#### 2.1.3慢操作 +lindex类似于java的get(int index)方法,需要对list进行遍历,性能随着参数index增加而变差。 +ltrim类似于截取操作,由两个参数start_index和end_index定义一个区间,保留在区间内的值,区间外的删除,可以用来实现一个定长的链表。 +index可以为负数,index=-1表示倒数第一个元素,同理index=-2表示倒数第二个元素。 +![[Snipaste_2023-02-22_14-56-05 10.png]] + +### 2.2底层数据结构(quicklist) +实际上Redis的list并不是一个简单的linkedlist,而是quicklist(快速链表)。 +在元素较少情况下,会使用一块连续的内存存储,这个结构是ziplist(压缩列表)。将所有的元素彼此紧挨着存储,也可以看作是数组结构。当数据量比较多的时间才会变成quicklist,因为普通的链表需要的附加指针空间(前后指针),所以Redis将链表和ziplist结合组成quicklist,将多个ziplist使用双向指针连接使用。 +![[Snipaste_2023-02-22_16-10-55.png]] +## 3.hash +Redis字典相当于Java的HashMap,属于无序字典,在数据结构上使用的是数组+链表也就是散列表结构。 +![[Snipaste_2023-02-22_16-10-55 4.png]] +### 3.1 常用操作 +![[Snipaste_2023-02-22_16-10-55 1.png]] +#### 获取字典中的所有值 +![[Snipaste_2023-02-22_16-10-55 2.png]] +#### 获取字典中的所有键值对 +![[Snipaste_2023-02-22_16-10-55 3.png]] +### 3.2 底层数据结构 +采用于HashMao相同的散列表结构,redis字段的值只能是字符串 +![[Snipaste_2023-02-22_16-10-55 5.png]] +#### 3.2.1 rehash +Redis为了追求高性能采用了渐进式rehash策略,可以不堵塞服务,但是需要牺牲空间,可以理解为空间换时间。渐进式rehash会在执行同时保留新旧两个hash结构,查询时会同时查询两个hash,然后再后续的定时任务以及hash操作指令中,循序渐进地将旧hash的内容迁移到新hash结构,当迁移完成就使用新hash代替。 +![[Snipaste_2023-02-22_16-10-55 6.png]] + +### 3.3优缺点 +hash结构可以结构化存储用户信息,相比于json存储,可以单独获取或修改某几个字段。如果以整个字符串形式保存的话只能一次性读取,比较浪费流量。 +缺点是存储消耗要高于单个字符。 + +## 4.set +相当于Java的HashSet,其内部键值对是无序且唯一的,内部实现相当于一个特殊的字典,字典中所有的value都是NULL +### 4.1 常用操作 +![[Snipaste_2023-02-22_16-10-55 7.png]] +#### 查询某个值是否存在 +![[Snipaste_2023-02-22_16-10-55 8.png]] +#### 获取长度 +![[Snipaste_2023-02-22_16-10-55 9.png]] +#### 弹出一个 +![[Snipaste_2023-02-22_16-10-55 10.png]] + +## 5.zset +类似于Java的SortedSet和HashMap结合体,set保证内部value的唯一性,另外可以给每个value赋予一个score代表排序权重,内部是使用‘跳跃列表’实现。 +![[Snipaste_2023-02-23_10-00-41.png]] +### 5.1 常用操作 +![[Snipaste_2023-02-23_10-00-41 1.png]] +#### 逆序输出 +![[Snipaste_2023-02-23_10-00-41 2.png]] +#### 统计 +![[Snipaste_2023-02-23_10-00-41 3.png]] +#### 获取指定value的score +![[Snipaste_2023-02-23_10-00-41 4.png]] +#### 排名 +![[Snipaste_2023-02-23_10-00-41 5.png]] +#### 删除value +![[Snipaste_2023-02-23_10-00-41 6.png]] +#### 根据score区间遍历 +0 2 表示分数区间 +![[Snipaste_2023-02-23_10-00-41 7.png]] + +### 5.2 底层数据结构(跳跃列表) +查看数据结构相关文档 \ No newline at end of file diff --git a/日常学习/中间件/redis/Hash相关命令.md b/日常学习/中间件/redis/Hash相关命令.md new file mode 100644 index 0000000..a82f984 --- /dev/null +++ b/日常学习/中间件/redis/Hash相关命令.md @@ -0,0 +1,3 @@ +[Redis 哈希(Hash)_redis教程](https://www.redis.net.cn/tutorial/3509.html) +![[Snipaste_2023-02-20_15-21-10 3.png]] +![[Snipaste_2023-02-20_15-21-10 2.png]] diff --git a/日常学习/中间件/redis/HyperLogLog.md b/日常学习/中间件/redis/HyperLogLog.md new file mode 100644 index 0000000..1afc80f --- /dev/null +++ b/日常学习/中间件/redis/HyperLogLog.md @@ -0,0 +1,5 @@ +用于不精确的去重统计,标准误差为0.81%,可以用于访问量统计或者其他不需要精确统计的场景 + +# 一、使用方法 +提供了pfadd、pfcount,第一个用于增加计数,第二个是获取计数 +![[Snipaste_2023-02-23_17-24-34 11.png]] \ No newline at end of file diff --git a/日常学习/中间件/redis/Key命令.md b/日常学习/中间件/redis/Key命令.md new file mode 100644 index 0000000..6342cb1 --- /dev/null +++ b/日常学习/中间件/redis/Key命令.md @@ -0,0 +1,4 @@ +![[Snipaste_2023-02-20_14-56-37 4.png]] + +![[Snipaste_2023-02-20_15-16-16.png]] + diff --git a/日常学习/中间件/redis/List相关命令.md b/日常学习/中间件/redis/List相关命令.md new file mode 100644 index 0000000..a16fc57 --- /dev/null +++ b/日常学习/中间件/redis/List相关命令.md @@ -0,0 +1,3 @@ +[Redis 列表(List)_redis教程](https://www.redis.net.cn/tutorial/3510.html) +![[Snipaste_2023-02-20_15-21-10 4.png]] +![[Snipaste_2023-02-20_15-21-10 5.png]] diff --git a/日常学习/中间件/redis/Redis命令.md b/日常学习/中间件/redis/Redis命令.md new file mode 100644 index 0000000..4299a61 --- /dev/null +++ b/日常学习/中间件/redis/Redis命令.md @@ -0,0 +1,9 @@ +1.本地打开redis +`redis-cli` + +2.远程打开redis +`redis-cli -h host -p port -a password` +例:`redis-cli -h 127.0.0.1 -p 6379 -a "mypass"` + + + diff --git a/日常学习/中间件/redis/Redis数据类型.md b/日常学习/中间件/redis/Redis数据类型.md new file mode 100644 index 0000000..1b9dae1 --- /dev/null +++ b/日常学习/中间件/redis/Redis数据类型.md @@ -0,0 +1,40 @@ +Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)。 + +# 一、String(字符串) +string是redis最基本的类型,你可以理解成与Memcached一模一样的类型,一个key对应一个value。 +string类型是二进制安全的。意思是redis的string可以包含任何数据。比如jpg图片或者序列化的对象 。 +string类型是Redis最基本的数据类型,一个键最大能存储512MB。 + +`1. redis 127.0.0.1:6379> SET name "redis.net.cn"` +`2. OK` +`3. redis 127.0.0.1:6379> GET name` +`4. "redis.net.cn"` +在以上实例中我们使用了 Redis 的 **SET** 和 **GET** 命令。键为 name,对应的值为redis.net.cn。 +**注意:**一个键最大能存储512MB。 + +# 二、Hash(哈希) +Redis hash 是一个键值对集合。 +Redis hash是一个string类型的field和value的映射表,hash特别适合用于存储对象。(一对多,一个key对应多个value) +![[Snipaste_2023-02-20_14-56-37.png]] +以上实例中 hash 数据类型存储了包含用户脚本信息的用户对象。 实例中我们使用了 Redis **HMSET, HEGTALL** 命令,**user:1** 为键值。 +每个 hash 可以存储 232 - 1 键值对(40多亿)。 + +# 三、List(列表) +Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素导列表的头部(左边)或者尾部(右边)。 +![[Snipaste_2023-02-20_14-56-37 1.png]] +列表最多可存储 232 - 1 元素 (4294967295, 每个列表可存储40多亿)。 + +# 四、Set(集合) +Redis的Set是string类型的无序集合。集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。 +### sadd 命令 +添加一个string元素到,key对应的set集合中,成功返回1,如果元素以及在集合中返回0,key对应的set不存在返回错误。 +![[Snipaste_2023-02-20_14-56-37 2.png]] +**注意:**以上实例中 rabitmq 添加了两次,但根据集合内元素的唯一性,第二次插入的元素将被忽略。 +集合中最大的成员数为 232 - 1 (4294967295, 每个集合可存储40多亿个成员)。 + +# 五、zset(有序集合) +Redis zset 和 set 一样也是string类型元素的集合,且不允许重复的成员。不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。zset的成员是唯一的,但分数(score)却可以重复。 + +### zadd 命令 +添加元素到集合,元素在集合中存在则更新对应score +![[Snipaste_2023-02-20_14-56-37 3.png]] diff --git a/日常学习/中间件/redis/Redis简介.md b/日常学习/中间件/redis/Redis简介.md new file mode 100644 index 0000000..9601be2 --- /dev/null +++ b/日常学习/中间件/redis/Redis简介.md @@ -0,0 +1,15 @@ +Redis 是完全开源免费的,遵守BSD协议,是一个高性能的key-value数据库。 +Redis 与其他 key - value 缓存产品有以下三个特点: +- Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用。 +- Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。 +- Redis支持数据的备份,即master-slave模式的数据备份。 + +## Redis优势 +- 性能极高 – Redis能读的速度是110000次/s,写的速度是81000次/s 。 +- 丰富的数据类型 – Redis支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作。 +- 原子 – Redis的所有操作都是原子性的,同时Redis还支持对几个操作全并后的原子性执行。 +- 丰富的特性 – Redis还支持 publish/subscribe, 通知, key 过期等等特性。 + +## Redis与其他key-value存储有什么不同? +- Redis有着更为复杂的数据结构并且提供对他们的原子性操作,这是一个不同于其他数据库的进化路径。Redis的数据类型都是基于基本数据结构的同时对程序员透明,无需进行额外的抽象。 +- Redis运行在内存中但是可以持久化到磁盘,所以在对不同数据集进行高速读写时需要权衡内存,应为数据量不能大于硬件内存。在内存数据库方面的另一个优点是, 相比在磁盘上相同的复杂的数据结构,在内存中操作起来非常简单,这样Redis可以做很多内部复杂性很强的事情。 同时,在磁盘格式方面他们是紧凑的以追加的方式产生的,因为他们并不需要进行随机访问。 diff --git a/日常学习/中间件/redis/Set相关命令.md b/日常学习/中间件/redis/Set相关命令.md new file mode 100644 index 0000000..505e21b --- /dev/null +++ b/日常学习/中间件/redis/Set相关命令.md @@ -0,0 +1,3 @@ +[Redis 集合(Set)_redis教程](https://www.redis.net.cn/tutorial/3511.html) +![[Snipaste_2023-02-20_15-21-10 6.png]] +![[Snipaste_2023-02-20_15-21-10 7.png]] diff --git a/日常学习/中间件/redis/String相关命令.md b/日常学习/中间件/redis/String相关命令.md new file mode 100644 index 0000000..a4bf98a --- /dev/null +++ b/日常学习/中间件/redis/String相关命令.md @@ -0,0 +1,3 @@ +[Redis 字符串(String)_redis教程](https://www.redis.net.cn/tutorial/3508.html) +![[Snipaste_2023-02-20_15-21-10.png]] +![[Snipaste_2023-02-20_15-21-10 1.png]] \ No newline at end of file diff --git a/日常学习/中间件/redis/zset相关命令.md b/日常学习/中间件/redis/zset相关命令.md new file mode 100644 index 0000000..e385ef8 --- /dev/null +++ b/日常学习/中间件/redis/zset相关命令.md @@ -0,0 +1,3 @@ +[Redis 有序集合(sorted set)_redis教程](https://www.redis.net.cn/tutorial/3512.html) +![[Snipaste_2023-02-20_15-21-10 8.png]] +![[Snipaste_2023-02-20_15-21-10 9.png]] \ No newline at end of file diff --git a/日常学习/中间件/redis/事务相关命令.md b/日常学习/中间件/redis/事务相关命令.md new file mode 100644 index 0000000..c368d04 --- /dev/null +++ b/日常学习/中间件/redis/事务相关命令.md @@ -0,0 +1,13 @@ +Redis 事务可以一次执行多个命令, 并且带有以下两个重要的保证: + +- 事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。 +- 事务是一个原子操作:事务中的命令要么全部被执行,要么全部都不执行。 + +一个事务从开始到执行会经历以下三个阶段: +- 开始事务。 +- 命令入队。 +- 执行事务。 + +![[Snipaste_2023-02-21_09-33-02.png]] + +![[Snipaste_2023-02-21_09-33-02 1.png]] \ No newline at end of file diff --git a/日常学习/中间件/redis/事务详解.md b/日常学习/中间件/redis/事务详解.md new file mode 100644 index 0000000..290593b --- /dev/null +++ b/日常学习/中间件/redis/事务详解.md @@ -0,0 +1,20 @@ +# 一、介绍 +redis提供了不完整的事务,有3个命令 +multi 开启事务,相当于begin +exec 执行事务,相当于commit +discard 回滚,相当于rollback + +使用方法如下图所示 +QUEUED是一个提示字符串,和OK相同,表示指令已经被服务器缓存到队列里了 +![[Snipaste_2023-02-24_14-42-21.png]] + + +# 二、原子性 +事务的原子性是指事务要么全部成功,要么全部失败,redis的事务不具备原子性,因为它在遇到指令执行失败后,后面的指令还会继续执行。 +redis仅仅是满足了事务隔离性中的串行化(当前执行的事务有着不被其他事务打断的权利) + +# 三、使用 +一般事务和管道是一起使用的,这样可以将多次IO操作压缩为单次IO操作。 +重点:多线程事务,redis提供了watch机制(一种乐观锁)用于解决并发修改问题 +watch会在事务开始之前盯住一个或多个关键变量,当事务执行时(服务器收到exec指令要顺序执行缓存的事务队列时),Redis会检查关键变量自watch之后是否被修改(包括当前事务所在的客户端)。如果关键变量被修改,exec指令就会返回NULL回复客户端事务执行失败,这个时候客户端可以选择重试。 +**禁止在multi和exec之间执行watch指令,必须在multi之前盯住关键变量** \ No newline at end of file diff --git a/日常学习/中间件/redis/位图bitmap.md b/日常学习/中间件/redis/位图bitmap.md new file mode 100644 index 0000000..6122507 --- /dev/null +++ b/日常学习/中间件/redis/位图bitmap.md @@ -0,0 +1,54 @@ +# 一、介绍 +举个例子:用户一年的签到记录,签了是1,没签是0,要记录365天。如果使用kv存储那么需要365条。当用户数量过亿的时候,需要的存储空间就太大了。 +为了解决这个问题redis提供了bitmap数据结构,这样每天的签到记录只占用1位,365天就是365位一共46个字节。位图的最小单位是比特(bit),每个bit的取值只能是0或1 +![[Snipaste_2023-02-23_10-00-41 21.png]] +位图的内容就是普通字符串,byte数组,1byte=8bit。redis的位数组是自动扩展,如果设置了某个偏移位置超出了现有的范围就会自动补零 +# 二、基本用法 + +**零存**: 使用setbit对位值进行逐个设置 +**整存**:使用字符串一次性填充所有位数组 +**零取**:使用getbit获取位数组的值 + +## 2.1 零存整取 +使用位操作符将字符串设置为hello,先得到hello的ASCII码 +![[Snipaste_2023-02-23_17-24-34.png]] +转换为8为ASCII码为 +h:01101000 +e:01100101 +l:01101100 +l:01101100 +o:01101111 +以h字符为例,只需要设置为1的位置,h字符有1/2/4位需要设置 +![[Snipaste_2023-02-23_17-24-34 1.png]] +命令如下 +![[Snipaste_2023-02-23_17-24-34 2.png]] +![[Snipaste_2023-02-23_17-24-34 3.png]] +## 2.2零存零取 +![[Snipaste_2023-02-23_17-24-34 4.png]] +## 2.3整存零取 +![[Snipaste_2023-02-23_17-24-34 5.png]] +## 2.4 统计和查找 +位图统计指令bitcount:用来统计指定位置范围内1的个数 + +位图查找指令bitpos:用来查找指定范围内出现的第一个0或1 + +例:可以通过bitcount统计用户一共签到了多少天,通过bitpos指令查找用户从哪一天开始第一次签到。如果指定了范围参数[start,end],就可以统计在某个时间范围内用户签到了多少天,用户自某天以后的哪天开始签到。**注意,start和end参数是字节索引,也就是指定的位范围必须是8的倍数,而不能任意指定。** +因为这个设计导致无法直接计算某个月内用户签到了多少天,而必须将这个月所覆盖的字节内容全部取出来在内存中统计 + +### bitcount +例: bitcount w 0 0 统计第一个字符中1的位数 +![[Snipaste_2023-02-23_17-24-34 6.png]] +### bitpos +例:bitpos w 0 第一个0位 +![[Snipaste_2023-02-23_17-24-34 7.png]] +bitpos w 1 0 1 从第一个字符算起,第一个1位 +![[Snipaste_2023-02-23_17-24-34 8.png]] +### bitfield +例:bitfield w get u4 0 从第一位开始取4个位,结果为6,对应4位二进制为0110 +![[Snipaste_2023-02-23_17-24-34 9.png]] +例:bitfield w get u3 2 从第三位开始取3个位,结果为5,对应3位编码为101,前面补零为0101=5 +![[Snipaste_2023-02-23_17-24-34 10.png]] + + +# 三、使用场景 ++ 用户签到统计 \ No newline at end of file diff --git a/日常学习/中间件/redis/分区.md b/日常学习/中间件/redis/分区.md new file mode 100644 index 0000000..fab7540 --- /dev/null +++ b/日常学习/中间件/redis/分区.md @@ -0,0 +1,34 @@ +分区是分割数据到多个Redis实例的处理过程,因此每个实例只保存key的一个子集。 + +### 分区的优势 + +- 通过利用多台计算机内存的和值,允许我们构造更大的数据库。 +- 通过多核和多台计算机,允许我们扩展计算能力;通过多台计算机和网络适配器,允许我们扩展网络带宽。 + +### 分区的不足 + +redis的一些特性在分区方面表现的不是很好: + +- 涉及多个key的操作通常是不被支持的。举例来说,当两个set映射到不同的redis实例上时,你就不能对这两个set执行交集操作。 +- 涉及多个key的redis事务不能使用。 +- 当使用分区时,数据处理较为复杂,比如你需要处理多个rdb/aof文件,并且从多个实例和主机备份持久化文件。 +- 增加或删除容量也比较复杂。redis集群大多数支持在运行时增加、删除节点的透明数据平衡的能力,但是类似于客户端分区、代理等其他系统则不支持这项特性。然而,一种叫做presharding的技术对此是有帮助的。 + +## 分区类型 + +Redis 有两种类型分区。 假设有4个Redis实例 R0,R1,R2,R3,和类似user:1,user:2这样的表示用户的多个key,对既定的key有多种不同方式来选择这个key存放在哪个实例中。也就是说,有不同的系统来映射某个key到某个Redis服务。 + +### 范围分区 + +最简单的分区方式是按范围分区,就是映射一定范围的对象到特定的Redis实例。 + +比如,ID从0到10000的用户会保存到实例R0,ID从10001到 20000的用户会保存到R1,以此类推。 + +这种方式是可行的,并且在实际中使用,不足就是要有一个区间范围到实例的映射表。这个表要被管理,同时还需要各 种对象的映射表,通常对Redis来说并非是好的方法。 + +### 哈希分区 + +另外一种分区方法是hash分区。这对任何key都适用,也无需是object_name:这种形式,像下面描述的一样简单: + +- 用一个hash函数将key转换为一个数字,比如使用crc32 hash函数。对key foobar执行crc32(foobar)会输出类似93024922的整数。 +- 对这个整数取模,将其转化为0-3之间的数字,就可以将这个整数映射到4个Redis实例中的一个了。93024922 % 4 = 2,就是说key foobar应该被存到R2实例中。注意:取模操作是取除的余数,通常在多种编程语言中用%操作符实现。 \ No newline at end of file diff --git a/日常学习/中间件/redis/小对象压缩ziplist.md b/日常学习/中间件/redis/小对象压缩ziplist.md new file mode 100644 index 0000000..68b3704 --- /dev/null +++ b/日常学习/中间件/redis/小对象压缩ziplist.md @@ -0,0 +1,8 @@ +Redis的ziplist是一个紧凑的字节数组结构,每个元素之间都是紧挨着。 +![[Snipaste_2023-02-24_14-42-21 1.png]] + ++ 如果存储的是hash结构,那么key和value会作为两个entry被相邻存储 ++ 如果是zset,value和score会作为两个entry被相邻存储 ++ 如果set里存储的是字符串,那么sadd会升级为hashtable结构(HashSet) + +# 存储界限 diff --git a/日常学习/中间件/redis/布隆过滤器.md b/日常学习/中间件/redis/布隆过滤器.md new file mode 100644 index 0000000..e527493 --- /dev/null +++ b/日常学习/中间件/redis/布隆过滤器.md @@ -0,0 +1,37 @@ +# 一、介绍 +可以把布隆过滤器理解为一个不怎么精确的set结构。当布隆过滤器判定某个值存在时,这个值可能不存在;当判定某个值不存在时,那肯定不存在。误判率大约为1%左右。 +# 二、使用方法及注意事项 +| 命令 | 用途 | +| ---------- | ------------------------ | +| bf.add | 添加元素 | +| bf.exists | 判断元素是否存在 | +| bf.madd | 批量添加元素 | +| bf.mexists | 一次查询多个元素是否存在 | + +![[Snipaste_2023-02-23_17-24-34 12.png]] + +## 显示创建布隆过滤器 +先说为什么需要显示创建,redis提供的默认设置错误率为0.01、预计放入的元素量为100,实际使用中我们的元素肯定不止100个,所以需要自定义创建,并且对于错误率的容忍度也不一样。 +redis提供了bf.reserver命令,格式如下 bf.reserver key error_rate initial_size +error_rate(错误率,错误率越低需要的空间越大) +initial_size(预计放入的元素数量,当实际数量超出这个数值时,误判率会上升,所以需要提前设置一个较大的数值避免超出导致误判率升高) +![[Snipaste_2023-02-23_17-24-34 13.png]] +# 三、原理 +布隆过滤器对应到Redis的数据结构里面就是一个大型的位数组和几个不一样的无偏hash函数。所谓无偏就是能够把元素的hash值算的比较均匀,让元素被hash映射到位数组中的位置比较随机。 +![[Snipaste_2023-02-24_09-52-40.png]] + +## 3.1 添加Key +会使用多个hash函数对Key进行Hash,算得一个整数索引值,然后对位数组长度进行取模得到一个下标,每个hash函数都会算的一个不同的下标。再把位数组的对应下标置为1,就完成了添加操作。 +## 3.2 判断Key是否存在 +和添加操作一样,先根据Hash计算下标,然后与位数组中这几个位置对比,是否为1,只要有一个为0,那么说明Key不存在。如果都是1,只能说明key可能存在,因为这些位置被置为1可能是因为其他key存在导致的。 +自定义布隆的initial_size参数与位数组长度有关,如果位数组比较稀疏,判断正确的概率就会很大,如果位数组比较拥挤,判断正确的概率就会降低。 +## 3.3 空间占用率估计 +布隆有两个参数,预计元素的数量m,错误率f。公式根据这两个输入得到两个输出,第一个输出是位数组长度l,第二个是hash函数的最佳数量k +k=0.7*(l/n) +f=0.6185^(l/n) ^表示次方计算,就是math.pow + +# 四、FAQ +1. 为什么使用布隆过滤器而不是直接使用set? + 因为set中会存储每个元素的内容,而布隆过滤器仅仅存储元素的指纹 +2. 如果redis不支持布隆过滤器怎么办? + python 版本 pyreBloom;java版本 orestes-bloomfilter或者hutool中提供的bloomfilter diff --git a/日常学习/中间件/redis/持久化.md b/日常学习/中间件/redis/持久化.md new file mode 100644 index 0000000..460cb23 --- /dev/null +++ b/日常学习/中间件/redis/持久化.md @@ -0,0 +1,15 @@ +# 一、介绍 +redis的持久化机制有2种,第一种是快照,第二种是AOF日志。快照是一次全量备份,AOF日志是增量备份。 +快照是内存数据的二进制序列化形式,在存储上非常紧凑;AOF日志记录的是内存数据修改的指令记录文本。AOF日志在长期的运行种会变得很大,如果重启时需要加载AOF日志重放,耗时很长,所以需要定期进行AOF重写,给日志瘦身。 +# 二、实现原理 +## 2.1 快照原理 +由于redis是单线程程序,为了持久化时不阻塞服务,使用了多进程COW(copy on write)机制实现快照功能。 +在持久化时会调用glibc的函数fork(fork/join机制)产生一个子进程,快照持久化完全由子进程处理,父进程继续处理客户端请求。 +子进程刚刚产生时,它和父进程共享内存里面的代码和数据段。子进程做数据持久化,不会修改现有的内存数据结构,它只是对数据结构进行遍历读取,然后序列化写入磁盘,此时的父进程还在处理客户端请求,也就是说**同一时间,父子进程的数据是有差异的**。 +COW机制进行数据段页面分离,当父进程对其中一个页面(page)的数据进行修改时,会将被共享的页面**复制**一份,然后父进程对这个复制的页修改。子进程相应的页是没有变化的,还是进程产生那一瞬间的数据。 +## 2.2 AOF原理 +AOF存储的是Redis服务器的顺序指令序列,AOF日志只记录对内存进行修改的指令记录 +当收到客户端修改指令后,进行参数校验、逻辑处理,如果没问题就将该指令写入AOF日志(先执行指令再存盘) +# 三、如何使用 +一般情况下不会单独使用上述两种方案,都是结合起来使用,称之为混合持久化。当重启时先加载快照内容,然后再重放增量AOF日志。 +混合持久化中将快照(rdb)文件的内容和增量AOF日志文件存在一起,这里的AOF日志不再是全量的日志,而是自持久化开始到结束这段时间内发生的增量操作日志,所以这部分AOF日志很小。 \ No newline at end of file diff --git a/日常学习/中间件/redis/管道.md b/日常学习/中间件/redis/管道.md new file mode 100644 index 0000000..3098958 --- /dev/null +++ b/日常学习/中间件/redis/管道.md @@ -0,0 +1,26 @@ +# 一、介绍 +管道是由客户端提供的一种加快存取效率的技术。 +如图所示,客户端将请求发给服务器,需要进过2个操作写->读,如果是多个操作就变成写->读->写->读 +![[Snipaste_2023-02-24_09-52-40 1.png]] + +此时如果调整读写顺序,变成写->写->读->读,两个连续的写操作和两个连续的读操作总共只会花费一次网络来回。 +管道的本质就是改变读写操作顺序来节省IO时间。管道中指令越多效果越好。 + +# 二、管道原理 +![[Snipaste_2023-02-24_09-52-40 2.png]] + +1. 客户段进程调用write将消息写到socket的send buffer中 +2. 客户端操作系统将发送缓冲的内容发送到网卡,网卡将数据通过路由送到服务器网卡 +3. 服务器操作系统将网卡内容放到socket的recv buffer中 +4. 服务器进程调用read从接收缓冲中读取消息进行处理 +5. 服务器进程调用write将响应消息写入到socket的send buffer中 +6. 服务器操作系统将发送缓冲的内容发送到网卡,网卡将数据通过路由送到客户端网卡 +7. 客户端器操作系统将网卡内容放到socket的recv buffer中 +8. 客户端进程调用read从接收缓冲中读取消息进行处理 +9. 结束 +5~8和1~4步骤一样,方向不同。一个是请求,一个是响应。 + +重点:write操作只负责将数据写到send buffer就返回了,剩下的事情由操作系统处理。对于redis.get(key)来说,write操作几乎没有耗时,直接写到发送缓冲就返回,而read需要走完上述的流程。 +对于管道来说,连续的write操作根本没有耗时,之后的第一个read操作会等待一个网络的来回开销,然后所有的响应消息就已经回到了recv buffer,后续的read操作就直接从recv buffer拿结果即可。 + +如果send buffer满了,那么就需要等待缓冲空出空间来,这就是写操作IO的真正耗时。 \ No newline at end of file diff --git a/日常学习/中间件/redis/队列实现.md b/日常学习/中间件/redis/队列实现.md new file mode 100644 index 0000000..0628e26 --- /dev/null +++ b/日常学习/中间件/redis/队列实现.md @@ -0,0 +1,8 @@ +# 一、异步消息队列 +list 可以作为异步队列使用,用rpush和lpop(右进左出)或lpush和rpop(左进右出) +![[Snipaste_2023-02-23_10-00-41 20.png]] +当队列为空时,如果一直pop会陷入pop死循环,可以采用与Future.get原理相同的阻塞读方法 **blpop/brpop** 其中b代表blocking +# 二、优先级队列 +使用zset实现优先级队列,score作为优先级分数 +# 三、延时队列 +使用zset实现延迟队列,将消息序列化成一个字符串作为zset的value,消息的时间作为到期时间score,然后用多个线程轮询zset获取到期的任务进行处理。 \ No newline at end of file diff --git a/日常学习/中间件/tomcat/tomcat原理.md b/日常学习/中间件/tomcat/tomcat原理.md index 5bbece8..16dae49 100644 --- a/日常学习/中间件/tomcat/tomcat原理.md +++ b/日常学习/中间件/tomcat/tomcat原理.md @@ -12,8 +12,7 @@ Catalina用于管理Server,它提供了三个方法load、start、stop用于 + await方法直接调用了Server的await方法,这个方法的作用是进入一个循环,让主线程不会退出 ### 3.Bootstrap - Bootstrap的作用类似一个CatalinaAdaptor,具体处理过程还是使用Catalina来完成,这么做的好处是可以把启动的入口和具体的管理类分开,从而可以很方便地创建出多种启动方式,每种启动方式只需要写一个相应的CatalinaAdaptor即可 - Bootstrap是tomcat的入口,启动tomcat就是调用Bootstrap的main方法。 +Bootstrap的作用类似一个CatalinaAdaptor,具体处理过程还是使用Catalina来完成,这么做的好处是可以把启动的入口和具体的管理类分开,从而可以很方便地创建出多种启动方式,每种启动方式只需要写一个相应的CatalinaAdaptor即可。Bootstrap是tomcat的入口,启动tomcat就是调用Bootstrap的main方法。 ### 4.启动流程图 ![[Snipaste_2023-02-13_20-13-01.png]] \ No newline at end of file diff --git a/日常学习/数据结构/跳跃列表(skiplist).md b/日常学习/数据结构/跳跃列表(skiplist).md new file mode 100644 index 0000000..c152710 --- /dev/null +++ b/日常学习/数据结构/跳跃列表(skiplist).md @@ -0,0 +1,61 @@ +# 一、介绍 +属于单链表的变体,解决了单链表查找慢的问题(单链表需要从头遍历并且无法使用二分查找因为没有指针或下标能找到中间位置) +跳跃列表的查找和插入都是O(logn) +# 二、原理 +## 2.1 创建 +由于链表无指针的特性导致不能实现快速查找,此时需要改进为跳跃列表,首先在头结点加入一个哨兵 +![[Snipaste_2023-02-23_10-00-41 8.png]] + +加入哨兵并把当前作为L0层 +![[Snipaste_2023-02-23_10-00-41 9.png]] + +开始构建L1层,从头遍历每个元素,每个元素有50%的概率上升到L1层,如图所示结点2、10、11、13、20、26上升为L1层元素,**同时保留在L0层的位置** +![[Snipaste_2023-02-23_10-00-41 10.png]] + +构建L2层,从头遍历L1层元素,过程与L0到L1相同,如图所示2、13、26从L1上升到L2层,**同时保留在L1层的位置**,根据概率论可以算出元素2来到L2层的概率为25%,50%(L1)*50%(L2)=25% +![[Snipaste_2023-02-23_10-00-41 11.png]] +构建L3层,从头遍历L2层元素,过程与L1到L2相同 +![[Snipaste_2023-02-23_10-00-41 12.png]] +跳跃的意义在于可以快速到达元素,例如从L2层可以之间从2到13只需要2步,而L1层从2到13需要4步,L0层需要5步。 +**跳跃列表的层数最好为Logn层** + +## 2.2 查找 +### 2.2.1 查找key=13 +1. 从顶层L3开始查找,从sentinel开始遍历(从头开始),到达第一个结点13 +2. 将key=13与元素相比较,结果相同说明已经找到该元素 +![[Snipaste_2023-02-23_10-00-41 13.png]] +### 2.2.2查找key=8 +1. 从顶层L3开始查找,从sentinel开始遍历(从头开始),到达第一个结点13,key<13,进入L2层 +2. 从L2层开始,到达第一个结点2,key>2,说明key在2的右边。到达L2层第二个结点13,key<13,进入L1层 +3. 从L1层开始,到达第一个结点2,key>2,说明key在2的右边。到达L1层第二个结点10,key<10,进入L0层 +4. 从L0层开始,依次遍历,找到key=8,结束 +![[Snipaste_2023-02-23_10-00-41 14.png]] + +### 2.2.3 查找key=20 +1. 从顶层L3开始查找,从sentinel开始遍历(从头开始),到达第一个结点13,key>13,由于L3层只有13这个结点所有进入L2层。 +2. 从L2层开始,由于key>13,所以从L2的13结点查找,到达26,key<26,说明key在13~26之间,向下进入L1层 +3. 从L1层13结点开始查找,向右找到Key=20,结束 +![[Snipaste_2023-02-23_10-00-41 15.png]] + +## 2.3 插入 +### 2.3.1 插入key=9 +1. 查找前先找到插入位置,过程看2.2节,如图所示找到L0层需要4个步骤 +![[Snipaste_2023-02-23_10-00-41 16.png]] +2. 记录每个步骤起点位置 +![[Snipaste_2023-02-23_10-00-41 17.png]] +3. 创建新结点9,高度随机,随机次数由(层数-1)决定 +![[Snipaste_2023-02-23_10-00-41 18.png]] +4. 将新结点与原有结点连接,此时新结点插入完毕,且进行了排序 +![[Snipaste_2023-02-23_10-00-41 19.png]] + +# 三、实践 +跳跃列表用于Redis的zset,作为有序去重队列使用 +# 四、总结 +特点: +1. 插入和查找都快 +2. 有些元素可以同时处于多层,例如13,同时处于L3、L2、L1、L0层 +3. 元素每次上升的概率都会乘以50%,例如从L0到L1为50%,L1到L2为50%,那么从L0到L2为25% +4. 列表中元素越多能够进入的层次越深,进入顶层的概率越大 +5. **一个元素如果位于顶层,那么从L0到顶层都会存在,例如结点13** + +跳跃列表是一个金字塔结构,从顶层到L0元素越来越少。如果查找的元素刚好位于顶层,那么效率就很高 \ No newline at end of file