Rumah > Artikel > pangkalan data > Perkara yang perlu dilakukan tentang ketidakkonsistenan sesi teragih dalam redis
Apa yang perlu dilakukan jika sesi yang diedarkan tidak konsisten? Artikel berikut akan memperkenalkan kepada anda penyelesaian kepada ketidakkonsistenan sesi yang diedarkan dalam redis. Saya harap ia akan membantu anda!
1.
Sesi ialah teknologi penjejakan sesi komunikasi antara pelanggan dan pelayan Pelayan dan pelanggan mengekalkan maklumat sesi asas keseluruhan komunikasi. [Cadangan berkaitan: Tutorial video Redis]
Apabila pelanggan mengakses pelayan buat kali pertama, pelayan akan membalas dengan sessionId dan menyimpannya secara setempat kuki, lawatan seterusnya akan meletakkan sessionId dalam kuki ke dalam pengepala permintaan untuk mengakses pelayan
Jika data yang sepadan tidak ditemui melalui sessionId ini, maka pelayan akan membuat satu. sessionId baharu dan memberi respons kepada pelanggan.
2.
Dalam aplikasi web pelayan tunggal, maklumat sesi hanya perlu disimpan dalam pelayan Ini adalah cara paling biasa kami berhubung dengannya dalam beberapa tahun lalu
Tetapi dalam beberapa tahun kebelakangan ini, dengan populariti sistem yang diedarkan, satu sistem tidak lagi dapat memenuhi keperluan berjuta-juta pengguna yang semakin meningkat Pelayan yang digunakan dalam kelompok telah digunakan dalam banyak syarikat
Apabila permintaan konkurensi tinggi tiba di pelayan, pengimbangan beban digunakan diedarkan kepada pelayan dalam kelompok, yang boleh menyebabkan berbilang permintaan daripada pengguna yang sama diedarkan ke pelayan berbeza dalam kelompok, dan data sesi tidak boleh diperoleh, jadi sesi perkongsian menjadi Satu persoalan.
3. Bagaimanakah pengelompokan perkhidmatan dilakukan?
4. Perbezaan antara pengimbangan beban nginx dan pengimbangan beban reben
5. Penyelesaian konsistensi sesi
1 >
Idea: Berbilang pelayan menyegerakkan sesi antara satu sama lain, supaya setiap pelayan mengandungi semua sesi
Kelebihan: Fungsi yang disokong oleh pelayan, aplikasi tidak tidak perlu mengubah suai kod
Kelemahan:
Penyegerakan sesi memerlukan penghantaran data, yang menduduki lebar jalur intranet dan mempunyai kelewatanKaedah storan pelanggan
Idea: Pelayan menyimpan sesi semua pengguna, yang menggunakan banyak memori Sesi boleh disimpan dalam kuki penyemak imbas Setiap hujung hanya perlu menyimpan data seorang pengguna
Kelebihan: Pelayan tidak perlu menyimpan
Kelemahan:
Setiap permintaan http membawa sesi, yang merangkumi lebar jalur rangkaian luaran data disimpan pada penghujung dan dalam Penghantaran rangkaian mempunyai risiko keselamatan seperti kebocoran, gangguan dan kecurian3. Konsistensi cincang proksi songsang
Idea: Untuk memastikan ketersediaan tinggi, pelayan mempunyai berbilang proksi terbalik yang berlebihan Bolehkah lapisan lakukan sesuatu supaya permintaan daripada pengguna yang sama dijamin mendarat pada pelayan yang sama?
Pilihan 1: Cincang proksi empat lapisanProksi terbalik menggunakan atribut perniagaan tertentu dalam protokol http untuk pencincangan, seperti sid, city_id, user_id, dll., yang boleh melaksanakan strategi cincangan dengan lebih fleksibel untuk memastikan permintaan daripada pengguna penyemak imbas yang sama jatuh pada pelayan yang sama .
Kelebihan:
Kelemahan:
Sesi umumnya mempunyai tempoh sah kedua-dua kelemahan itu boleh dianggap bersamaan dengan kegagalan sesi separa Secara umumnya, masalahnya tidak besar.
Sama ada cincangan empat lapisan atau cincang tujuh lapisan, saya secara peribadi mengesyorkan yang pertama: biarkan perisian profesional melakukan perkara profesional, dan proksi terbalik bertanggungjawab untuk pemajuan. Cuba untuk tidak memperkenalkan perniagaan lapisan aplikasi atribut melainkan anda perlu (seperti , kadangkala berbilang bilik komputer dan berbilang pelayan perlu dihalakan ke pelayan dalam bilik komputer yang berbeza mengikut atribut perniagaan).
Perbezaan antara pengimbangan beban empat lapisan dan tujuh lapisan
Storan terpusat bersatu bahagian belakang
Kelebihan:
Kelemahan: Panggilan rangkaian ditambah dan kod aplikasi perlu diubah suai
Untuk storan db atau cache, saya secara peribadi mengesyorkan yang terakhir: sesi Kekerapan membaca akan menjadi sangat tinggi, dan tekanan pangkalan data akan agak tinggi. Jika terdapat keperluan untuk ketersediaan tinggi sesi, cache boleh disediakan dengan sangat baik, tetapi dalam kebanyakan kes sesi boleh hilang, dan secara amnya tidak perlu mempertimbangkan ketersediaan tinggi.
Ringkasan
Kaedah biasa reka bentuk seni bina untuk memastikan konsistensi sesi:
6 Amalan kes: SpringSession redis menyelesaikan masalah ketidakkonsistenan sesi yang diedarkan
Langkah 1: Tambah pakej pergantungan bagi SpringSession dan redis
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-redis</artifactId> <version>1.4.7.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.session</groupId> <artifactId>spring-session-data-redis</artifactId> </dependency>
Langkah 2: Fail konfigurasi
# 为某个包目录下 设置日志 logging.level.com.ljw=debug # 设置session的存储方式,采用redis存储 spring.session.store-type=redis # session有效时长为10分钟 server.servlet.session.timeout=PT10M ## Redis 配置 ## Redis数据库索引(默认为0) spring.redis.database=0 ## Redis服务器地址 spring.redis.host=127.0.0.1 ## Redis服务器连接端口 spring.redis.port=6379 ## Redis服务器连接密码(默认为空) spring.redis.password=
Langkah 3: Konfigurasikan pemintas
@Configuration public class SessionConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new SecurityInterceptor()) //排除拦截的2个路径 .excludePathPatterns("/user/login") .excludePathPatterns("/user/logout") //拦截所有URL路径 .addPathPatterns("/**"); } }
@Configuration public class SecurityInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException { HttpSession session = request.getSession(); //验证当前session是否存在,存在返回true true代表能正常处理业务逻辑 if (session.getAttribute(session.getId()) != null){ log.info("session拦截器,session={},验证通过",session.getId()); return true; } //session不存在,返回false,并提示请重新登录。 response.setCharacterEncoding("UTF-8"); response.setContentType("application/json; charset=utf-8"); response.getWriter().write("请登录!!!!!"); log.info("session拦截器,session={},验证失败",session.getId()); return false; } }
Langkah 4: Pengawal
@RestController @RequestMapping(value = "/user") public class UserController { Map<String, User> userMap = new HashMap<>(); public UserController() { //初始化2个用户,用于模拟登录 User u1=new User(1,"user1","user1"); userMap.put("user1",u1); User u2=new User(2,"user2","user2"); userMap.put("user2",u2); } @GetMapping(value = "/login") public String login(String username, String password, HttpSession session) { //模拟数据库的查找 User user = this.userMap.get(username); if (user != null) { if (!password.equals(user.getPassword())) { return "用户名或密码错误!!!"; } else { session.setAttribute(session.getId(), user); log.info("登录成功{}",user); } } else { return "用户名或密码错误!!!"; } return "登录成功!!!"; } /** * 通过用户名查找用户 */ @GetMapping(value = "/find/{username}") public User find(@PathVariable String username) { User user=this.userMap.get(username); log.info("通过用户名={},查找出用户{}",username,user); return user; } /** *拿当前用户的session */ @GetMapping(value = "/session") public String session(HttpSession session) { log.info("当前用户的session={}",session.getId()); return session.getId(); } /** * 退出登录 */ @GetMapping(value = "/logout") public String logout(HttpSession session) { log.info("退出登录session={}",session.getId()); session.removeAttribute(session.getId()); return "成功退出!!"; } }
Langkah 5: Kelas entiti
@Data public class User implements Serializable{ private int id; private String username; private String password; public User(int id, String username, String password) { this.id = id; this.username = username; this.password = password; } }
Langkah 6: Ujian akses
Log dahulu :http://127.0.0.1:8080/user/login?username=user1&password=user1
Soal semulahttp://127.0.0.1:8080/user /find /user1
7 Analisis prinsip redis SpringSession
Langkah 1: Analisis. data redis bagi Struktur SpringSession
127.0.0.1:6379> keys * 1) "spring:session:sessions:9889ccfd-f4c9-41e5-b9ab-a77649a7bb6a" 2) "spring:session:sessions:expires:d3434f61-4d0a-4687-9070-610bd7790f3b" 3) "spring:session:expirations:1635413520000" 4) "spring:session:sessions:expires:9889ccfd-f4c9-41e5-b9ab-a77649a7bb6a" 5) "spring:session:expirations:1635412980000" 6) "spring:session:sessions:d3434f61-4d0a-4687-9070-610bd7790f3b"
Perkara biasa: 3 kekunci semuanya bermula dengan spring:session:, mewakili data redis SpringSession.
Jenis pertanyaan
127.0.0.1:6379> type spring:session:sessions:d3434f61-4d0a-4687-9070-610bd7790f3b hash
127.0.0.1:6379> hgetall spring:session:sessions:d3434f61-4d0a-4687-9070-610bd7790f3b // session的创建时间 1) "creationTime" 2) "\xac\xed\x00\x05sr\x00\x0ejava.lang.Long;\x8b\xe4\x90\xcc\x8f#\xdf\x02\x00\x01J\x00\x05valuexr\x00\x10java.lang.Number\x86\xac\x95\x1d\x0b\x94\xe0\x8b\x02\x00\x00xp\x00\x00\x01|\xc5\xdb\xecu" // sesson的属性,存储了user对象 3) "sessionAttr:d3434f61-4d0a-4687-9070-610bd7790f3b" 4) "\xac\xed\x00\x05sr\x00\x1ecom.ljw.redis.controller.User\x16\"_m\x1b\xa0W\x7f\x02\x00\x03I\x00\x02idL\x00\bpasswordt\x00\x12Ljava/lang/String;L\x00\busernameq\x00~\x00\x01xp\x00\x00\x00\x01t\x00\x05user1q\x00~\x00\x03" //最后的访问时间 5) "lastAccessedTime" 6) "\xac\xed\x00\x05sr\x00\x0ejava.lang.Long;\x8b\xe4\x90\xcc\x8f#\xdf\x02\x00\x01J\x00\x05valuexr\x00\x10java.lang.Number\x86\xac\x95\x1d\x0b\x94\xe0\x8b\x02\x00\x00xp\x00\x00\x01|\xc5\xe1\xc7\xed" //失效时间 100分钟 7) "maxInactiveInterval" 8) "\xac\xed\x00\x05sr\x00\x11java.lang.Integer\x12\xe2\xa0\xa4\xf7\x81\x878\x02\x00\x01I\x00\x05valuexr\x00\x10java.lang.Number\x86\xac\x95\x1d\x0b\x94\xe0\x8b\x02\x00\x00xp\x00\x00\x17p"
Langkah 2: Analisis strategi tamat tempoh redis SpringSession
Untuk data tamat tempoh , secara amnya terdapat tiga strategi pemadaman:
Pemadaman berjadual, iaitu semasa menetapkan masa tamat tempoh kunci, cipta pemasa dan padamkannya serta-merta apabila masa tamat tempoh kunci tiba. .
Pemadaman malas, iaitu, apabila mengakses kunci, ia dinilai sama ada kunci telah tamat tempoh, dan kemudian dipadamkan jika ia tamat tempoh, jika tidak, nilai kunci dikembalikan.
定期删除,即每隔一段时间,程序就对数据库进行一次检查,删除里面的过期键。至于要删除多少过期键,以及要检查多少个数据库,则由算法决定。
redis删除过期数据采用的是懒性删除+定期删除组合策略,也就是数据过期了并不会及时被删除。
但由于redis是单线程,并且redis对删除过期的key优先级很低;如果有大量的过期key,就会出现key已经过期但是未删除。
为了实现 session 过期的及时性,spring session 采用了定时删除+惰性删除的策略。
定时删除
127.0.0.1:6379> type spring:session:expirations:1635413520000 set 127.0.0.1:6379> smembers spring:session:expirations:1635413520000 1) "\xac\xed\x00\x05t\x00,expires:d3434f61-4d0a-4687-9070-610bd7790f3b"
2) "spring:session:sessions:expires:d3434f61-4d0a-4687-9070-610bd7790f3b" 3) "spring:session:expirations:1635413520000" 6) "spring:session:sessions:d3434f61-4d0a-4687-9070-610bd7790f3b"
惰性删除
127.0.0.1:6379> type spring:session:sessions:expires:d3434f61-4d0a-4687-9070-610bd7790f3b string 127.0.0.1:6379> get spring:session:sessions:expires:d3434f61-4d0a-4687-9070-610bd7790f3b "" 127.0.0.1:6379> ttl spring:session:sessions:expires:d3434f61-4d0a-4687-9070-610bd7790f3b (integer) 3143 127.0.0.1:6379>
2) "spring:session:sessions:expires:d3434f61-4d0a-4687-9070-610bd7790f3b" 3) "spring:session:expirations:1635413520000" 6) "spring:session:sessions:d3434f61-4d0a-4687-9070-610bd7790f3b"
更多编程相关知识,请访问:编程视频!!
Atas ialah kandungan terperinci Perkara yang perlu dilakukan tentang ketidakkonsistenan sesi teragih dalam redis. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!